1116 lines
30 KiB
C
1116 lines
30 KiB
C
/*
|
|
** Copyright 1995-2095, Silicon Graphics, Inc.
|
|
** All Rights Reserved.
|
|
**
|
|
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
|
|
** the contents of this file may not be disclosed to third parties, copied or
|
|
** duplicated in any form, in whole or in part, without the prior written
|
|
** permission of Silicon Graphics, Inc.
|
|
**
|
|
** RESTRICTED RIGHTS LEGEND:
|
|
** Use, duplication or disclosure by the Government is subject to restrictions
|
|
** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
|
|
** and Computer Software clause at DFARS 252.227-7013, and/or in similar or
|
|
** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
|
|
** rights reserved under the Copyright Laws of the United States.
|
|
*/
|
|
|
|
#include "glslib.h"
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
|
|
/******************************************************************************
|
|
POSIX threads
|
|
******************************************************************************/
|
|
|
|
#if __GLS_POSIX_THREADS
|
|
|
|
#if !__GLS_FAKE_MUTEX
|
|
|
|
static pthread_mutex_t __gls_lock;
|
|
|
|
static const pthread_mutexattr_t __gls_lockInit = {
|
|
MUTEX_TYPE_FAST,
|
|
MUTEX_FLAGS_INITED,
|
|
};
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
if (pthread_mutex_lock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: pthread_mutex_lock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
if (pthread_mutex_unlock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: pthread_mutex_unlock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
|
|
pthread_key_t __gls_contextTLS;
|
|
pthread_key_t __gls_errorTLS;
|
|
|
|
__GLScontext* __glsGetContext(void) {
|
|
return (__GLScontext *)pthread_getspecific(__gls_contextTLS);
|
|
}
|
|
|
|
GLSenum __glsGetError(void) {
|
|
return (GLSenum)pthread_getspecific(__gls_errorTLS);
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
|
|
static void __glsFinalPthreads(void) {
|
|
#if !__GLS_FAKE_MUTEX
|
|
pthread_mutex_destroy(&__gls_lock);
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
pthread_key_delete(__gls_contextTLS);
|
|
pthread_key_delete(__gls_errorTLS);
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
}
|
|
|
|
static void __glsInitPthreads(void) {
|
|
#if !__GLS_FAKE_MUTEX
|
|
if (pthread_mutex_init(&__gls_lock, &__gls_lockInit)) {
|
|
fprintf(stderr, "GLS fatal: pthread_mutex_init failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
if (
|
|
pthread_key_create(&__gls_contextTLS, GLS_NONE) ||
|
|
pthread_key_create(&__gls_errorTLS, GLS_NONE)
|
|
) {
|
|
fprintf(stderr, "GLS fatal: pthread_key_create failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
}
|
|
|
|
#endif /* __GLS_POSIX_THREADS */
|
|
|
|
/******************************************************************************
|
|
These routines must be called during library loading/unloading
|
|
******************************************************************************/
|
|
|
|
static GLboolean __glsInitContextDict(void) {
|
|
__glsContextDict = __glsIntDict_create(1);
|
|
return (GLboolean)(__glsContextDict != GLS_NONE);
|
|
}
|
|
|
|
static void __glsFinalContextDict(void) {
|
|
__GLScontext *ctx;
|
|
__GLS_LIST_ITER(__GLScontext) iter;
|
|
|
|
__GLS_LIST_FIRST(&__glsContextList, &iter);
|
|
while (ctx = iter.elem) {
|
|
__GLS_LIST_NEXT(&__glsContextList, &iter);
|
|
__glsContext_destroy(ctx);
|
|
}
|
|
__glsIntDict_destroy(__glsContextDict);
|
|
}
|
|
|
|
/******************************************************************************
|
|
Fake lltostr
|
|
******************************************************************************/
|
|
|
|
#if __GLS_FAKE_LLTOSTR
|
|
|
|
char *ulltostr(GLulong inVal, char *outBuf) {
|
|
char buf[24];
|
|
char *p1 = buf;
|
|
char *p2 = outBuf;
|
|
|
|
do {
|
|
*p1++ = '0' + (char)(inVal % 10);
|
|
inVal /= 10;
|
|
} while (inVal);
|
|
while (--p1 >= buf) *p2++ = *p1;
|
|
*p2 = 0;
|
|
return outBuf;
|
|
}
|
|
|
|
char *lltostr(GLlong inVal, char *outBuf) {
|
|
char *p = outBuf;
|
|
|
|
if (inVal < 0) {
|
|
*p++ = '-';
|
|
inVal = -inVal;
|
|
}
|
|
ulltostr(inVal, p);
|
|
return outBuf;
|
|
}
|
|
|
|
#endif /* __GLS_FAKE_LLTOSTR */
|
|
|
|
/******************************************************************************
|
|
Fake mutex
|
|
******************************************************************************/
|
|
|
|
#if __GLS_FAKE_MUTEX
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
}
|
|
|
|
#endif /* __GLS_FAKE_MUTEX */
|
|
|
|
/******************************************************************************
|
|
Fake strtoll
|
|
******************************************************************************/
|
|
|
|
#if __GLS_FAKE_STRTOLL
|
|
|
|
#define __GLS_DIGIT(c) ( \
|
|
isdigit(c) ? c - '0' : islower(c) ? c - 'a' + 10 : c - 'A' + 10 \
|
|
)
|
|
|
|
#define __GLS_LL_MIN (-9223372036854775807LL-1LL)
|
|
#define __GLS_LL_MAX 9223372036854775807LL
|
|
#define __GLS_ULL_MAX 18446744073709551615LLU
|
|
|
|
static GLboolean __gls_strtoull(
|
|
const char *inStr, char **outPtr, GLboolean *outNeg, GLulong *outVal
|
|
) {
|
|
GLint base, c, d;
|
|
GLulong multMax, val;
|
|
const char **ptr = (const char **)outPtr;
|
|
|
|
if (ptr) *ptr = inStr;
|
|
*outNeg = GL_FALSE;
|
|
if (!isalnum(c = *inStr)) {
|
|
while (isspace(c)) c = *++inStr;
|
|
switch (c) {
|
|
case '-':
|
|
*outNeg = GL_TRUE;
|
|
c = *++inStr;
|
|
break;
|
|
case '+':
|
|
c = *++inStr;
|
|
break;
|
|
}
|
|
}
|
|
if (c != '0') {
|
|
base = 10;
|
|
} else if (inStr[1] == 'x' || inStr[1] == 'X') {
|
|
base = 16;
|
|
} else {
|
|
base = 8;
|
|
}
|
|
if (!isalnum(c) || __GLS_DIGIT(c) >= base) {
|
|
*outVal = 0;
|
|
return GL_TRUE;
|
|
}
|
|
if (base == 16 && isxdigit(inStr[2])) c = *(inStr += 2);
|
|
multMax = __GLS_ULL_MAX / base;
|
|
val = __GLS_DIGIT(c);
|
|
for (c = *++inStr; isalnum(c) && (d = __GLS_DIGIT(c)) < base; ) {
|
|
if (val > multMax) goto overflow;
|
|
val *= base;
|
|
if (__GLS_ULL_MAX - val < d) goto overflow;
|
|
val += d;
|
|
c = *++inStr;
|
|
}
|
|
if (ptr) *ptr = inStr;
|
|
*outVal = val;
|
|
return GL_TRUE;
|
|
overflow:
|
|
for (c = *++inStr; isalnum(c) && __GLS_DIGIT(c) < base; c = *++inStr);
|
|
if (ptr) *ptr = inStr;
|
|
return GL_FALSE;
|
|
}
|
|
|
|
extern GLlong strtoll(const char *inStr, char **outPtr, int inBase) {
|
|
GLboolean neg;
|
|
GLulong outVal;
|
|
|
|
if (
|
|
!__gls_strtoull(inStr, outPtr, &neg, &outVal) ||
|
|
outVal > (GLulong)__GLS_LL_MAX + (GLulong)neg
|
|
) {
|
|
__GLS_PUT_ERRNO(ERANGE);
|
|
return neg ? __GLS_LL_MIN : __GLS_LL_MAX;
|
|
} else {
|
|
return neg ? -outVal : outVal;
|
|
}
|
|
}
|
|
|
|
extern GLulong strtoull(const char *inStr, char **outPtr, int inBase) {
|
|
GLboolean neg;
|
|
GLulong outVal;
|
|
|
|
if (!__gls_strtoull(inStr, outPtr, &neg, &outVal)) {
|
|
__GLS_PUT_ERRNO(ERANGE);
|
|
return __GLS_ULL_MAX;
|
|
} else {
|
|
return neg ? -outVal : outVal;
|
|
}
|
|
}
|
|
|
|
#endif /* __GLS_FAKE_STRTOLL */
|
|
|
|
/******************************************************************************
|
|
Fake thread-local storage
|
|
******************************************************************************/
|
|
|
|
#if __GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
__GLScontext *__gls_context;
|
|
GLSenum __gls_error;
|
|
#endif /* __GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
|
|
/******************************************************************************
|
|
2-level GL dispatch with GLS library defining all GL entry points
|
|
******************************************************************************/
|
|
|
|
#if __GLS_GL_DISPATCH
|
|
|
|
#if __GLS_PLATFORM_WIN32
|
|
|
|
#include <gldrv.h>
|
|
#include <exttable.h>
|
|
|
|
// Version 1.1 table mapping
|
|
static GLSopcode opGl11Procs[] =
|
|
{
|
|
GLS_OP_glArrayElement,
|
|
GLS_OP_glBindTexture,
|
|
GLS_OP_glColorPointer,
|
|
GLS_OP_glDisableClientState,
|
|
GLS_OP_glDrawArrays,
|
|
GLS_OP_glDrawElements,
|
|
GLS_OP_glEdgeFlagPointer,
|
|
GLS_OP_glEnableClientState,
|
|
GLS_OP_glIndexPointer,
|
|
GLS_OP_glIndexub,
|
|
GLS_OP_glIndexubv,
|
|
GLS_OP_glInterleavedArrays,
|
|
GLS_OP_glNormalPointer,
|
|
GLS_OP_glPolygonOffset,
|
|
GLS_OP_glTexCoordPointer,
|
|
GLS_OP_glVertexPointer,
|
|
GLS_OP_glAreTexturesResident,
|
|
GLS_OP_glCopyTexImage1D,
|
|
GLS_OP_glCopyTexImage2D,
|
|
GLS_OP_glCopyTexSubImage1D,
|
|
GLS_OP_glCopyTexSubImage2D,
|
|
GLS_OP_glDeleteTextures,
|
|
GLS_OP_glGenTextures,
|
|
GLS_OP_glGetPointerv,
|
|
GLS_OP_glIsTexture,
|
|
GLS_OP_glPrioritizeTextures,
|
|
GLS_OP_glTexSubImage1D,
|
|
GLS_OP_glTexSubImage2D,
|
|
GLS_OP_glPopClientAttrib,
|
|
GLS_OP_glPushClientAttrib,
|
|
};
|
|
#define GL11_PROCS (sizeof(opGl11Procs)/sizeof(opGl11Procs[0]))
|
|
|
|
// Extension function mapping
|
|
static GLSopcode opExtProcs[] =
|
|
{
|
|
GLS_OP_glDrawRangeElementsWIN,
|
|
GLS_OP_glColorTableEXT,
|
|
GLS_OP_glColorSubTableEXT,
|
|
GLS_OP_glGetColorTableEXT,
|
|
GLS_OP_glGetColorTableParameterivEXT,
|
|
GLS_OP_glGetColorTableParameterfvEXT
|
|
};
|
|
#define EXT_PROCS (sizeof(opExtProcs)/sizeof(opExtProcs[0]))
|
|
|
|
// DrewB
|
|
void glsUpdateCaptureExecTable(GLCLTPROCTABLE *pgcpt, GLEXTPROCTABLE *pgept)
|
|
{
|
|
GLint i;
|
|
GLSopcode op;
|
|
__GLScontext *ctx = __GLS_CONTEXT;
|
|
GLSfunc *pgfn;
|
|
|
|
if (ctx == NULL)
|
|
{
|
|
#if DBG
|
|
OutputDebugString(TEXT("glsUpdateCaptureExecTable call ignored\n"));
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
ctx->captureExecOverride = GL_TRUE;
|
|
|
|
// Copy over standard 1.0 entries
|
|
// The ordering is the same between OpenGL and GLS so straight copy works
|
|
memcpy(&ctx->captureExec[GLS_OP_glNewList], &pgcpt->glDispatchTable,
|
|
OPENGL_VERSION_100_ENTRIES*sizeof(GLSfunc));
|
|
|
|
// If the dispatch table contains 1.1 entries, map them in
|
|
pgfn = (GLSfunc *)&pgcpt->glDispatchTable.glArrayElement;
|
|
if (pgcpt->cEntries == OPENGL_VERSION_110_ENTRIES)
|
|
{
|
|
for (i = 0; i < GL11_PROCS; i++)
|
|
{
|
|
op = __glsMapOpcode(opGl11Procs[i]);
|
|
ctx->captureExec[op] = *pgfn++;
|
|
}
|
|
}
|
|
#if DBG
|
|
else if (pgcpt->cEntries != OPENGL_VERSION_100_ENTRIES)
|
|
{
|
|
OutputDebugString("glsUpdateCaptureExecTable clt table size wrong\n");
|
|
}
|
|
#endif
|
|
|
|
// Map in extension functions
|
|
#if DBG
|
|
if (pgept->cEntries != EXT_PROCS)
|
|
{
|
|
OutputDebugString("glsUpdateCaptureExecTable ext table size wrong\n");
|
|
}
|
|
#endif
|
|
pgfn = (GLSfunc *)&pgept->glDispatchTable;
|
|
for (i = 0; i < EXT_PROCS; i++)
|
|
{
|
|
op = __glsMapOpcode(opExtProcs[i]);
|
|
ctx->captureExec[op] = *pgfn++;
|
|
}
|
|
}
|
|
|
|
void __glsMapGlsTableToGl(const GLSfunc *pgfnGlsTable,
|
|
GLCLTPROCTABLE *pgcpt, GLEXTPROCTABLE *pgept)
|
|
{
|
|
GLint i;
|
|
GLSopcode op;
|
|
GLSfunc *pgfn;
|
|
|
|
#if DBG
|
|
if (sizeof(GLDISPATCHTABLE)/sizeof(PROC) < OPENGL_VERSION_110_ENTRIES)
|
|
{
|
|
OutputDebugString("__glsMapGlsTableToGl GLDISPATCHTABLE too small\n");
|
|
}
|
|
#endif
|
|
|
|
// GLS supports all 1.1 functions so set a 1.1 entry count
|
|
pgcpt->cEntries = OPENGL_VERSION_110_ENTRIES;
|
|
pgept->cEntries = EXT_PROCS;
|
|
|
|
// Copy over standard 1.0 entries
|
|
// The ordering is the same between OpenGL and GLS so straight copy works
|
|
memcpy(&pgcpt->glDispatchTable, &pgfnGlsTable[GLS_OP_glNewList],
|
|
OPENGL_VERSION_100_ENTRIES*sizeof(GLSfunc));
|
|
|
|
// Map in 1.1 entries
|
|
pgfn = (GLSfunc *)&pgcpt->glDispatchTable.glArrayElement;
|
|
for (i = 0; i < GL11_PROCS; i++)
|
|
{
|
|
op = __glsMapOpcode(opGl11Procs[i]);
|
|
*pgfn++ = pgfnGlsTable[op];
|
|
}
|
|
|
|
// Map in extension functions
|
|
pgfn = (GLSfunc *)&pgept->glDispatchTable;
|
|
for (i = 0; i < EXT_PROCS; i++)
|
|
{
|
|
op = __glsMapOpcode(opExtProcs[i]);
|
|
*pgfn++ = pgfnGlsTable[op];
|
|
}
|
|
}
|
|
void glsGetCaptureExecTable(GLCLTPROCTABLE *pgcpt, GLEXTPROCTABLE *pgept)
|
|
{
|
|
__GLScontext *ctx = __GLS_CONTEXT;
|
|
|
|
if (ctx == NULL ||
|
|
!ctx->captureExecOverride)
|
|
{
|
|
#if DBG
|
|
OutputDebugString(TEXT("glsGetCaptureExecTable call ignored\n"));
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
__glsMapGlsTableToGl(ctx->captureExec, pgcpt, pgept);
|
|
}
|
|
|
|
void glsGetCaptureDispatchTable(GLCLTPROCTABLE *pgcpt, GLEXTPROCTABLE *pgept)
|
|
{
|
|
__glsMapGlsTableToGl(__glsDispatchCapture, pgcpt, pgept);
|
|
}
|
|
|
|
void __glsBeginCaptureExec(__GLScontext *ctx, GLSopcode inOpcode) {
|
|
if (!ctx->captureNesting) return;
|
|
inOpcode = __glsMapOpcode(inOpcode);
|
|
if (ctx->captureExecOverride)
|
|
{
|
|
ctx->dispatchAPI[inOpcode] = ctx->captureExec[inOpcode];
|
|
}
|
|
else
|
|
{
|
|
ctx->dispatchAPI[inOpcode] = __glsDispatchExec[inOpcode];
|
|
}
|
|
}
|
|
|
|
void __glsEndCaptureExec(__GLScontext *ctx, GLSopcode inOpcode) {
|
|
if (!ctx->captureNesting) return;
|
|
inOpcode = __glsMapOpcode(inOpcode);
|
|
ctx->dispatchAPI[inOpcode] = (
|
|
(GLSfunc)__glsDispatchCapture[inOpcode]
|
|
);
|
|
}
|
|
#else
|
|
void __glsBeginCaptureExec(GLSopcode inOpcode) {
|
|
if (!__GLS_CONTEXT->captureNesting) return;
|
|
inOpcode = __glsMapOpcode(inOpcode);
|
|
__GLS_CONTEXT->dispatchAPI[inOpcode] = __glsDispatchExec[inOpcode];
|
|
}
|
|
|
|
void __glsEndCaptureExec(GLSopcode inOpcode) {
|
|
if (!__GLS_CONTEXT->captureNesting) return;
|
|
inOpcode = __glsMapOpcode(inOpcode);
|
|
__GLS_CONTEXT->dispatchAPI[inOpcode] = (
|
|
(GLSfunc)__glsDispatchCapture[inOpcode]
|
|
);
|
|
}
|
|
#endif
|
|
|
|
void __glsUpdateDispatchTables(void) {
|
|
}
|
|
|
|
#include "g_glapi.c"
|
|
|
|
#endif /* __GLS_GL_DISPATCH */
|
|
|
|
/******************************************************************************
|
|
If using DSOs for the 2-level dispatch, use this DSO init function as well
|
|
******************************************************************************/
|
|
|
|
#if __GLS_GL_DISPATCH_DSO
|
|
|
|
#include <dlfcn.h>
|
|
|
|
static void __glsInitGLDispatch_DSO(void) {
|
|
GLvoid *const dso = dlopen(__GL_LIB_NAME, RTLD_LAZY);
|
|
GLint i;
|
|
GLSopcode op;
|
|
|
|
if (!dso) {
|
|
fprintf(stderr, "GLS fatal: dlopen failed on %s\n", __GL_LIB_NAME);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
for (i = 0 ; op = __glsMapOpcode(__glsOpcodesGL[i]) ; ++i) {
|
|
const GLSfunc func = (
|
|
(GLSfunc) dlsym(dso, (const char *)__glsOpcodeString[op])
|
|
);
|
|
|
|
__glsDispatchExec[op] = func ? func : __glsNop;
|
|
}
|
|
}
|
|
|
|
#endif /* __GLS_GL_DISPATCH_DSO */
|
|
|
|
/******************************************************************************
|
|
Null command func
|
|
******************************************************************************/
|
|
|
|
#if __GLS_SINGLE_NULL_COMMAND_FUNC
|
|
|
|
GLSfunc glsNullCommandFunc(GLSopcode inOpcode) {
|
|
if (!__glsValidateOpcode(inOpcode)) return GLS_NONE;
|
|
return (GLSfunc)__glsNop;
|
|
}
|
|
|
|
#endif /* __GLS_SINGLE_NULL_COMMAND_FUNC */
|
|
|
|
/******************************************************************************
|
|
AIX
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_AIX
|
|
|
|
#include <a.out.h>
|
|
#include <ldfcn.h>
|
|
#include <string.h>
|
|
#include <sys/ldr.h>
|
|
|
|
static void __glsInitSA(void) {
|
|
GLint i;
|
|
LDFILE *ldFile = GLS_NONE;
|
|
LDHDR *ldHdr;
|
|
struct ld_info *ldInfo;
|
|
GLvoid *ldInfoBuf = GLS_NONE;
|
|
GLint ldInfoBufSize = 4096;
|
|
LDSYM *ldSym;
|
|
GLSopcode op;
|
|
GLubyte *scnBuf;
|
|
SCNHDR scnHdr;
|
|
|
|
if (0) __gls_glRef();
|
|
for (;;) {
|
|
ldInfoBuf = realloc(ldInfoBuf, ldInfoBufSize);
|
|
if (!ldInfoBuf) {
|
|
fprintf(stderr, "GLS fatal: realloc for loadquery failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (loadquery(L_GETINFO, ldInfoBuf, ldInfoBufSize) != -1) break;
|
|
if (__GLS_ERRNO != ENOMEM) {
|
|
fprintf(stderr, "GLS fatal: loadquery failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
ldInfoBufSize <<= 1;
|
|
}
|
|
ldInfo = (struct ld_info *)ldInfoBuf;
|
|
for (;;) {
|
|
if (strstr(ldInfo->ldinfo_filename, __GL_LIB_NAME)) break;
|
|
if (!ldInfo->ldinfo_next) {
|
|
fprintf(stderr, "GLS fatal: %s not loaded\n", __GL_LIB_NAME);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
ldInfo = (struct ld_info *)((GLubyte *)ldInfo + ldInfo->ldinfo_next);
|
|
}
|
|
ldFile = ldopen(ldInfo->ldinfo_filename, ldFile);
|
|
if (!ldFile) {
|
|
fprintf(
|
|
stderr,
|
|
"GLS fatal: ldopen failed on %s\n",
|
|
ldInfo->ldinfo_filename
|
|
);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (ldnshread(ldFile, _LOADER, &scnHdr) != SUCCESS) {
|
|
fprintf(stderr, "GLS fatal: ldnshread failed on %s\n", __GL_LIB_NAME);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
scnBuf = (GLubyte *)malloc(scnHdr.s_size);
|
|
if (!scnBuf) {
|
|
fprintf(stderr, "GLS fatal: malloc for scnBuf failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (FSEEK(ldFile, scnHdr.s_scnptr, BEGINNING) != OKFSEEK) {
|
|
fprintf(stderr, "GLS fatal: FSEEK failed on %s\n", __GL_LIB_NAME);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (FREAD((char *)scnBuf, scnHdr.s_size, 1, ldFile) != 1) {
|
|
fprintf(stderr, "GLS fatal: FREAD failed on %s\n", __GL_LIB_NAME);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
for (i = 0 ; op = __glsMapOpcode(__glsOpcodesGL[i]) ; ++i) {
|
|
__glsDispatchExec[op] = __glsNop;
|
|
}
|
|
__glsParser = __glsParser_create();
|
|
ldHdr = (LDHDR *)scnBuf;
|
|
ldSym = (LDSYM *)(scnBuf + LDHDRSZ);
|
|
for (i = 0 ; i < ldHdr->l_nsyms ; ++i, ++ldSym) {
|
|
GLubyte *sym;
|
|
|
|
if (!LDR_EXPORT(*ldSym)) continue;
|
|
if (ldSym->l_zeroes) {
|
|
sym = (GLubyte *)ldSym->l_name;
|
|
} else {
|
|
sym = scnBuf + ldHdr->l_stoff + ldSym->l_offset;
|
|
}
|
|
if (__glsStr2IntDict_find(__glsParser->glsOpDict, sym, (GLint*)&op)) {
|
|
__glsDispatchExec[__glsMapOpcode(op)] = (GLSfunc)(
|
|
(GLubyte *)ldInfo->ldinfo_dataorg + ldSym->l_value
|
|
);
|
|
}
|
|
}
|
|
free(ldInfoBuf);
|
|
free(scnBuf);
|
|
while(ldclose(ldFile) == FAILURE);
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
static GLboolean __glsInitDone;
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
if (!__glsInitDone) {
|
|
__glsInitSA();
|
|
__glsInitDone = GL_TRUE;
|
|
}
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
}
|
|
|
|
#endif /* __GLS_PLATFORM_AIX */
|
|
|
|
/******************************************************************************
|
|
DECUNIX
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_DECUNIX
|
|
|
|
|
|
#if !__GLS_FAKE_MUTEX
|
|
|
|
static pthread_mutex_t __gls_lock;
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
if (pthread_mutex_lock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: pthread_mutex_lock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
if (pthread_mutex_unlock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: pthread_mutex_unlock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
|
|
pthread_key_t __gls_contextTLS;
|
|
pthread_key_t __gls_errorTLS;
|
|
|
|
__GLScontext* __glsGetContext(void) {
|
|
__GLScontext *outContext;
|
|
|
|
pthread_getspecific(__gls_contextTLS, (pthread_addr_t *)&outContext);
|
|
return outContext;
|
|
}
|
|
|
|
GLSenum __glsGetError(void) {
|
|
GLvoid *outError;
|
|
|
|
pthread_getspecific(__gls_errorTLS, (pthread_addr_t *)&outError);
|
|
return (GLSenum)outError;
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
|
|
void __glsFinalDSO(void) {
|
|
__glsFinalContextDict();
|
|
__glsParser_destroy(__glsParser);
|
|
#if !__GLS_FAKE_MUTEX
|
|
pthread_mutex_destroy(&__gls_lock);
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
}
|
|
|
|
void __glsInitDSO(void) {
|
|
#if __GLS_GL_DISPATCH_DSO
|
|
__glsInitGLDispatch_DSO();
|
|
#endif /* __GLS_GL_DISPATCH_DSO */
|
|
#if !__GLS_FAKE_MUTEX
|
|
if (pthread_mutex_init(&__gls_lock, pthread_mutexattr_default)) {
|
|
fprintf(stderr, "GLS fatal: pthread_mutex_init failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
if (
|
|
pthread_keycreate(&__gls_contextTLS, GLS_NONE) ||
|
|
pthread_keycreate(&__gls_errorTLS, GLS_NONE)
|
|
) {
|
|
fprintf(stderr, "GLS fatal: pthread_keycreate failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* __GLS_PLATFORM_DECUNIX */
|
|
|
|
/******************************************************************************
|
|
HPUX
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_HPUX
|
|
|
|
#include <dl.h>
|
|
|
|
void __glsInitSL(void) {
|
|
GLint i;
|
|
GLSopcode op;
|
|
shl_t sl = shl_load(__GL_LIB_NAME, BIND_DEFERRED | DYNAMIC_PATH, 0);
|
|
|
|
if (!sl) {
|
|
fprintf(stderr, "GLS fatal: shl_load failed on %s\n", __GL_LIB_NAME);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
for (i = 0 ; op = __glsMapOpcode(__glsOpcodesGL[i]) ; ++i) {
|
|
GLSfunc func;
|
|
|
|
if (
|
|
!shl_findsym(
|
|
&sl,
|
|
(const char *)__glsOpcodeString[op],
|
|
TYPE_PROCEDURE,
|
|
&func
|
|
)
|
|
) {
|
|
__glsDispatchExec[op] = func;
|
|
} else {
|
|
__glsDispatchExec[op] = __glsNop;
|
|
}
|
|
}
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* __GLS_PLATFORM_HPUX */
|
|
|
|
/******************************************************************************
|
|
IRIX
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_IRIX
|
|
|
|
#if !__GLS_FAKE_MUTEX
|
|
|
|
#include <abi_mutex.h>
|
|
|
|
static abilock_t __gls_lock;
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
spin_lock(&__gls_lock);
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
if (release_lock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: release_lock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
|
|
void __glsFinalDSO(void) {
|
|
__glsFinalContextDict();
|
|
__glsParser_destroy(__glsParser);
|
|
}
|
|
|
|
void __glsInitDSO(void) {
|
|
#if __GLS_GL_DISPATCH_DSO
|
|
__glsInitGLDispatch_DSO();
|
|
#endif /* __GLS_GL_DISPATCH_DSO */
|
|
#if !__GLS_FAKE_MUTEX
|
|
if (init_lock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: init_lock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#if !__GLS_GL_DISPATCH
|
|
|
|
#include "glxclient.h"
|
|
|
|
extern __GLdispatchState __glDispatchCapture;
|
|
|
|
void __glsBeginCaptureExec(GLSopcode inOpcode) {
|
|
if (!__gl_dispatchOverride) return;
|
|
__gl_dispatch = *__glXDispatchExec();
|
|
}
|
|
|
|
void __glsEndCaptureExec(GLSopcode inOpcode) {
|
|
if (!__gl_dispatchOverride) return;
|
|
__gl_dispatch = __glDispatchCapture;
|
|
}
|
|
|
|
void __glsUpdateDispatchTables(void) {
|
|
if (__GLS_CONTEXT && __GLS_CONTEXT->captureNesting) {
|
|
__glXBeginDispatchOverride(&__glDispatchCapture);
|
|
} else if (!__GLS_CONTEXT || !__GLS_CONTEXT->captureNesting) {
|
|
__glXEndDispatchOverride();
|
|
}
|
|
}
|
|
|
|
#include "g_irix.c"
|
|
|
|
#endif /* !__GLS_GL_DISPATCH */
|
|
|
|
#endif /* __GLS_PLATFORM_IRIX */
|
|
|
|
/******************************************************************************
|
|
LINUX
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_LINUX
|
|
|
|
void __glsFinalDSO(void) __attribute__ ((destructor));
|
|
void __glsInitDSO(void) __attribute__ ((constructor));
|
|
|
|
void __glsFinalDSO(void) {
|
|
__glsFinalContextDict();
|
|
__glsParser_destroy(__glsParser);
|
|
#if __GLS_POSIX_THREADS
|
|
__glsFinalPthreads();
|
|
#endif /* __GLS_POSIX_THREADS */
|
|
}
|
|
|
|
void __glsInitDSO(void) {
|
|
#if __GLS_GL_DISPATCH_DSO
|
|
__glsInitGLDispatch_DSO();
|
|
#endif /* __GLS_GL_DISPATCH_DSO */
|
|
#if __GLS_POSIX_THREADS
|
|
__glsInitPthreads();
|
|
#endif /* __GLS_POSIX_THREADS */
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* __GLS_PLATFORM_LINUX */
|
|
|
|
/******************************************************************************
|
|
SOLARIS
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_SOLARIS
|
|
|
|
#if !__GLS_FAKE_MUTEX
|
|
|
|
#include <synch.h>
|
|
|
|
static mutex_t __gls_lock;
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
if (mutex_lock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: mutex_lock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
if (mutex_unlock(&__gls_lock)) {
|
|
fprintf(stderr, "GLS fatal: mutex_unlock failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
|
|
#include <thread.h>
|
|
|
|
thread_key_t __gls_contextTLS;
|
|
thread_key_t __gls_errorTLS;
|
|
|
|
__GLScontext* __glsGetContext(void) {
|
|
__GLScontext *outContext;
|
|
|
|
thr_getspecific(__gls_contextTLS, (GLvoid **)&outContext);
|
|
return outContext;
|
|
}
|
|
|
|
GLSenum __glsGetError(void) {
|
|
GLvoid *outError;
|
|
|
|
thr_getspecific(__gls_errorTLS, &outError);
|
|
return (GLSenum)outError;
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
|
|
#pragma fini(__glsFinalDSO)
|
|
#pragma init(__glsInitDSO)
|
|
|
|
void __glsFinalDSO(void) {
|
|
__glsFinalContextDict();
|
|
__glsParser_destroy(__glsParser);
|
|
#if !__GLS_FAKE_MUTEX
|
|
mutex_destroy(&__gls_lock);
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
}
|
|
|
|
void __glsInitDSO(void) {
|
|
#if __GLS_GL_DISPATCH_DSO
|
|
__glsInitGLDispatch_DSO();
|
|
#endif /* __GLS_GL_DISPATCH_DSO */
|
|
#if !__GLS_FAKE_MUTEX
|
|
if (mutex_init(&__gls_lock, USYNC_THREAD, GLS_NONE)) {
|
|
fprintf(stderr, "GLS fatal: mutex_init failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
if (
|
|
thr_keycreate(&__gls_contextTLS, GLS_NONE) ||
|
|
thr_keycreate(&__gls_errorTLS, GLS_NONE)
|
|
) {
|
|
fprintf(stderr, "GLS fatal: thr_keycreate failed\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
#endif /* __GLS_PLATFORM_SOLARIS */
|
|
|
|
/******************************************************************************
|
|
WIN32
|
|
******************************************************************************/
|
|
|
|
#if __GLS_PLATFORM_WIN32
|
|
|
|
#include <string.h>
|
|
#include "g_win32.c"
|
|
|
|
#if !__GLS_FAKE_MUTEX
|
|
|
|
static CRITICAL_SECTION __gls_lock;
|
|
|
|
void __glsBeginCriticalSection(void) {
|
|
EnterCriticalSection(&__gls_lock);
|
|
}
|
|
|
|
void __glsEndCriticalSection(void) {
|
|
LeaveCriticalSection(&__gls_lock);
|
|
}
|
|
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
GLint __gls_contextTLS;
|
|
GLint __gls_errorTLS;
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
|
|
// DrewB
|
|
typedef PROC (APIENTRY *wglGetDefaultProcAddressFunc)(LPCSTR);
|
|
|
|
BOOL __glsDLLProcessAttach(void) {
|
|
GLvoid *const dll = LoadLibrary(__GL_LIB_NAME);
|
|
GLint i;
|
|
GLSopcode op;
|
|
// DrewB
|
|
wglGetDefaultProcAddressFunc pfnGetDefaultProcAddress;
|
|
|
|
if (!dll) {
|
|
fprintf(
|
|
stderr, "GLS fatal: LoadLibrary failed on %s\n", __GL_LIB_NAME
|
|
);
|
|
return GL_FALSE;
|
|
}
|
|
|
|
// DrewB
|
|
pfnGetDefaultProcAddress = (wglGetDefaultProcAddressFunc)
|
|
GetProcAddress(dll, "wglGetDefaultProcAddress");
|
|
|
|
for (i = 0 ; op = __glsMapOpcode(__glsOpcodesGL[i]) ; ++i) {
|
|
GLSfunc func;
|
|
|
|
func = (GLSfunc) GetProcAddress(dll, __glsOpcodeString[op]);
|
|
if (func == NULL)
|
|
{
|
|
func = (GLSfunc) pfnGetDefaultProcAddress(__glsOpcodeString[op]);
|
|
}
|
|
|
|
__glsDispatchExec[op] = func ? func : __glsNullCommandFuncs[op];
|
|
}
|
|
|
|
for (i = 0 ; i < __GLS_OPCODE_COUNT ; ++i) {
|
|
if (__glsOpcodeAttrib[i] & __GLS_COMMAND_0_PARAMS_BIT) {
|
|
__glsDispatchDecode_bin_default[i] =
|
|
__glsDispatchDecode_bin_swap[i];
|
|
}
|
|
}
|
|
|
|
#if !__GLS_FAKE_MUTEX
|
|
__try
|
|
{
|
|
InitializeCriticalSection(&__gls_lock);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
return GL_FALSE;
|
|
}
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
__gls_contextTLS = TlsAlloc();
|
|
__gls_errorTLS = TlsAlloc();
|
|
if (__gls_contextTLS == -1 || __gls_errorTLS == -1) {
|
|
fprintf(stderr, "GLS fatal: TlsAlloc failed\n");
|
|
return GL_FALSE;
|
|
}
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
if (!__glsInitContextDict()) {
|
|
fprintf(stderr, "GLS fatal: couldn't create __glsContextDict\n");
|
|
return GL_FALSE;
|
|
}
|
|
return GL_TRUE;
|
|
}
|
|
|
|
BOOL __glsDLLProcessDetach(void) {
|
|
__glsFinalContextDict();
|
|
__glsParser_destroy(__glsParser);
|
|
#if !__GLS_FAKE_MUTEX
|
|
DeleteCriticalSection(&__gls_lock);
|
|
#endif /* !__GLS_FAKE_MUTEX */
|
|
#if !__GLS_FAKE_THREAD_LOCAL_STORAGE
|
|
TlsFree(__gls_contextTLS);
|
|
TlsFree(__gls_errorTLS);
|
|
#endif /* !__GLS_FAKE_THREAD_LOCAL_STORAGE */
|
|
return GL_TRUE;
|
|
}
|
|
|
|
BOOL DllMain(HINSTANCE hModule, DWORD inReason, LPVOID inReserved) {
|
|
inReserved;
|
|
switch (inReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
return __glsDLLProcessAttach();
|
|
case DLL_PROCESS_DETACH:
|
|
return __glsDLLProcessDetach();
|
|
}
|
|
return GL_TRUE;
|
|
}
|
|
|
|
GLlong __gls_strtoi64(const char *inStr, char **outPtr, int inBase) {
|
|
GLlong outVal;
|
|
|
|
inBase;
|
|
if (sscanf(inStr, "%I64i", &outVal) == 1) {
|
|
if (outPtr) *outPtr = (char *)inStr + strlen(inStr);
|
|
return outVal;
|
|
} else {
|
|
if (outPtr) *outPtr = (char *)inStr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
GLulong __gls_strtoui64(const char *inStr, char **outPtr, int inBase) {
|
|
GLulong outVal;
|
|
|
|
inBase;
|
|
if (sscanf(inStr, "%I64i", &outVal) ==1) {
|
|
if (outPtr) *outPtr = (char *)inStr + strlen(inStr);
|
|
return outVal;
|
|
} else {
|
|
if (outPtr) *outPtr = (char *)inStr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
GLSfunc glsNullCommandFunc(GLSopcode inOpcode) {
|
|
if (!__glsValidateOpcode(inOpcode)) return GLS_NONE;
|
|
return __glsNullCommandFuncs[__glsMapOpcode(inOpcode)];
|
|
}
|
|
|
|
#endif /* __GLS_PLATFORM_WIN32 */
|
|
|
|
/*****************************************************************************/
|