#include "glheader.h"
#include "glapi.h"
#include "glapioffsets.h"
#include "glapitable.h"
#include "glthread.h"
static GLboolean WarnFlag = GL_FALSE;
static _glapi_warning_func warning_func;
void
_glapi_noop_enable_warnings(GLboolean enable)
{
WarnFlag = enable;
}
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 KEYWORD1 static
#define KEYWORD2
#define NAME(func) NoOp##func
#define F NULL
#define DISPATCH(func, args, msg) \
if (warn()) { \
warning_func(NULL, "GL User Error: called without context:"); \
warning_func msg; \
}
#define RETURN_DISPATCH(func, args, msg) \
if (warn()) { \
warning_func(NULL, "GL User Error: called without context:"); \
warning_func msg; \
} \
return 0
#define DISPATCH_TABLE_NAME __glapi_noop_table
#define UNUSED_TABLE_NAME __usused_noop_functions
#define TABLE_ENTRY(name) (void *) NoOp##name
static int NoOpUnused(void)
{
if (warn()) {
warning_func(NULL, "GL User Error: calling extension function without a current context\n");
}
return 0;
}
#include "glapitemp.h"
#if defined(THREADS)
static GLboolean ThreadSafe = GL_FALSE;
static _glthread_TSD DispatchTSD;
static _glthread_TSD RealDispatchTSD;
static _glthread_TSD ContextTSD;
#define KEYWORD1 static
#define KEYWORD2 GLAPIENTRY
#define NAME(func) _ts_##func
#define DISPATCH(FUNC, ARGS, MESSAGE) \
struct _glapi_table *dispatch; \
dispatch = (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD); \
if (!dispatch) \
dispatch = (struct _glapi_table *) __glapi_noop_table; \
(dispatch->FUNC) ARGS
#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
struct _glapi_table *dispatch; \
dispatch = (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD); \
if (!dispatch) \
dispatch = (struct _glapi_table *) __glapi_noop_table; \
return (dispatch->FUNC) ARGS
#define DISPATCH_TABLE_NAME __glapi_threadsafe_table
#define UNUSED_TABLE_NAME __usused_threadsafe_functions
#define TABLE_ENTRY(name) (void *) _ts_##name
static int _ts_Unused(void)
{
return 0;
}
#include "glapitemp.h"
#endif
struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;
void *_glapi_Context = NULL;
static GLboolean DispatchOverride = GL_FALSE;
static char *
str_dup(const char *str)
{
char *copy;
copy = (char*) malloc(strlen(str) + 1);
if (!copy)
return NULL;
strcpy(copy, str);
return copy;
}
void
_glapi_check_multithread(void)
{
#if defined(THREADS)
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;
}
}
if (ThreadSafe) {
if (!_glapi_get_dispatch()) {
_glapi_set_dispatch(NULL);
}
}
#endif
}
void
_glapi_set_context(void *context)
{
#if defined(THREADS)
_glthread_SetTSD(&ContextTSD, context);
if (ThreadSafe)
_glapi_Context = NULL;
else
_glapi_Context = context;
#else
_glapi_Context = context;
#endif
}
void *
_glapi_get_context(void)
{
#if defined(THREADS)
if (ThreadSafe) {
return _glthread_GetTSD(&ContextTSD);
}
else {
return _glapi_Context;
}
#else
return _glapi_Context;
#endif
}
void
_glapi_set_dispatch(struct _glapi_table *dispatch)
{
if (!dispatch) {
dispatch = (struct _glapi_table *) __glapi_noop_table;
}
#ifdef DEBUG
else {
_glapi_check_table(dispatch);
}
#endif
#if defined(THREADS)
if (DispatchOverride) {
_glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
if (ThreadSafe)
_glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table;
else
_glapi_RealDispatch = dispatch;
}
else {
_glthread_SetTSD(&DispatchTSD, (void *) dispatch);
if (ThreadSafe)
_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
else
_glapi_Dispatch = dispatch;
}
#else
if (DispatchOverride) {
_glapi_RealDispatch = dispatch;
}
else {
_glapi_Dispatch = dispatch;
}
#endif
}
struct _glapi_table *
_glapi_get_dispatch(void)
{
#if defined(THREADS)
if (ThreadSafe) {
if (DispatchOverride) {
return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
}
else {
return (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD);
}
}
else {
if (DispatchOverride) {
assert(_glapi_RealDispatch);
return _glapi_RealDispatch;
}
else {
assert(_glapi_Dispatch);
return _glapi_Dispatch;
}
}
#else
return _glapi_Dispatch;
#endif
}
int
_glapi_begin_dispatch_override(struct _glapi_table *override)
{
struct _glapi_table *real = _glapi_get_dispatch();
assert(!DispatchOverride);
DispatchOverride = GL_TRUE;
_glapi_set_dispatch(real);
#if defined(THREADS)
_glthread_SetTSD(&DispatchTSD, (void *) override);
if (ThreadSafe)
_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
else
_glapi_Dispatch = override;
#else
_glapi_Dispatch = override;
#endif
return 1;
}
void
_glapi_end_dispatch_override(int layer)
{
struct _glapi_table *real = _glapi_get_dispatch();
(void) layer;
DispatchOverride = GL_FALSE;
_glapi_set_dispatch(real);
#if defined(THREADS)
_glthread_SetTSD(&RealDispatchTSD, NULL);
#endif
_glapi_RealDispatch = NULL;
}
struct _glapi_table *
_glapi_get_override_dispatch(int layer)
{
if (layer == 0) {
return _glapi_get_dispatch();
}
else {
if (DispatchOverride) {
#if defined(THREADS)
return (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD);
#else
return _glapi_Dispatch;
#endif
}
else {
return NULL;
}
}
}
struct name_address_offset {
const char *Name;
GLvoid *Address;
GLuint Offset;
};
#include "glprocs.h"
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 static_functions[i].Offset;
}
}
return -1;
}
static GLvoid *
get_static_proc_address(const char *funcName)
{
GLint i;
for (i = 0; static_functions[i].Name; i++) {
if (strcmp(static_functions[i].Name, funcName) == 0) {
return static_functions[i].Address;
}
}
return NULL;
}
#define MAX_EXTENSION_FUNCS 300
#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
static struct name_address_offset ExtEntryTable[MAX_EXTENSION_FUNCS];
static GLuint NumExtEntryPoints = 0;
#ifdef USE_SPARC_ASM
extern void __glapi_sparc_icache_flush(unsigned int *);
#endif
static void *
generate_entrypoint(GLuint functionOffset)
{
#if defined(USE_X86_ASM)
static const unsigned char insn_template[] = {
0xa1, 0x00, 0x00, 0x00, 0x00,
0x85, 0xc0,
0x74, 0x06,
0xff, 0xa0, 0x00, 0x00, 0x00, 0x00,
0xe8, 0x00, 0x00, 0x00, 0x00,
0xff, 0xa0, 0x00, 0x00, 0x00, 0x00
};
unsigned char *code = (unsigned char *) malloc(sizeof(insn_template));
unsigned int next_insn;
if (code) {
memcpy(code, insn_template, sizeof(insn_template));
*(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_Dispatch;
*(unsigned int *)(code + 0x0b) = (unsigned int)functionOffset * 4;
next_insn = (unsigned int)(code + 0x14);
*(unsigned int *)(code + 0x10) = (unsigned int)_glapi_get_dispatch - next_insn;
*(unsigned int *)(code + 0x16) = (unsigned int)functionOffset * 4;
}
return code;
#elif defined(USE_SPARC_ASM)
#if defined(__sparc_v9__) && !defined(__linux__)
#define SPARC_64BIT_ADDR
#endif
#ifdef SPARC_64BIT_ADDR
static const unsigned int insn_template[] = {
0x05000000,
0x03000000,
0x8410a000,
0x82106000,
0x8528b020,
0xc2584002,
0x05000000,
0x8410a000,
0xc6584002,
0x81c0c000,
0x01000000
};
#else
static const unsigned int insn_template[] = {
0x03000000,
0xc2006000,
0xc6006000,
0x81c0c000,
0x01000000
};
#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 SPARC_64BIT_ADDR
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 code;
#else
return NULL;
#endif
}
static void
fill_in_entrypoint_offset(void *entrypoint, GLuint offset)
{
#if defined(USE_X86_ASM)
unsigned char *code = (unsigned char *) entrypoint;
*(unsigned int *)(code + 0x0b) = offset * 4;
*(unsigned int *)(code + 0x16) = offset * 4;
#elif defined(USE_SPARC_ASM)
unsigned int *code = (unsigned int *) entrypoint;
#ifdef SPARC_64BIT_ADDR
code[6] = 0x05000000;
code[7] = 0x8410a000;
code[6] |= ((offset * 8) >> 10);
code[7] |= ((offset * 8) & ((1 << 10) - 1));
__glapi_sparc_icache_flush(&code[6]);
#else
code[2] = 0xc6006000;
code[2] |= (offset * 4);
__glapi_sparc_icache_flush(&code[2]);
#endif
#endif
}
GLboolean
_glapi_add_entrypoint(const char *funcName, GLuint offset)
{
if (!funcName || funcName[0] != 'g' || funcName[1] != 'l')
return GL_FALSE;
{
GLint index = get_static_proc_offset(funcName);
if (index >= 0) {
return (GLboolean) ((GLuint) index == offset);
}
}
{
GLuint i;
for (i = 0; i < NumExtEntryPoints; i++) {
if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
if (ExtEntryTable[i].Offset == offset) {
return GL_TRUE;
}
else if (ExtEntryTable[i].Offset == ~0
&& offset < DISPATCH_TABLE_SIZE) {
if (offset != ~0) {
fill_in_entrypoint_offset(ExtEntryTable[i].Address, offset);
ExtEntryTable[i].Offset = offset;
}
return GL_TRUE;
}
else {
return GL_FALSE;
}
}
}
}
if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS ||
offset >= DISPATCH_TABLE_SIZE) {
return GL_FALSE;
}
else {
void *entrypoint = generate_entrypoint(offset);
if (!entrypoint)
return GL_FALSE;
ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
ExtEntryTable[NumExtEntryPoints].Offset = offset;
ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
NumExtEntryPoints++;
return GL_TRUE;
}
return GL_FALSE;
}
GLint
_glapi_get_proc_offset(const char *funcName)
{
GLuint i;
for (i = 0; i < NumExtEntryPoints; i++) {
if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
return ExtEntryTable[i].Offset;
}
}
return get_static_proc_offset(funcName);
}
const GLvoid *
_glapi_get_proc_address(const char *funcName)
{
GLuint i;
if (funcName[0] != 'g' || funcName[1] != 'l')
return NULL;
for (i = 0; i < NumExtEntryPoints; i++) {
if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
return ExtEntryTable[i].Address;
}
}
{
const GLvoid *func = get_static_proc_address(funcName);
if (func)
return func;
}
if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
GLvoid *entrypoint = generate_entrypoint(~0);
if (!entrypoint)
return GL_FALSE;
ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
ExtEntryTable[NumExtEntryPoints].Offset = ~0;
ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
NumExtEntryPoints++;
return entrypoint;
}
else {
return NULL;
}
}
const char *
_glapi_get_proc_name(GLuint offset)
{
const GLuint n = sizeof(static_functions) / sizeof(struct name_address_offset);
GLuint i;
for (i = 0; i < n; i++) {
if (static_functions[i].Offset == offset)
return static_functions[i].Name;
}
for (i = 0; i < NumExtEntryPoints; i++) {
if (ExtEntryTable[i].Offset == offset) {
return ExtEntryTable[i].Name;
}
}
return NULL;
}
GLuint
_glapi_get_dispatch_table_size(void)
{
return DISPATCH_TABLE_SIZE;
}
const char *
_glapi_get_version(void)
{
return "20021001";
}
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]);
}
{
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") == (void *) &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") == (void *) &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") == (void *) &glSetFenceNV);
}
#endif
}