X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fglapi%2Fglapi.c;h=c11760cf126b7e3dfe6f179981f00f9fd60a17fb;hb=dfb6c56ed85d7b11b6e7e9b0a5ec7eddb1162510;hp=944e77ac53868b8dec5d1682091f456c49bae6cd;hpb=0f710258c22ca1ee4a009162c4c63562a061306a;p=mesa.git diff --git a/src/mesa/glapi/glapi.c b/src/mesa/glapi/glapi.c index 944e77ac538..c11760cf126 100644 --- a/src/mesa/glapi/glapi.c +++ b/src/mesa/glapi/glapi.c @@ -1,10 +1,8 @@ -/* $Id: glapi.c,v 1.13 1999/12/15 15:02:30 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 3.3 + * Version: 6.3 * - * Copyright (C) 1999 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,728 +30,831 @@ * There are functions to set/get the current dispatch table for the * current thread and to manage registration/dispatch of dynamically * added extension functions. + * + * It's intended that this file and the other glapi*.[ch] files are + * flexible enough to be reused in several places: XFree86, DRI- + * based libGL.so, and perhaps the SGI SI. + * + * NOTE: There are no dependencies on Mesa in this code. + * + * Versions (API changes): + * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0 + * 2001/01/16 - added dispatch override feature for Mesa 3.5 + * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1. + * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints + * itself (using offset ~0). _glapi_add_entrypoint() can be + * called afterward and it'll fill in the correct dispatch + * offset. This allows DRI libGL to avoid probing for DRI + * drivers! No changes to the public glapi interface. */ -#include -#include /* to get NULL */ -#include +#include "glheader.h" #include "glapi.h" -#include "glapinoop.h" +#include "glapioffsets.h" +#include "glapitable.h" +#include "glthread.h" +/***** BEGIN NO-OP DISPATCH *****/ -/* Flag to indicate whether thread-safe dispatch is enabled */ -static GLboolean ThreadSafe = GL_FALSE; +static GLboolean WarnFlag = GL_FALSE; +static _glapi_warning_func warning_func; -/* This is used when thread safety is disabled */ -static struct _glapi_table *Dispatch = &__glapi_noop_table; +static void init_glapi_relocs(void); +static _glapi_proc generate_entrypoint(GLuint functionOffset); +static void fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset); -#if defined(THREADS) -#include "mthreads.h" -static MesaTSD mesa_dispatch_tsd; -static void mesa_dispatch_thread_init() { - MesaInitTSD(&mesa_dispatch_tsd); +/* + * Enable/disable printing of warning messages. + */ +PUBLIC void +_glapi_noop_enable_warnings(GLboolean enable) +{ + WarnFlag = enable; } -#endif +/* + * Register a callback function for reporting errors. + */ +PUBLIC void +_glapi_set_warning_func( _glapi_warning_func func ) +{ + warning_func = func; +} +static GLboolean +warn(void) +{ + if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) + && warning_func) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} -#define DISPATCH_SETUP \ - const struct _glapi_table *dispatch; \ - if (ThreadSafe) { \ - dispatch = _glapi_get_dispatch(); \ - } \ - else { \ - dispatch = Dispatch; \ + +#define KEYWORD1 static +#define KEYWORD2 GLAPIENTRY +#define NAME(func) NoOp##func + +#define F NULL + +#define DISPATCH(func, args, msg) \ + if (warn()) { \ + warning_func(NULL, "GL User Error: called without context: %s", #func); \ } -#define DISPATCH(FUNC, ARGS) (dispatch->FUNC) ARGS +#define RETURN_DISPATCH(func, args, msg) \ + if (warn()) { \ + warning_func(NULL, "GL User Error: called without context: %s", #func); \ + } \ + return 0 +#define DISPATCH_TABLE_NAME __glapi_noop_table +#define UNUSED_TABLE_NAME __unused_noop_functions -static GLuint MaxDispatchOffset = sizeof(struct _glapi_table) / sizeof(void *); -static GLboolean GetSizeCalled = GL_FALSE; +#define TABLE_ENTRY(name) (_glapi_proc) NoOp##name +static GLint NoOpUnused(void) +{ + if (warn()) { + warning_func(NULL, "GL User Error: calling extension function without a current context\n"); + } + return 0; +} -/* - * Set the global or per-thread dispatch table pointer. +#include "glapitemp.h" + +/***** END NO-OP DISPATCH *****/ + + + +/** + * \name Current dispatch and current context control variables + * + * Depending on whether or not multithreading is support, and the type of + * support available, several variables are used to store the current context + * pointer and the current dispatch table pointer. In the non-threaded case, + * the variables \c _glapi_Dispatch and \c _glapi_Context are used for this + * purpose. + * + * In the "normal" threaded case, the variables \c _glapi_Dispatch and + * \c _glapi_Context will be \c NULL if an application is detected as being + * multithreaded. Single-threaded applications will use \c _glapi_Dispatch + * and \c _glapi_Context just like the case without any threading support. + * When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state + * data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the + * static dispatch functions access these variables via \c _glapi_get_dispatch + * and \c _glapi_get_context. + * + * There is a race condition in setting \c _glapi_Dispatch to \c NULL. It is + * possible for the original thread to be setting it at the same instant a new + * thread, perhaps running on a different processor, is clearing it. Because + * of that, \c ThreadSafe, which can only ever be changed to \c GL_TRUE, is + * used to determine whether or not the application is multithreaded. + * + * In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context are + * hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch and + * \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and + * \c _glapi_Context be hardcoded to \c NULL maintains binary compatability + * between TLS enabled loaders and non-TLS DRI drivers. + */ +/*@{*/ +#if defined(GLX_USE_TLS) + +PUBLIC __thread struct _glapi_table * _glapi_tls_Dispatch + __attribute__((tls_model("initial-exec"))) + = (struct _glapi_table *) __glapi_noop_table; + +PUBLIC __thread void * _glapi_tls_Context + __attribute__((tls_model("initial-exec"))); + +PUBLIC const struct _glapi_table *_glapi_Dispatch = NULL; +PUBLIC const void *_glapi_Context = NULL; + +#else + +#if defined(THREADS) + +static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */ +_glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */ +static _glthread_TSD ContextTSD; /**< Per-thread context pointer */ + +#endif /* defined(THREADS) */ + +PUBLIC struct _glapi_table *_glapi_Dispatch = + (struct _glapi_table *) __glapi_noop_table; +PUBLIC void *_glapi_Context = NULL; + +#endif /* defined(GLX_USE_TLS) */ +/*@}*/ + + +/** + * 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; +} + + + +/** + * We should call this periodically from a function such as glXMakeCurrent + * in order to test if multiple threads are being used. */ void -_glapi_set_dispatch(struct _glapi_table *dispatch) +_glapi_check_multithread(void) { - if (!dispatch) { - /* use the no-op functions */ - dispatch = &__glapi_noop_table; +#if defined(THREADS) && !defined(GLX_USE_TLS) + if (!ThreadSafe) { + static unsigned long knownID; + static GLboolean firstCall = GL_TRUE; + if (firstCall) { + knownID = _glthread_GetID(); + firstCall = GL_FALSE; + } + else if (knownID != _glthread_GetID()) { + ThreadSafe = GL_TRUE; + _glapi_set_dispatch(NULL); + } } -#ifdef DEBUG - else { - _glapi_check_table(dispatch); + else if (!_glapi_get_dispatch()) { + /* make sure that this thread's dispatch pointer isn't null */ + _glapi_set_dispatch(NULL); } #endif - -#if defined(THREADS) - MesaSetTSD(&mesa_dispatch_tsd, (void*) dispatch, mesa_dispatch_thread_init); -#else - Dispatch = dispatch; -#endif } -/* - * Get the global or per-thread dispatch table pointer. + +/** + * Set the current context pointer for this thread. + * The context pointer is an opaque type which should be cast to + * void from the real context pointer type. */ -struct _glapi_table * -_glapi_get_dispatch(void) +PUBLIC void +_glapi_set_context(void *context) { -#if defined(THREADS) - /* return this thread's dispatch pointer */ - return (struct _glapi_table *) MesaGetTSD(&mesa_dispatch_tsd); + (void) __unused_noop_functions; /* silence a warning */ +#if defined(GLX_USE_TLS) + _glapi_tls_Context = context; +#elif defined(THREADS) + _glthread_SetTSD(&ContextTSD, context); + _glapi_Context = (ThreadSafe) ? NULL : context; #else - return Dispatch; + _glapi_Context = context; #endif } -void -_glapi_enable_thread_safety(void) +/** + * Get the current context pointer for this thread. + * The context pointer is an opaque type which should be cast from + * void to the real context pointer type. + */ +PUBLIC void * +_glapi_get_context(void) { - ThreadSafe = GL_TRUE; +#if defined(GLX_USE_TLS) + return _glapi_tls_Context; +#elif defined(THREADS) + if (ThreadSafe) { + return _glthread_GetTSD(&ContextTSD); + } + else { + return _glapi_Context; + } +#else + return _glapi_Context; +#endif } -/* - * Return size of dispatch table struct as number of functions (or - * slots). +/** + * Set the global or per-thread dispatch table pointer. */ -GLuint -_glapi_get_dispatch_table_size(void) +PUBLIC void +_glapi_set_dispatch(struct _glapi_table *dispatch) { - /* return sizeof(struct _glapi_table) / sizeof(void *);*/ - GetSizeCalled = GL_TRUE; - return MaxDispatchOffset + 1; +#if defined(PTHREADS) || defined(GLX_USE_TLS) + static pthread_once_t once_control = PTHREAD_ONCE_INIT; + + + pthread_once( & once_control, init_glapi_relocs ); +#endif + + if (!dispatch) { + /* use the no-op functions */ + dispatch = (struct _glapi_table *) __glapi_noop_table; + } +#ifdef DEBUG + else { + _glapi_check_table(dispatch); + } +#endif + +#if defined(GLX_USE_TLS) + _glapi_tls_Dispatch = dispatch; +#elif defined(THREADS) + _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch); + _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch; +#else /*THREADS*/ + _glapi_Dispatch = dispatch; +#endif /*THREADS*/ } -/* - * Get API dispatcher version string. - * XXX this isn't well defined yet. +/** + * Return pointer to current dispatch table for calling thread. */ -const char * -_glapi_get_version(void) +PUBLIC struct _glapi_table * +_glapi_get_dispatch(void) { - return "1.2"; -} + struct _glapi_table * api; + +#if defined(GLX_USE_TLS) + api = _glapi_tls_Dispatch; +#elif defined(THREADS) + api = (ThreadSafe) + ? (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD) + : _glapi_Dispatch; +#else + api = _glapi_Dispatch; +#endif + assert( api != NULL ); + return api; +} -struct name_address_pair { - const char *Name; - GLvoid *Address; -}; -static struct name_address_pair static_functions[] = { - { "glAccum", (GLvoid *) glAccum }, - { "glAlphaFunc", (GLvoid *) glAlphaFunc }, - { "glBegin", (GLvoid *) glBegin }, - { "glBitmap", (GLvoid *) glBitmap }, - { "glAccum", (GLvoid *) glAccum }, - { "glAlphaFunc", (GLvoid *) glAlphaFunc }, - { "glBegin", (GLvoid *) glBegin }, - { "glBitmap", (GLvoid *) glBitmap }, - { "glBlendFunc", (GLvoid *) glBlendFunc }, - { "glCallList", (GLvoid *) glCallList }, - { "glCallLists", (GLvoid *) glCallLists }, - { "glClear", (GLvoid *) glClear }, - { "glClearAccum", (GLvoid *) glClearAccum }, - { "glClearColor", (GLvoid *) glClearColor }, - { "glClearDepth", (GLvoid *) glClearDepth }, - { "glClearIndex", (GLvoid *) glClearIndex }, - { "glClearStencil", (GLvoid *) glClearStencil }, - { "glClipPlane", (GLvoid *) glClipPlane }, - { "glColor3b", (GLvoid *) glColor3b }, - { "glColor3bv", (GLvoid *) glColor3bv }, - { "glColor3d", (GLvoid *) glColor3d }, - { "glColor3dv", (GLvoid *) glColor3dv }, - { "glColor3f", (GLvoid *) glColor3f }, - { "glColor3fv", (GLvoid *) glColor3fv }, - { "glColor3i", (GLvoid *) glColor3i }, - { "glColor3iv", (GLvoid *) glColor3iv }, - { "glColor3s", (GLvoid *) glColor3s }, - { "glColor3sv", (GLvoid *) glColor3sv }, - { "glColor3ub", (GLvoid *) glColor3ub }, - { "glColor3ubv", (GLvoid *) glColor3ubv }, - { "glColor3ui", (GLvoid *) glColor3ui }, - { "glColor3uiv", (GLvoid *) glColor3uiv }, - { "glColor3us", (GLvoid *) glColor3us }, - { "glColor3usv", (GLvoid *) glColor3usv }, - { "glColor4b", (GLvoid *) glColor4b }, - { "glColor4bv", (GLvoid *) glColor4bv }, - { "glColor4d", (GLvoid *) glColor4d }, - { "glColor4dv", (GLvoid *) glColor4dv }, - { "glColor4f", (GLvoid *) glColor4f }, - { "glColor4fv", (GLvoid *) glColor4fv }, - { "glColor4i", (GLvoid *) glColor4i }, - { "glColor4iv", (GLvoid *) glColor4iv }, - { "glColor4s", (GLvoid *) glColor4s }, - { "glColor4sv", (GLvoid *) glColor4sv }, - { "glColor4ub", (GLvoid *) glColor4ub }, - { "glColor4ubv", (GLvoid *) glColor4ubv }, - { "glColor4ui", (GLvoid *) glColor4ui }, - { "glColor4uiv", (GLvoid *) glColor4uiv }, - { "glColor4us", (GLvoid *) glColor4us }, - { "glColor4usv", (GLvoid *) glColor4usv }, - { "glColorMask", (GLvoid *) glColorMask }, - { "glColorMaterial", (GLvoid *) glColorMaterial }, - { "glCopyPixels", (GLvoid *) glCopyPixels }, - { "glCullFace", (GLvoid *) glCullFace }, - { "glDeleteLists", (GLvoid *) glDeleteLists }, - { "glDepthFunc", (GLvoid *) glDepthFunc }, - { "glDepthMask", (GLvoid *) glDepthMask }, - { "glDepthRange", (GLvoid *) glDepthRange }, - { "glDisable", (GLvoid *) glDisable }, - { "glDrawBuffer", (GLvoid *) glDrawBuffer }, - { "glDrawPixels", (GLvoid *) glDrawPixels }, - { "glEdgeFlag", (GLvoid *) glEdgeFlag }, - { "glEdgeFlagv", (GLvoid *) glEdgeFlagv }, - { "glEnable", (GLvoid *) glEnable }, - { "glEnd", (GLvoid *) glEnd }, - { "glEndList", (GLvoid *) glEndList }, - { "glEvalCoord1d", (GLvoid *) glEvalCoord1d }, - { "glEvalCoord1dv", (GLvoid *) glEvalCoord1dv }, - { "glEvalCoord1f", (GLvoid *) glEvalCoord1f }, - { "glEvalCoord1fv", (GLvoid *) glEvalCoord1fv }, - { "glEvalCoord2d", (GLvoid *) glEvalCoord2d }, - { "glEvalCoord2dv", (GLvoid *) glEvalCoord2dv }, - { "glEvalCoord2f", (GLvoid *) glEvalCoord2f }, - { "glEvalCoord2fv", (GLvoid *) glEvalCoord2fv }, - { "glEvalMesh1", (GLvoid *) glEvalMesh1 }, - { "glEvalMesh2", (GLvoid *) glEvalMesh2 }, - { "glEvalPoint1", (GLvoid *) glEvalPoint1 }, - { "glEvalPoint2", (GLvoid *) glEvalPoint2 }, - { "glFeedbackBuffer", (GLvoid *) glFeedbackBuffer }, - { "glFinish", (GLvoid *) glFinish }, - { "glFlush", (GLvoid *) glFlush }, - { "glFogf", (GLvoid *) glFogf }, - { "glFogfv", (GLvoid *) glFogfv }, - { "glFogi", (GLvoid *) glFogi }, - { "glFogiv", (GLvoid *) glFogiv }, - { "glFrontFace", (GLvoid *) glFrontFace }, - { "glFrustum", (GLvoid *) glFrustum }, - { "glGenLists", (GLvoid *) glGenLists }, - { "glGetBooleanv", (GLvoid *) glGetBooleanv }, - { "glGetClipPlane", (GLvoid *) glGetClipPlane }, - { "glGetDoublev", (GLvoid *) glGetDoublev }, - { "glGetError", (GLvoid *) glGetError }, - { "glGetFloatv", (GLvoid *) glGetFloatv }, - { "glGetIntegerv", (GLvoid *) glGetIntegerv }, - { "glGetLightfv", (GLvoid *) glGetLightfv }, - { "glGetLightiv", (GLvoid *) glGetLightiv }, - { "glGetMapdv", (GLvoid *) glGetMapdv }, - { "glGetMapfv", (GLvoid *) glGetMapfv }, - { "glGetMapiv", (GLvoid *) glGetMapiv }, - { "glGetMaterialfv", (GLvoid *) glGetMaterialfv }, - { "glGetMaterialiv", (GLvoid *) glGetMaterialiv }, - { "glGetPixelMapfv", (GLvoid *) glGetPixelMapfv }, - { "glGetPixelMapuiv", (GLvoid *) glGetPixelMapuiv }, - { "glGetPixelMapusv", (GLvoid *) glGetPixelMapusv }, - { "glGetPolygonStipple", (GLvoid *) glGetPolygonStipple }, - { "glGetString", (GLvoid *) glGetString }, - { "glGetTexEnvfv", (GLvoid *) glGetTexEnvfv }, - { "glGetTexEnviv", (GLvoid *) glGetTexEnviv }, - { "glGetTexGendv", (GLvoid *) glGetTexGendv }, - { "glGetTexGenfv", (GLvoid *) glGetTexGenfv }, - { "glGetTexGeniv", (GLvoid *) glGetTexGeniv }, - { "glGetTexImage", (GLvoid *) glGetTexImage }, - { "glGetTexLevelParameterfv", (GLvoid *) glGetTexLevelParameterfv }, - { "glGetTexLevelParameteriv", (GLvoid *) glGetTexLevelParameteriv }, - { "glGetTexParameterfv", (GLvoid *) glGetTexParameterfv }, - { "glGetTexParameteriv", (GLvoid *) glGetTexParameteriv }, - { "glHint", (GLvoid *) glHint }, - { "glIndexMask", (GLvoid *) glIndexMask }, - { "glIndexd", (GLvoid *) glIndexd }, - { "glIndexdv", (GLvoid *) glIndexdv }, - { "glIndexf", (GLvoid *) glIndexf }, - { "glIndexfv", (GLvoid *) glIndexfv }, - { "glIndexi", (GLvoid *) glIndexi }, - { "glIndexiv", (GLvoid *) glIndexiv }, - { "glIndexs", (GLvoid *) glIndexs }, - { "glIndexsv", (GLvoid *) glIndexsv }, - { "glInitNames", (GLvoid *) glInitNames }, - { "glIsEnabled", (GLvoid *) glIsEnabled }, - { "glIsList", (GLvoid *) glIsList }, - { "glLightModelf", (GLvoid *) glLightModelf }, - { "glLightModelfv", (GLvoid *) glLightModelfv }, - { "glLightModeli", (GLvoid *) glLightModeli }, - { "glLightModeliv", (GLvoid *) glLightModeliv }, - { "glLightf", (GLvoid *) glLightf }, - { "glLightfv", (GLvoid *) glLightfv }, - { "glLighti", (GLvoid *) glLighti }, - { "glLightiv", (GLvoid *) glLightiv }, - { "glLineStipple", (GLvoid *) glLineStipple }, - { "glLineWidth", (GLvoid *) glLineWidth }, - { "glListBase", (GLvoid *) glListBase }, - { "glLoadIdentity", (GLvoid *) glLoadIdentity }, - { "glLoadMatrixd", (GLvoid *) glLoadMatrixd }, - { "glLoadMatrixf", (GLvoid *) glLoadMatrixf }, - { "glLoadName", (GLvoid *) glLoadName }, - { "glLogicOp", (GLvoid *) glLogicOp }, - { "glMap1d", (GLvoid *) glMap1d }, - { "glMap1f", (GLvoid *) glMap1f }, - { "glMap2d", (GLvoid *) glMap2d }, - { "glMap2f", (GLvoid *) glMap2f }, - { "glMapGrid1d", (GLvoid *) glMapGrid1d }, - { "glMapGrid1f", (GLvoid *) glMapGrid1f }, - { "glMapGrid2d", (GLvoid *) glMapGrid2d }, - { "glMapGrid2f", (GLvoid *) glMapGrid2f }, - { "glMaterialf", (GLvoid *) glMaterialf }, - { "glMaterialfv", (GLvoid *) glMaterialfv }, - { "glMateriali", (GLvoid *) glMateriali }, - { "glMaterialiv", (GLvoid *) glMaterialiv }, - { "glMatrixMode", (GLvoid *) glMatrixMode }, - { "glMultMatrixd", (GLvoid *) glMultMatrixd }, - { "glMultMatrixf", (GLvoid *) glMultMatrixf }, - { "glNewList", (GLvoid *) glNewList }, - { "glNormal3b", (GLvoid *) glNormal3b }, - { "glNormal3bv", (GLvoid *) glNormal3bv }, - { "glNormal3d", (GLvoid *) glNormal3d }, - { "glNormal3dv", (GLvoid *) glNormal3dv }, - { "glNormal3f", (GLvoid *) glNormal3f }, - { "glNormal3fv", (GLvoid *) glNormal3fv }, - { "glNormal3i", (GLvoid *) glNormal3i }, - { "glNormal3iv", (GLvoid *) glNormal3iv }, - { "glNormal3s", (GLvoid *) glNormal3s }, - { "glNormal3sv", (GLvoid *) glNormal3sv }, - { "glOrtho", (GLvoid *) glOrtho }, - { "glPassThrough", (GLvoid *) glPassThrough }, - { "glPixelMapfv", (GLvoid *) glPixelMapfv }, - { "glPixelMapuiv", (GLvoid *) glPixelMapuiv }, - { "glPixelMapusv", (GLvoid *) glPixelMapusv }, - { "glPixelStoref", (GLvoid *) glPixelStoref }, - { "glPixelStorei", (GLvoid *) glPixelStorei }, - { "glPixelTransferf", (GLvoid *) glPixelTransferf }, - { "glPixelTransferi", (GLvoid *) glPixelTransferi }, - { "glPixelZoom", (GLvoid *) glPixelZoom }, - { "glPointSize", (GLvoid *) glPointSize }, - { "glPolygonMode", (GLvoid *) glPolygonMode }, - { "glPolygonOffset", (GLvoid *) glPolygonOffset }, - { "glPolygonStipple", (GLvoid *) glPolygonStipple }, - { "glPopAttrib", (GLvoid *) glPopAttrib }, - { "glPopMatrix", (GLvoid *) glPopMatrix }, - { "glPopName", (GLvoid *) glPopName }, - { "glPushAttrib", (GLvoid *) glPushAttrib }, - { "glPushMatrix", (GLvoid *) glPushMatrix }, - { "glPushName", (GLvoid *) glPushName }, - { "glRasterPos2d", (GLvoid *) glRasterPos2d }, - { "glRasterPos2dv", (GLvoid *) glRasterPos2dv }, - { "glRasterPos2f", (GLvoid *) glRasterPos2f }, - { "glRasterPos2fv", (GLvoid *) glRasterPos2fv }, - { "glRasterPos2i", (GLvoid *) glRasterPos2i }, - { "glRasterPos2iv", (GLvoid *) glRasterPos2iv }, - { "glRasterPos2s", (GLvoid *) glRasterPos2s }, - { "glRasterPos2sv", (GLvoid *) glRasterPos2sv }, - { "glRasterPos3d", (GLvoid *) glRasterPos3d }, - { "glRasterPos3dv", (GLvoid *) glRasterPos3dv }, - { "glRasterPos3f", (GLvoid *) glRasterPos3f }, - { "glRasterPos3fv", (GLvoid *) glRasterPos3fv }, - { "glRasterPos3i", (GLvoid *) glRasterPos3i }, - { "glRasterPos3iv", (GLvoid *) glRasterPos3iv }, - { "glRasterPos3s", (GLvoid *) glRasterPos3s }, - { "glRasterPos3sv", (GLvoid *) glRasterPos3sv }, - { "glRasterPos4d", (GLvoid *) glRasterPos4d }, - { "glRasterPos4dv", (GLvoid *) glRasterPos4dv }, - { "glRasterPos4f", (GLvoid *) glRasterPos4f }, - { "glRasterPos4fv", (GLvoid *) glRasterPos4fv }, - { "glRasterPos4i", (GLvoid *) glRasterPos4i }, - { "glRasterPos4iv", (GLvoid *) glRasterPos4iv }, - { "glRasterPos4s", (GLvoid *) glRasterPos4s }, - { "glRasterPos4sv", (GLvoid *) glRasterPos4sv }, - { "glReadBuffer", (GLvoid *) glReadBuffer }, - { "glReadPixels", (GLvoid *) glReadPixels }, - { "glRectd", (GLvoid *) glRectd }, - { "glRectdv", (GLvoid *) glRectdv }, - { "glRectf", (GLvoid *) glRectf }, - { "glRectfv", (GLvoid *) glRectfv }, - { "glRecti", (GLvoid *) glRecti }, - { "glRectiv", (GLvoid *) glRectiv }, - { "glRects", (GLvoid *) glRects }, - { "glRectsv", (GLvoid *) glRectsv }, - { "glRenderMode", (GLvoid *) glRenderMode }, - { "glRotated", (GLvoid *) glRotated }, - { "glRotatef", (GLvoid *) glRotatef }, - { "glScaled", (GLvoid *) glScaled }, - { "glScalef", (GLvoid *) glScalef }, - { "glScissor", (GLvoid *) glScissor }, - { "glSelectBuffer", (GLvoid *) glSelectBuffer }, - { "glShadeModel", (GLvoid *) glShadeModel }, - { "glStencilFunc", (GLvoid *) glStencilFunc }, - { "glStencilMask", (GLvoid *) glStencilMask }, - { "glStencilOp", (GLvoid *) glStencilOp }, - { "glTexCoord1d", (GLvoid *) glTexCoord1d }, - { "glTexCoord1dv", (GLvoid *) glTexCoord1dv }, - { "glTexCoord1f", (GLvoid *) glTexCoord1f }, - { "glTexCoord1fv", (GLvoid *) glTexCoord1fv }, - { "glTexCoord1i", (GLvoid *) glTexCoord1i }, - { "glTexCoord1iv", (GLvoid *) glTexCoord1iv }, - { "glTexCoord1s", (GLvoid *) glTexCoord1s }, - { "glTexCoord1sv", (GLvoid *) glTexCoord1sv }, - { "glTexCoord2d", (GLvoid *) glTexCoord2d }, - { "glTexCoord2dv", (GLvoid *) glTexCoord2dv }, - { "glTexCoord2f", (GLvoid *) glTexCoord2f }, - { "glTexCoord2fv", (GLvoid *) glTexCoord2fv }, - { "glTexCoord2i", (GLvoid *) glTexCoord2i }, - { "glTexCoord2iv", (GLvoid *) glTexCoord2iv }, - { "glTexCoord2s", (GLvoid *) glTexCoord2s }, - { "glTexCoord2sv", (GLvoid *) glTexCoord2sv }, - { "glTexCoord3d", (GLvoid *) glTexCoord3d }, - { "glTexCoord3dv", (GLvoid *) glTexCoord3dv }, - { "glTexCoord3f", (GLvoid *) glTexCoord3f }, - { "glTexCoord3fv", (GLvoid *) glTexCoord3fv }, - { "glTexCoord3i", (GLvoid *) glTexCoord3i }, - { "glTexCoord3iv", (GLvoid *) glTexCoord3iv }, - { "glTexCoord3s", (GLvoid *) glTexCoord3s }, - { "glTexCoord3sv", (GLvoid *) glTexCoord3sv }, - { "glTexCoord4d", (GLvoid *) glTexCoord4d }, - { "glTexCoord4dv", (GLvoid *) glTexCoord4dv }, - { "glTexCoord4f", (GLvoid *) glTexCoord4f }, - { "glTexCoord4fv", (GLvoid *) glTexCoord4fv }, - { "glTexCoord4i", (GLvoid *) glTexCoord4i }, - { "glTexCoord4iv", (GLvoid *) glTexCoord4iv }, - { "glTexCoord4s", (GLvoid *) glTexCoord4s }, - { "glTexCoord4sv", (GLvoid *) glTexCoord4sv }, - { "glTexEnvf", (GLvoid *) glTexEnvf }, - { "glTexEnvfv", (GLvoid *) glTexEnvfv }, - { "glTexEnvi", (GLvoid *) glTexEnvi }, - { "glTexEnviv", (GLvoid *) glTexEnviv }, - { "glTexGend", (GLvoid *) glTexGend }, - { "glTexGendv", (GLvoid *) glTexGendv }, - { "glTexGenf", (GLvoid *) glTexGenf }, - { "glTexGenfv", (GLvoid *) glTexGenfv }, - { "glTexGeni", (GLvoid *) glTexGeni }, - { "glTexGeniv", (GLvoid *) glTexGeniv }, - { "glTexImage1D", (GLvoid *) glTexImage1D }, - { "glTexImage2D", (GLvoid *) glTexImage2D }, - { "glTexParameterf", (GLvoid *) glTexParameterf }, - { "glTexParameterfv", (GLvoid *) glTexParameterfv }, - { "glTexParameteri", (GLvoid *) glTexParameteri }, - { "glTexParameteriv", (GLvoid *) glTexParameteriv }, - { "glTranslated", (GLvoid *) glTranslated }, - { "glTranslatef", (GLvoid *) glTranslatef }, - { "glVertex2d", (GLvoid *) glVertex2d }, - { "glVertex2dv", (GLvoid *) glVertex2dv }, - { "glVertex2f", (GLvoid *) glVertex2f }, - { "glVertex2fv", (GLvoid *) glVertex2fv }, - { "glVertex2i", (GLvoid *) glVertex2i }, - { "glVertex2iv", (GLvoid *) glVertex2iv }, - { "glVertex2s", (GLvoid *) glVertex2s }, - { "glVertex2sv", (GLvoid *) glVertex2sv }, - { "glVertex3d", (GLvoid *) glVertex3d }, - { "glVertex3dv", (GLvoid *) glVertex3dv }, - { "glVertex3f", (GLvoid *) glVertex3f }, - { "glVertex3fv", (GLvoid *) glVertex3fv }, - { "glVertex3i", (GLvoid *) glVertex3i }, - { "glVertex3iv", (GLvoid *) glVertex3iv }, - { "glVertex3s", (GLvoid *) glVertex3s }, - { "glVertex3sv", (GLvoid *) glVertex3sv }, - { "glVertex4d", (GLvoid *) glVertex4d }, - { "glVertex4dv", (GLvoid *) glVertex4dv }, - { "glVertex4f", (GLvoid *) glVertex4f }, - { "glVertex4fv", (GLvoid *) glVertex4fv }, - { "glVertex4i", (GLvoid *) glVertex4i }, - { "glVertex4iv", (GLvoid *) glVertex4iv }, - { "glVertex4s", (GLvoid *) glVertex4s }, - { "glVertex4sv", (GLvoid *) glVertex4sv }, - { "glViewport", (GLvoid *) glViewport }, - -#ifdef _GLAPI_VERSION_1_1 - { "glAreTexturesResident", (GLvoid *) glAreTexturesResident }, - { "glArrayElement", (GLvoid *) glArrayElement }, - { "glBindTexture", (GLvoid *) glBindTexture }, - { "glColorPointer", (GLvoid *) glColorPointer }, - { "glCopyTexImage1D", (GLvoid *) glCopyTexImage1D }, - { "glCopyTexImage2D", (GLvoid *) glCopyTexImage2D }, - { "glCopyTexSubImage1D", (GLvoid *) glCopyTexSubImage1D }, - { "glCopyTexSubImage2D", (GLvoid *) glCopyTexSubImage2D }, - { "glDeleteTextures", (GLvoid *) glDeleteTextures }, - { "glDisableClientState", (GLvoid *) glDisableClientState }, - { "glDrawArrays", (GLvoid *) glDrawArrays }, - { "glDrawElements", (GLvoid *) glDrawElements }, - { "glEdgeFlagPointer", (GLvoid *) glEdgeFlagPointer }, - { "glEnableClientState", (GLvoid *) glEnableClientState }, - { "glGenTextures", (GLvoid *) glGenTextures }, - { "glGetPointerv", (GLvoid *) glGetPointerv }, - { "glIndexPointer", (GLvoid *) glIndexPointer }, - { "glIndexub", (GLvoid *) glIndexub }, - { "glIndexubv", (GLvoid *) glIndexubv }, - { "glInterleavedArrays", (GLvoid *) glInterleavedArrays }, - { "glIsTexture", (GLvoid *) glIsTexture }, - { "glNormalPointer", (GLvoid *) glNormalPointer }, - { "glPopClientAttrib", (GLvoid *) glPopClientAttrib }, - { "glPrioritizeTextures", (GLvoid *) glPrioritizeTextures }, - { "glPushClientAttrib", (GLvoid *) glPushClientAttrib }, - { "glTexCoordPointer", (GLvoid *) glTexCoordPointer }, - { "glTexSubImage1D", (GLvoid *) glTexSubImage1D }, - { "glTexSubImage2D", (GLvoid *) glTexSubImage2D }, - { "glVertexPointer", (GLvoid *) glVertexPointer }, +#if !defined( USE_X86_ASM ) +#define NEED_FUNCTION_POINTER #endif -#ifdef _GLAPI_VERSION_1_2 - { "glCopyTexSubImage3D", (GLvoid *) glCopyTexSubImage3D }, - { "glDrawRangeElements", (GLvoid *) glDrawRangeElements }, - { "glTexImage3D", (GLvoid *) glTexImage3D }, - { "glTexSubImage3D", (GLvoid *) glTexSubImage3D }, - -#ifdef _GLAPI_ARB_imaging - { "glBlendColor", (GLvoid *) glBlendColor }, - { "glBlendEquation", (GLvoid *) glBlendEquation }, - { "glColorSubTable", (GLvoid *) glColorSubTable }, - { "glColorTable", (GLvoid *) glColorTable }, - { "glColorTableParameterfv", (GLvoid *) glColorTableParameterfv }, - { "glColorTableParameteriv", (GLvoid *) glColorTableParameteriv }, - { "glConvolutionFilter1D", (GLvoid *) glConvolutionFilter1D }, - { "glConvolutionFilter2D", (GLvoid *) glConvolutionFilter2D }, - { "glConvolutionParameterf", (GLvoid *) glConvolutionParameterf }, - { "glConvolutionParameterfv", (GLvoid *) glConvolutionParameterfv }, - { "glConvolutionParameteri", (GLvoid *) glConvolutionParameteri }, - { "glConvolutionParameteriv", (GLvoid *) glConvolutionParameteriv }, - { "glCopyColorSubTable", (GLvoid *) glCopyColorSubTable }, - { "glCopyColorTable", (GLvoid *) glCopyColorTable }, - { "glCopyConvolutionFilter1D", (GLvoid *) glCopyConvolutionFilter1D }, - { "glCopyConvolutionFilter2D", (GLvoid *) glCopyConvolutionFilter2D }, - { "glGetColorTable", (GLvoid *) glGetColorTable }, - { "glGetColorTableParameterfv", (GLvoid *) glGetColorTableParameterfv }, - { "glGetColorTableParameteriv", (GLvoid *) glGetColorTableParameteriv }, - { "glGetConvolutionFilter", (GLvoid *) glGetConvolutionFilter }, - { "glGetConvolutionParameterfv", (GLvoid *) glGetConvolutionParameterfv }, - { "glGetConvolutionParameteriv", (GLvoid *) glGetConvolutionParameteriv }, - { "glGetHistogram", (GLvoid *) glGetHistogram }, - { "glGetHistogramParameterfv", (GLvoid *) glGetHistogramParameterfv }, - { "glGetHistogramParameteriv", (GLvoid *) glGetHistogramParameteriv }, - { "glGetMinmax", (GLvoid *) glGetMinmax }, - { "glGetMinmaxParameterfv", (GLvoid *) glGetMinmaxParameterfv }, - { "glGetMinmaxParameteriv", (GLvoid *) glGetMinmaxParameteriv }, - { "glGetSeparableFilter", (GLvoid *) glGetSeparableFilter }, - { "glHistogram", (GLvoid *) glHistogram }, - { "glMinmax", (GLvoid *) glMinmax }, - { "glResetHistogram", (GLvoid *) glResetHistogram }, - { "glResetMinmax", (GLvoid *) glResetMinmax }, - { "glSeparableFilter2D", (GLvoid *) glSeparableFilter2D }, -#endif -#endif +/* The code in this file is auto-generated with Python */ +#include "glprocs.h" - /* GL_ARB_multitexture */ - { "glActiveTextureARB", (GLvoid *) glActiveTextureARB }, - { "glClientActiveTextureARB", (GLvoid *) glClientActiveTextureARB }, - { "glMultiTexCoord1dARB", (GLvoid *) glMultiTexCoord1dARB }, - { "glMultiTexCoord1dvARB", (GLvoid *) glMultiTexCoord1dvARB }, - { "glMultiTexCoord1fARB", (GLvoid *) glMultiTexCoord1fARB }, - { "glMultiTexCoord1fvARB", (GLvoid *) glMultiTexCoord1fvARB }, - { "glMultiTexCoord1iARB", (GLvoid *) glMultiTexCoord1iARB }, - { "glMultiTexCoord1ivARB", (GLvoid *) glMultiTexCoord1ivARB }, - { "glMultiTexCoord1sARB", (GLvoid *) glMultiTexCoord1sARB }, - { "glMultiTexCoord1svARB", (GLvoid *) glMultiTexCoord1svARB }, - { "glMultiTexCoord2dARB", (GLvoid *) glMultiTexCoord2dARB }, - { "glMultiTexCoord2dvARB", (GLvoid *) glMultiTexCoord2dvARB }, - { "glMultiTexCoord2fARB", (GLvoid *) glMultiTexCoord2fARB }, - { "glMultiTexCoord2fvARB", (GLvoid *) glMultiTexCoord2fvARB }, - { "glMultiTexCoord2iARB", (GLvoid *) glMultiTexCoord2iARB }, - { "glMultiTexCoord2ivARB", (GLvoid *) glMultiTexCoord2ivARB }, - { "glMultiTexCoord2sARB", (GLvoid *) glMultiTexCoord2sARB }, - { "glMultiTexCoord2svARB", (GLvoid *) glMultiTexCoord2svARB }, - { "glMultiTexCoord3dARB", (GLvoid *) glMultiTexCoord3dARB }, - { "glMultiTexCoord3dvARB", (GLvoid *) glMultiTexCoord3dvARB }, - { "glMultiTexCoord3fARB", (GLvoid *) glMultiTexCoord3fARB }, - { "glMultiTexCoord3fvARB", (GLvoid *) glMultiTexCoord3fvARB }, - { "glMultiTexCoord3iARB", (GLvoid *) glMultiTexCoord3iARB }, - { "glMultiTexCoord3ivARB", (GLvoid *) glMultiTexCoord3ivARB }, - { "glMultiTexCoord3sARB", (GLvoid *) glMultiTexCoord3sARB }, - { "glMultiTexCoord3svARB", (GLvoid *) glMultiTexCoord3svARB }, - { "glMultiTexCoord4dARB", (GLvoid *) glMultiTexCoord4dARB }, - { "glMultiTexCoord4dvARB", (GLvoid *) glMultiTexCoord4dvARB }, - { "glMultiTexCoord4fARB", (GLvoid *) glMultiTexCoord4fARB }, - { "glMultiTexCoord4fvARB", (GLvoid *) glMultiTexCoord4fvARB }, - { "glMultiTexCoord4iARB", (GLvoid *) glMultiTexCoord4iARB }, - { "glMultiTexCoord4ivARB", (GLvoid *) glMultiTexCoord4ivARB }, - { "glMultiTexCoord4sARB", (GLvoid *) glMultiTexCoord4sARB }, - { "glMultiTexCoord4svARB", (GLvoid *) glMultiTexCoord4svARB }, - - /* 2. GL_EXT_blend_color */ - { "glBlendColorEXT", (GLvoid *) glBlendColorEXT }, - - /* 3. GL_EXT_polygon_offset */ - { "glPolygonOffsetEXT", (GLvoid *) glPolygonOffsetEXT }, - - /* 54. GL_EXT_point_parameters */ - { "glPointParameterfEXT", (GLvoid *) glPointParameterfEXT }, - { "glPointParameterfvEXT", (GLvoid *) glPointParameterfvEXT }, - - /* 78. GL_EXT_paletted_texture */ - { "glColorTableEXT", (GLvoid *) glColorTableEXT }, - { "glColorSubTableEXT", (GLvoid *) glColorSubTableEXT }, - { "glGetColorTableEXT", (GLvoid *) glGetColorTableEXT }, - { "glGetColorTableParameterfvEXT", (GLvoid *) glGetColorTableParameterfvEXT }, - { "glGetColorTableParameterivEXT", (GLvoid *) glGetColorTableParameterivEXT }, - - /* 97. GL_EXT_compiled_vertex_array */ - { "glLockArraysEXT", (GLvoid *) glLockArraysEXT }, - { "glUnlockArraysEXT", (GLvoid *) glUnlockArraysEXT }, - - /* 37. GL_EXT_blend_minmax */ - { "glBlendEquationEXT", (GLvoid *) glBlendEquationEXT }, - - /* 173. GL_EXT/INGR_blend_func_separate */ - { "glBlendFuncSeparateINGR", (GLvoid *) glBlendFuncSeparateINGR }, - - /* GL_MESA_window_pos */ - { "glWindowPos4fMESA", (GLvoid *) glWindowPos4fMESA }, - - /* GL_MESA_resize_buffers */ - { "glResizeBuffersMESA", (GLvoid *) glResizeBuffersMESA }, - - /* GL_ARB_transpose_matrix */ - { "glLoadTransposeMatrixdARB", (GLvoid *) glLoadTransposeMatrixdARB }, - { "glLoadTransposeMatrixfARB", (GLvoid *) glLoadTransposeMatrixfARB }, - { "glMultTransposeMatrixdARB", (GLvoid *) glMultTransposeMatrixdARB }, - { "glMultTransposeMatrixfARB", (GLvoid *) glMultTransposeMatrixfARB }, - - { NULL, NULL } /* end of list marker */ -}; +/** + * Search the table of static entrypoint functions for the named function + * and return the corresponding glprocs_table_t entry. + */ +static const glprocs_table_t * +find_entry( const char * n ) +{ + GLuint i; + for (i = 0; static_functions[i].Name_offset >= 0; i++) { + const char * test_name; -/* + test_name = gl_string_table + static_functions[i].Name_offset; + if (strcmp(test_name, n) == 0) { + return & static_functions[i]; + } + } + return NULL; +} + + +/** * Return dispatch table offset of the named static (built-in) function. * Return -1 if function not found. */ static GLint get_static_proc_offset(const char *funcName) { - GLuint i; - for (i = 0; static_functions[i].Name; i++) { - if (strcmp(static_functions[i].Name, funcName) == 0) { - return i; - } + const glprocs_table_t * const f = find_entry( funcName ); + + if ( f != NULL ) { + return f->Offset; } return -1; } -/* +#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 + +# if defined(THREADS) && !defined(GLX_USE_TLS) +# define X86_DISPATCH_FUNCTION_SIZE 32 +# else +# define X86_DISPATCH_FUNCTION_SIZE 16 +# endif + + +/** * Return dispatch function address the named static (built-in) function. * Return NULL if function not found. */ -static GLvoid * +static const _glapi_proc get_static_proc_address(const char *funcName) { - GLuint i = get_static_proc_offset(funcName); - if (i >= 0) - return static_functions[i].Address; - else + const glprocs_table_t * const f = find_entry( funcName ); + + if ( f != NULL ) { + return (_glapi_proc) (gl_dispatch_functions_start + + (X86_DISPATCH_FUNCTION_SIZE * f->Offset)); + } + else { return NULL; + } +} + +#else + + +/** + * Return pointer to the named static (built-in) function. + * \return NULL if function not found. + */ +static const _glapi_proc +get_static_proc_address(const char *funcName) +{ + const glprocs_table_t * const f = find_entry( funcName ); + return ( f != NULL ) ? f->Address : NULL; +} + +#endif /* USE_X86_ASM */ + + +/** + * Return the name of the function at the given offset in the dispatch + * table. For debugging only. + */ +static const char * +get_static_proc_name( GLuint offset ) +{ + GLuint i; + + for (i = 0; static_functions[i].Name_offset >= 0; i++) { + if (static_functions[i].Offset == offset) { + return gl_string_table + static_functions[i].Name_offset; + } + } + return NULL; } /********************************************************************** * Extension function management. - **********************************************************************/ + */ + +/* + * Number of extension functions which we can dynamically add at runtime. + */ +#define MAX_EXTENSION_FUNCS 300 + + +/* + * 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) + +/** + * Track information about a function added to the GL API. + */ +struct _glapi_function { + /** + * Name of the function. + */ + const char * name; + + + /** + * Text string that describes the types of the parameters passed to the + * named function. Parameter types are converted to characters using the + * following rules: + * - 'i' for \c GLint, \c GLuint, and \c GLenum + * - 'p' for any pointer type + * - 'f' for \c GLfloat and \c GLclampf + * - 'd' for \c GLdouble and \c GLclampd + */ + const char * parameter_signature; -struct _glapi_ext_entrypoint { - const char *Name; /* the extension function's name */ - GLuint Offset; /* relative to start of dispatch table */ - GLvoid *Address; /* address of dispatch function */ + + /** + * Offset in the dispatch table where the pointer to the real function is + * located. If the driver has not requested that the named function be + * added to the dispatch table, this will have the value ~0. + */ + unsigned dispatch_offset; + + + /** + * Pointer to the dispatch stub for the named function. + * + * \todo + * The semantic of this field should be changed slightly. Currently, it + * is always expected to be non-\c NULL. However, it would be better to + * only allocate the entry-point stub when the application requests the + * function via \c glXGetProcAddress. This would save memory for all the + * functions that the driver exports but that the application never wants + * to call. + */ + _glapi_proc dispatch_stub; }; -static struct _glapi_ext_entrypoint ExtEntryTable[_GLAPI_EXTRA_SLOTS]; -static GLuint NumExtEntryPoints = 0; +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 void * -generate_entrypoint(GLuint offset) +static _glapi_proc +generate_entrypoint(GLuint functionOffset) { - /* XXX need to generate some assembly code here */ +#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 + + (X86_DISPATCH_FUNCTION_SIZE * 32); + GLubyte * const code = (GLubyte *) malloc( X86_DISPATCH_FUNCTION_SIZE ); + + + if ( code != NULL ) { + (void) memcpy( code, template_func, X86_DISPATCH_FUNCTION_SIZE ); + fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset ); + } + 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 + 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 + } + return (_glapi_proc) code; +#else + (void) functionOffset; return NULL; +#endif /* USE_*_ASM */ } - -/* - * Add a new extension function entrypoint. - * Return: GL_TRUE = success or GL_FALSE = failure +/** + * This function inserts a new dispatch offset into the assembly language + * stub that was generated with the preceeding function. */ -GLboolean -_glapi_add_entrypoint(const char *funcName, GLuint offset) +static void +fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) { - GLint index; +#if defined(USE_X86_ASM) + GLubyte * const code = (GLubyte *) entrypoint; + + +#if X86_DISPATCH_FUNCTION_SIZE == 32 + *((unsigned int *)(code + 11)) = 4 * offset; + *((unsigned int *)(code + 22)) = 4 * offset; +#elif X86_DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS ) + *((unsigned int *)(code + 8)) = 4 * offset; +#elif X86_DISPATCH_FUNCTION_SIZE == 16 + *((unsigned int *)(code + 7)) = 4 * offset; +#else +# error Invalid X86_DISPATCH_FUNCTION_SIZE! +#endif - /* Make sure we don't try to add a new entrypoint after someone - * has already called _glapi_get_dispatch_table_size()! If that's - * happened the caller's information will now be out of date. - */ - assert(!GetSizeCalled); +#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__ */ - /* first check if the named function is already statically present */ - index = get_static_proc_offset(funcName); +#else - if (index >= 0) { - assert(index == offset); - return GL_TRUE; + /* an unimplemented architecture */ + (void) entrypoint; + (void) offset; + +#endif /* USE_*_ASM */ +} + + +/** + * Generate new entrypoint + * + * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver + * calls \c _glapi_add_dispatch we'll put in the proper offset. If that + * never happens, and the user calls this function, he'll segfault. That's + * what you get when you try calling a GL function that doesn't really exist. + * + * \param funcName Name of the function to create an entry-point for. + * + * \sa _glapi_add_entrypoint + */ + +static struct _glapi_function * +add_function_name( const char * funcName ) +{ + struct _glapi_function * entry = NULL; + + if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) { + _glapi_proc entrypoint = generate_entrypoint(~0); + if (entrypoint != NULL) { + entry = & ExtEntryTable[NumExtEntryPoints]; + + ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName); + ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL; + ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0; + ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint; + NumExtEntryPoints++; + } } - /* else if (offset < _glapi_get_dispatch_table_size()) { */ - else { - /* be sure index and name match known data */ - GLuint i; - for (i = 0; i < NumExtEntryPoints; i++) { - if (strcmp(ExtEntryTable[i].Name, funcName) == 0) { - /* function already registered with api */ - if (ExtEntryTable[i].Offset == offset) { - return GL_TRUE; /* offsets match */ - } - else { - return GL_FALSE; /* bad offset! */ - } - } + + return entry; +} + + +/** + * Fill-in the dispatch stub for the named function. + * + * This function is intended to be called by a hardware driver. When called, + * a dispatch stub may be created created for the function. A pointer to this + * dispatch function will be returned by glXGetProcAddress. + * + * \param function_names Array of pointers to function names that should + * share a common dispatch offset. + * \param parameter_signature String representing the types of the parameters + * passed to the named function. Parameter types + * are converted to characters using the following + * rules: + * - 'i' for \c GLint, \c GLuint, and \c GLenum + * - 'p' for any pointer type + * - 'f' for \c GLfloat and \c GLclampf + * - 'd' for \c GLdouble and \c GLclampd + * + * \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]. + * + * \sa glXGetProcAddress + * + * \warning + * This function can only handle up to 8 names at a time. As far as I know, + * the maximum number of names ever associated with an existing GL function is + * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT, + * \c glPointParameterfARB, and \c glPointParameterf), so this should not be + * too painful of a limitation. + * + * \todo + * Determine whether or not \c parameter_signature should be allowed to be + * \c NULL. It doesn't seem like much of a hardship for drivers to have to + * pass in an empty string. + * + * \todo + * Determine if code should be added to reject function names that start with + * 'glX'. + * + * \bug + * Add code to compare \c parameter_signature with the parameter signature of + * a static function. In order to do that, we need to find a way to \b get + * the parameter signature of a static function. + */ + +PUBLIC int +_glapi_add_dispatch( const char * const * function_names, + const char * parameter_signature ) +{ + static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC; + const char * const real_sig = (parameter_signature != NULL) + ? parameter_signature : ""; + struct _glapi_function * entry[8]; + GLboolean is_static[8]; + unsigned i; + unsigned j; + int offset = ~0; + int new_offset; + + + (void) memset( is_static, 0, sizeof( is_static ) ); + (void) memset( entry, 0, sizeof( entry ) ); + + for ( i = 0 ; function_names[i] != NULL ; i++ ) { + /* Do some trivial validation on the name of the function. + */ + +#ifdef MANGLE + if (!function_names[i] || function_names[i][0] != 'm' || function_names[i][1] != 'g' || function_names[i][2] != 'l') + return GL_FALSE; +#else + if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l') + return GL_FALSE; +#endif + + + /* Determine if the named function already exists. If the function does + * exist, it must have the same parameter signature as the function + * being added. + */ + + new_offset = get_static_proc_offset(function_names[i]); + if (new_offset >= 0) { + /* FIXME: Make sure the parameter signatures match! How do we get + * FIXME: the parameter signature for static functions? + */ + + if ( (offset != ~0) && (new_offset != offset) ) { + return -1; + } + + is_static[i] = GL_TRUE; + offset = new_offset; + } + + + for ( j = 0 ; j < NumExtEntryPoints ; j++ ) { + if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) { + /* 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) { + return -1; + } + + if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) { + return -1; + } + + offset = ExtEntryTable[j].dispatch_offset; + } + + entry[i] = & ExtEntryTable[j]; + break; + } } - assert(NumExtEntryPoints < _GLAPI_EXTRA_SLOTS); - ExtEntryTable[NumExtEntryPoints].Name = strdup(funcName); - ExtEntryTable[NumExtEntryPoints].Offset = offset; - ExtEntryTable[NumExtEntryPoints].Address = generate_entrypoint(offset); - NumExtEntryPoints++; + } - if (offset > MaxDispatchOffset) - MaxDispatchOffset = offset; - return GL_TRUE; + if (offset == ~0) { + offset = next_dynamic_offset; + next_dynamic_offset++; } -/* - else { - return GL_FALSE; + + + for ( i = 0 ; function_names[i] != NULL ; i++ ) { + if (! is_static[i] ) { + if (entry[i] == NULL) { + entry[i] = add_function_name( function_names[i] ); + if (entry[i] == NULL) { + /* FIXME: Possible memory leak here. + */ + return -1; + } + } + + + entry[i]->parameter_signature = str_dup(real_sig); + fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset); + entry[i]->dispatch_offset = offset; + } } -*/ + + return offset; } - -/* +/** * Return offset of entrypoint for named function within dispatch table. */ -GLint +PUBLIC GLint _glapi_get_proc_offset(const char *funcName) { /* search extension functions first */ - GLint i; + GLuint i; for (i = 0; i < NumExtEntryPoints; i++) { - if (strcmp(ExtEntryTable[i].Name, funcName) == 0) { - return ExtEntryTable[i].Offset; + if (strcmp(ExtEntryTable[i].name, funcName) == 0) { + return ExtEntryTable[i].dispatch_offset; } } @@ -763,516 +864,191 @@ _glapi_get_proc_offset(const char *funcName) -/* - * Return entrypoint for named function. +/** + * Return pointer to the named function. If the function name isn't found + * in the name of static functions, try generating a new API entrypoint on + * the fly with assembly language. */ -const GLvoid * +_glapi_proc _glapi_get_proc_address(const char *funcName) { + struct _glapi_function * entry; + GLuint i; + +#ifdef MANGLE + if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l') + return NULL; +#else + if (funcName[0] != 'g' || funcName[1] != 'l') + return NULL; +#endif + /* search extension functions first */ - GLint i; for (i = 0; i < NumExtEntryPoints; i++) { - if (strcmp(ExtEntryTable[i].Name, funcName) == 0) { - return ExtEntryTable[i].Address; + if (strcmp(ExtEntryTable[i].name, funcName) == 0) { + return ExtEntryTable[i].dispatch_stub; } } /* search static functions */ - return get_static_proc_address(funcName); + { + const _glapi_proc func = get_static_proc_address(funcName); + if (func) + return func; + } + + entry = add_function_name(funcName); + return (entry == NULL) ? NULL : entry->dispatch_stub; } -/* - * Make sure there are no NULL pointers in the given dispatch table. - * Intented for debugging purposes. +/** + * Return the name of the function at the given dispatch offset. + * This is only intended for debugging. */ -void -_glapi_check_table(const struct _glapi_table *table) +const char * +_glapi_get_proc_name(GLuint offset) { - const GLuint entries = _glapi_get_dispatch_table_size(); - const void **tab = (const void **) table; GLuint i; - for (i = 0; i < entries; i++) { - assert(tab[i]); - } -#if 000 - assert(table->Accum); - assert(table->AlphaFunc); - assert(table->Begin); - assert(table->Bitmap); - assert(table->BlendFunc); - assert(table->CallList); - assert(table->CallLists); - assert(table->Clear); - assert(table->ClearAccum); - assert(table->ClearColor); - assert(table->ClearDepth); - assert(table->ClearIndex); - assert(table->ClearStencil); - assert(table->ClipPlane); - assert(table->Color3b); - assert(table->Color3bv); - assert(table->Color3d); - assert(table->Color3dv); - assert(table->Color3f); - assert(table->Color3fv); - assert(table->Color3i); - assert(table->Color3iv); - assert(table->Color3s); - assert(table->Color3sv); - assert(table->Color3ub); - assert(table->Color3ubv); - assert(table->Color3ui); - assert(table->Color3uiv); - assert(table->Color3us); - assert(table->Color3usv); - assert(table->Color4b); - assert(table->Color4bv); - assert(table->Color4d); - assert(table->Color4dv); - assert(table->Color4f); - assert(table->Color4fv); - assert(table->Color4i); - assert(table->Color4iv); - assert(table->Color4s); - assert(table->Color4sv); - assert(table->Color4ub); - assert(table->Color4ubv); - assert(table->Color4ui); - assert(table->Color4uiv); - assert(table->Color4us); - assert(table->Color4usv); - assert(table->ColorMask); - assert(table->ColorMaterial); - assert(table->CopyPixels); - assert(table->CullFace); - assert(table->DeleteLists); - assert(table->DepthFunc); - assert(table->DepthMask); - assert(table->DepthRange); - assert(table->Disable); - assert(table->DrawBuffer); - assert(table->DrawElements); - assert(table->DrawPixels); - assert(table->EdgeFlag); - assert(table->EdgeFlagv); - assert(table->Enable); - assert(table->End); - assert(table->EndList); - assert(table->EvalCoord1d); - assert(table->EvalCoord1dv); - assert(table->EvalCoord1f); - assert(table->EvalCoord1fv); - assert(table->EvalCoord2d); - assert(table->EvalCoord2dv); - assert(table->EvalCoord2f); - assert(table->EvalCoord2fv); - assert(table->EvalMesh1); - assert(table->EvalMesh2); - assert(table->EvalPoint1); - assert(table->EvalPoint2); - assert(table->FeedbackBuffer); - assert(table->Finish); - assert(table->Flush); - assert(table->Fogf); - assert(table->Fogfv); - assert(table->Fogi); - assert(table->Fogiv); - assert(table->FrontFace); - assert(table->Frustum); - assert(table->GenLists); - assert(table->GetBooleanv); - assert(table->GetClipPlane); - assert(table->GetDoublev); - assert(table->GetError); - assert(table->GetFloatv); - assert(table->GetIntegerv); - assert(table->GetLightfv); - assert(table->GetLightiv); - assert(table->GetMapdv); - assert(table->GetMapfv); - assert(table->GetMapiv); - assert(table->GetMaterialfv); - assert(table->GetMaterialiv); - assert(table->GetPixelMapfv); - assert(table->GetPixelMapuiv); - assert(table->GetPixelMapusv); - assert(table->GetPolygonStipple); - assert(table->GetString); - assert(table->GetTexEnvfv); - assert(table->GetTexEnviv); - assert(table->GetTexGendv); - assert(table->GetTexGenfv); - assert(table->GetTexGeniv); - assert(table->GetTexImage); - assert(table->GetTexLevelParameterfv); - assert(table->GetTexLevelParameteriv); - assert(table->GetTexParameterfv); - assert(table->GetTexParameteriv); - assert(table->Hint); - assert(table->IndexMask); - assert(table->Indexd); - assert(table->Indexdv); - assert(table->Indexf); - assert(table->Indexfv); - assert(table->Indexi); - assert(table->Indexiv); - assert(table->Indexs); - assert(table->Indexsv); - assert(table->InitNames); - assert(table->IsEnabled); - assert(table->IsList); - assert(table->LightModelf); - assert(table->LightModelfv); - assert(table->LightModeli); - assert(table->LightModeliv); - assert(table->Lightf); - assert(table->Lightfv); - assert(table->Lighti); - assert(table->Lightiv); - assert(table->LineStipple); - assert(table->LineWidth); - assert(table->ListBase); - assert(table->LoadIdentity); - assert(table->LoadMatrixd); - assert(table->LoadMatrixf); - assert(table->LoadName); - assert(table->LogicOp); - assert(table->Map1d); - assert(table->Map1f); - assert(table->Map2d); - assert(table->Map2f); - assert(table->MapGrid1d); - assert(table->MapGrid1f); - assert(table->MapGrid2d); - assert(table->MapGrid2f); - assert(table->Materialf); - assert(table->Materialfv); - assert(table->Materiali); - assert(table->Materialiv); - assert(table->MatrixMode); - assert(table->MultMatrixd); - assert(table->MultMatrixf); - assert(table->NewList); - assert(table->Normal3b); - assert(table->Normal3bv); - assert(table->Normal3d); - assert(table->Normal3dv); - assert(table->Normal3f); - assert(table->Normal3fv); - assert(table->Normal3i); - assert(table->Normal3iv); - assert(table->Normal3s); - assert(table->Normal3sv); - assert(table->Ortho); - assert(table->PassThrough); - assert(table->PixelMapfv); - assert(table->PixelMapuiv); - assert(table->PixelMapusv); - assert(table->PixelStoref); - assert(table->PixelStorei); - assert(table->PixelTransferf); - assert(table->PixelTransferi); - assert(table->PixelZoom); - assert(table->PointSize); - assert(table->PolygonMode); - assert(table->PolygonOffset); - assert(table->PolygonStipple); - assert(table->PopAttrib); - assert(table->PopMatrix); - assert(table->PopName); - assert(table->PushAttrib); - assert(table->PushMatrix); - assert(table->PushName); - assert(table->RasterPos2d); - assert(table->RasterPos2dv); - assert(table->RasterPos2f); - assert(table->RasterPos2fv); - assert(table->RasterPos2i); - assert(table->RasterPos2iv); - assert(table->RasterPos2s); - assert(table->RasterPos2sv); - assert(table->RasterPos3d); - assert(table->RasterPos3dv); - assert(table->RasterPos3f); - assert(table->RasterPos3fv); - assert(table->RasterPos3i); - assert(table->RasterPos3iv); - assert(table->RasterPos3s); - assert(table->RasterPos3sv); - assert(table->RasterPos4d); - assert(table->RasterPos4dv); - assert(table->RasterPos4f); - assert(table->RasterPos4fv); - assert(table->RasterPos4i); - assert(table->RasterPos4iv); - assert(table->RasterPos4s); - assert(table->RasterPos4sv); - assert(table->ReadBuffer); - assert(table->ReadPixels); - assert(table->Rectd); - assert(table->Rectdv); - assert(table->Rectf); - assert(table->Rectfv); - assert(table->Recti); - assert(table->Rectiv); - assert(table->Rects); - assert(table->Rectsv); - assert(table->RenderMode); - assert(table->Rotated); - assert(table->Rotatef); - assert(table->Scaled); - assert(table->Scalef); - assert(table->Scissor); - assert(table->SelectBuffer); - assert(table->ShadeModel); - assert(table->StencilFunc); - assert(table->StencilMask); - assert(table->StencilOp); - assert(table->TexCoord1d); - assert(table->TexCoord1dv); - assert(table->TexCoord1f); - assert(table->TexCoord1fv); - assert(table->TexCoord1i); - assert(table->TexCoord1iv); - assert(table->TexCoord1s); - assert(table->TexCoord1sv); - assert(table->TexCoord2d); - assert(table->TexCoord2dv); - assert(table->TexCoord2f); - assert(table->TexCoord2fv); - assert(table->TexCoord2i); - assert(table->TexCoord2iv); - assert(table->TexCoord2s); - assert(table->TexCoord2sv); - assert(table->TexCoord3d); - assert(table->TexCoord3dv); - assert(table->TexCoord3f); - assert(table->TexCoord3fv); - assert(table->TexCoord3i); - assert(table->TexCoord3iv); - assert(table->TexCoord3s); - assert(table->TexCoord3sv); - assert(table->TexCoord4d); - assert(table->TexCoord4dv); - assert(table->TexCoord4f); - assert(table->TexCoord4fv); - assert(table->TexCoord4i); - assert(table->TexCoord4iv); - assert(table->TexCoord4s); - assert(table->TexCoord4sv); - assert(table->TexEnvf); - assert(table->TexEnvfv); - assert(table->TexEnvi); - assert(table->TexEnviv); - assert(table->TexGend); - assert(table->TexGendv); - assert(table->TexGenf); - assert(table->TexGenfv); - assert(table->TexGeni); - assert(table->TexGeniv); - assert(table->TexImage1D); - assert(table->TexImage2D); - assert(table->TexParameterf); - assert(table->TexParameterfv); - assert(table->TexParameteri); - assert(table->TexParameteriv); - assert(table->Translated); - assert(table->Translatef); - assert(table->Vertex2d); - assert(table->Vertex2dv); - assert(table->Vertex2f); - assert(table->Vertex2fv); - assert(table->Vertex2i); - assert(table->Vertex2iv); - assert(table->Vertex2s); - assert(table->Vertex2sv); - assert(table->Vertex3d); - assert(table->Vertex3dv); - assert(table->Vertex3f); - assert(table->Vertex3fv); - assert(table->Vertex3i); - assert(table->Vertex3iv); - assert(table->Vertex3s); - assert(table->Vertex3sv); - assert(table->Vertex4d); - assert(table->Vertex4dv); - assert(table->Vertex4f); - assert(table->Vertex4fv); - assert(table->Vertex4i); - assert(table->Vertex4iv); - assert(table->Vertex4s); - assert(table->Vertex4sv); - assert(table->Viewport); - -#ifdef _GLAPI_VERSION_1_1 - assert(table->AreTexturesResident); - assert(table->ArrayElement); - assert(table->BindTexture); - assert(table->ColorPointer); - assert(table->CopyTexImage1D); - assert(table->CopyTexImage2D); - assert(table->CopyTexSubImage1D); - assert(table->CopyTexSubImage2D); - assert(table->DeleteTextures); - assert(table->DisableClientState); - assert(table->DrawArrays); - assert(table->EdgeFlagPointer); - assert(table->EnableClientState); - assert(table->GenTextures); - assert(table->GetPointerv); - assert(table->IndexPointer); - assert(table->Indexub); - assert(table->Indexubv); - assert(table->InterleavedArrays); - assert(table->IsTexture); - assert(table->NormalPointer); - assert(table->PopClientAttrib); - assert(table->PrioritizeTextures); - assert(table->PushClientAttrib); - assert(table->TexCoordPointer); - assert(table->TexSubImage1D); - assert(table->TexSubImage2D); - assert(table->VertexPointer); -#endif - -#ifdef _GLAPI_VERSION_1_2 - assert(table->CopyTexSubImage3D); - assert(table->DrawRangeElements); - assert(table->TexImage3D); - assert(table->TexSubImage3D); -#ifdef _GLAPI_ARB_imaging - assert(table->BlendColor); - assert(table->BlendEquation); - assert(table->ColorSubTable); - assert(table->ColorTable); - assert(table->ColorTableParameterfv); - assert(table->ColorTableParameteriv); - assert(table->ConvolutionFilter1D); - assert(table->ConvolutionFilter2D); - assert(table->ConvolutionParameterf); - assert(table->ConvolutionParameterfv); - assert(table->ConvolutionParameteri); - assert(table->ConvolutionParameteriv); - assert(table->CopyColorSubTable); - assert(table->CopyColorTable); - assert(table->CopyConvolutionFilter1D); - assert(table->CopyConvolutionFilter2D); - assert(table->GetColorTable); - assert(table->GetColorTableParameterfv); - assert(table->GetColorTableParameteriv); - assert(table->GetConvolutionFilter); - assert(table->GetConvolutionParameterfv); - assert(table->GetConvolutionParameteriv); - assert(table->GetHistogram); - assert(table->GetHistogramParameterfv); - assert(table->GetHistogramParameteriv); - assert(table->GetMinmax); - assert(table->GetMinmaxParameterfv); - assert(table->GetMinmaxParameteriv); - assert(table->Histogram); - assert(table->Minmax); - assert(table->ResetHistogram); - assert(table->ResetMinmax); - assert(table->SeparableFilter2D); -#endif -#endif - + const char * n; -#ifdef _GLAPI_EXT_paletted_texture - assert(table->ColorTableEXT); - assert(table->ColorSubTableEXT); - assert(table->GetColorTableEXT); - assert(table->GetColorTableParameterfvEXT); - assert(table->GetColorTableParameterivEXT); -#endif + /* search built-in functions */ + n = get_static_proc_name(offset); + if ( n != NULL ) { + return n; + } -#ifdef _GLAPI_EXT_compiled_vertex_array - assert(table->LockArraysEXT); - assert(table->UnlockArraysEXT); -#endif + /* search added extension functions */ + for (i = 0; i < NumExtEntryPoints; i++) { + if (ExtEntryTable[i].dispatch_offset == offset) { + return ExtEntryTable[i].name; + } + } + return NULL; +} -#ifdef _GLAPI_EXT_point_parameter - assert(table->PointParameterfEXT); - assert(table->PointParameterfvEXT); -#endif -#ifdef _GLAPI_EXT_polygon_offset - assert(table->PolygonOffsetEXT); -#endif -#ifdef _GLAPI_ARB_multitexture - assert(table->ActiveTextureARB); - assert(table->ClientActiveTextureARB); - assert(table->MultiTexCoord1dARB); - assert(table->MultiTexCoord1dvARB); - assert(table->MultiTexCoord1fARB); - assert(table->MultiTexCoord1fvARB); - assert(table->MultiTexCoord1iARB); - assert(table->MultiTexCoord1ivARB); - assert(table->MultiTexCoord1sARB); - assert(table->MultiTexCoord1svARB); - assert(table->MultiTexCoord2dARB); - assert(table->MultiTexCoord2dvARB); - assert(table->MultiTexCoord2fARB); - assert(table->MultiTexCoord2fvARB); - assert(table->MultiTexCoord2iARB); - assert(table->MultiTexCoord2ivARB); - assert(table->MultiTexCoord2sARB); - assert(table->MultiTexCoord2svARB); - assert(table->MultiTexCoord3dARB); - assert(table->MultiTexCoord3dvARB); - assert(table->MultiTexCoord3fARB); - assert(table->MultiTexCoord3fvARB); - assert(table->MultiTexCoord3iARB); - assert(table->MultiTexCoord3ivARB); - assert(table->MultiTexCoord3sARB); - assert(table->MultiTexCoord3svARB); - assert(table->MultiTexCoord4dARB); - assert(table->MultiTexCoord4dvARB); - assert(table->MultiTexCoord4fARB); - assert(table->MultiTexCoord4fvARB); - assert(table->MultiTexCoord4iARB); - assert(table->MultiTexCoord4ivARB); - assert(table->MultiTexCoord4sARB); - assert(table->MultiTexCoord4svARB); -#endif +/** + * Return size of dispatch table struct as number of functions (or + * slots). + */ +PUBLIC GLuint +_glapi_get_dispatch_table_size(void) +{ + return DISPATCH_TABLE_SIZE; +} -#ifdef _GLAPI_INGR_blend_func_separate - assert(table->BlendFuncSeparateINGR); -#endif -#ifdef _GLAPI_MESA_window_pos - assert(table->WindowPos4fMESA); -#endif -#ifdef _GLAPI_MESA_resize_buffers - assert(table->ResizeBuffersMESA); -#endif +/** + * Make sure there are no NULL pointers in the given dispatch table. + * Intended for debugging purposes. + */ +void +_glapi_check_table(const struct _glapi_table *table) +{ +#ifdef 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]); + } -#ifdef _GLAPI_ARB_transpose_matrix - assert(table->LoadTransposeMatrixdARB); - assert(table->LoadTransposeMatrixfARB); - assert(table->MultTransposeMatrixdARB); - assert(table->MultTransposeMatrixfARB); -#endif + /* Do some spot checks to be sure that the dispatch table + * slots are assigned correctly. + */ + { + 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 istextureOffset = _glapi_get_proc_offset("glIsTextureEXT"); + char *istextureFunc = (char*) &table->IsTextureEXT; + GLuint offset = (istextureFunc - (char *) table) / sizeof(void *); + assert(istextureOffset == _gloffset_IsTextureEXT); + assert(istextureOffset == 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); + assert(_glapi_get_proc_address("glSecondaryColor3fEXT") == (_glapi_proc) &glSecondaryColor3fEXT); + } + { + 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); + assert(_glapi_get_proc_address("glPointParameterivNV") == (_glapi_proc) &glPointParameterivNV); + } + { + 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); + assert(_glapi_get_proc_address("glSetFenceNV") == (_glapi_proc) &glSetFenceNV); + } +#else + (void) table; #endif } - -/* - * Generate the GL entrypoint functions here. +/** + * Perform platform-specific GL API entry-point fixups. + * + * */ +static void +init_glapi_relocs( void ) +{ +#if defined( USE_X86_ASM ) && defined( GLX_USE_TLS ) + extern void * _x86_get_dispatch(void); + const GLubyte * const get_disp = (const GLubyte *) _x86_get_dispatch; + GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start; -#define KEYWORD1 -#define KEYWORD2 GLAPIENTRY -#ifdef USE_MGL_NAMESPACE -#define NAME(func) mgl##func -#else -#define NAME(func) gl##func -#endif - -#include "glapitemp.h" + while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) { + (void) memcpy( curr_func, get_disp, 6 ); + curr_func += X86_DISPATCH_FUNCTION_SIZE; + } +#endif /* defined( USE_X86_ASM ) && defined( GLX_USE_TLS ) */ +}