/* ** 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 #include static GLuint __glsContextCount = 0; static GLuint __glsNextContext = 1; typedef struct { GLuint mask1; GLuint val1; GLuint shift; GLuint mask4; GLuint val4; } __GLSutf8format; static const __GLSutf8format __glsUTF8formats[] = { {0x80, 0x00, 0, 0x0000007f, 0x00000000,}, {0xe0, 0xc0, 6, 0x000007ff, 0x00000080,}, {0xf0, 0xe0, 12, 0x0000ffff, 0x00000800,}, {0xf8, 0xf0, 18, 0x001fffff, 0x00010000,}, {0xfc, 0xf8, 24, 0x03ffffff, 0x00200000,}, {0xfe, 0xfc, 30, 0x7fffffff, 0x04000000,}, {0x00, 0x00, 0, 0x00000000, 0x00000000,}, }; GLSenum glsBinary(GLboolean inSwapped) { return inSwapped ? __GLS_BINARY_SWAP1 : __GLS_BINARY_SWAP0; } GLSenum glsCommandAPI(GLSopcode inOpcode) { const GLSenum outVal = __glsOpcodeAPI(inOpcode); if (!outVal) __GLS_RAISE_ERROR(GLS_UNSUPPORTED_COMMAND); return outVal; } const GLubyte* glsCommandString(GLSopcode inOpcode) { if (!__glsValidateOpcode(inOpcode)) return GLS_NONE; return __glsOpcodeString[__glsMapOpcode(inOpcode)]; } void glsContext(GLuint inContext) { __GLScontext *ctx = __GLS_CONTEXT; __GLScontext *newCtx; if (ctx && (ctx->callNesting || ctx->captureEntryCount)) { __GLS_RAISE_ERROR(GLS_INVALID_OPERATION); return; } if (inContext) { __glsBeginCriticalSection(); if ( newCtx = (__GLScontext *)__glsInt2PtrDict_find( __glsContextDict, (GLint)inContext ) ) { if (newCtx == ctx) { newCtx = GLS_NONE; } else { if (newCtx->current) { __GLS_RAISE_ERROR(GLS_INVALID_OPERATION); newCtx = GLS_NONE; } else { newCtx->current = GL_TRUE; if (ctx) { if (ctx->deleted) { __glsContext_destroy(ctx); } else { ctx->current = GL_FALSE; } } } } } else { __GLS_RAISE_ERROR(GLS_NOT_FOUND); } __glsEndCriticalSection(); if (newCtx) { __GLS_PUT_CONTEXT(newCtx); __glsUpdateDispatchTables(); } } else if (ctx) { __glsBeginCriticalSection(); if (ctx->deleted) { __glsContext_destroy(ctx); } else { ctx->current = GL_FALSE; } __glsEndCriticalSection(); __GLS_PUT_CONTEXT(GLS_NONE); __glsUpdateDispatchTables(); } } void glsDeleteContext(GLuint inContext) { if (inContext) { __GLScontext *ctx; __glsBeginCriticalSection(); if ( ctx = (__GLScontext *)__glsInt2PtrDict_find( __glsContextDict, (GLint)inContext ) ) { __glsIntDict_remove(__glsContextDict, (GLint)inContext); __GLS_LIST_REMOVE(&__glsContextList, ctx); --__glsContextCount; if (ctx->current) { ctx->deleted = GL_TRUE; } else { __glsContext_destroy(ctx); } } else { __GLS_RAISE_ERROR(GLS_NOT_FOUND); } __glsEndCriticalSection(); } else { __GLS_RAISE_ERROR(GLS_INVALID_VALUE); } } const GLubyte* glsEnumString(GLSenum inAPI, GLSenum inEnum) { GLint offset, page; switch (inAPI) { case GLS_API_GLS: page = __GLS_ENUM_PAGE(inEnum); offset = __GLS_ENUM_OFFSET(inEnum); if ( page < __GLS_ENUM_PAGE_COUNT && offset < __glsEnumStringCount[page] && __glsEnumString[page][offset] ) { return __glsEnumString[page][offset]; } break; case GLS_API_GL: page = __GL_ENUM_PAGE(inEnum); offset = __GL_ENUM_OFFSET(inEnum); if ( page < __GL_ENUM_PAGE_COUNT && offset < __glEnumStringCount[page] && __glEnumString[page][offset] ) { return __glEnumString[page][offset]; } break; } __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } GLuint glsGenContext(void) { GLboolean added = GL_FALSE; __GLScontext *ctx; GLuint name; __glsBeginCriticalSection(); name = __glsNextContext; if ( (ctx = __glsContext_create(name)) && (added = __glsInt2PtrDict_add(__glsContextDict, (GLint)name, ctx)) ) { ++__glsContextCount; ++__glsNextContext; __GLS_LIST_APPEND(&__glsContextList, ctx); } __glsEndCriticalSection(); if (added) { return name; } else { __glsContext_destroy(ctx); return 0; } } GLuint* glsGetAllContexts(void) { GLuint *buf = GLS_NONE; GLint i = 0; __glsBeginCriticalSection(); if (buf = __glsMalloc((__glsContextCount + 1) * sizeof(GLuint))) { __GLS_LIST_ITER(__GLScontext) iter; __GLS_LIST_FIRST(&__glsContextList, &iter); while (iter.elem) { buf[i++] = iter.elem->name; __GLS_LIST_NEXT(&__glsContextList, &iter); } buf[i] = 0; } __glsEndCriticalSection(); return buf; } GLScommandAlignment* glsGetCommandAlignment( GLSopcode inOpcode, GLSenum inExternStreamType, GLScommandAlignment *outAlignment ) { GLbitfield attrib; if (!__glsValidateOpcode(inOpcode)) return GLS_NONE; attrib = __glsOpcodeAttrib[__glsMapOpcode(inOpcode)]; switch (inExternStreamType) { case GLS_BINARY_LSB_FIRST: case GLS_BINARY_MSB_FIRST: if (attrib & __GLS_COMMAND_ALIGN_EVEN32_BIT) { outAlignment->mask = 7; outAlignment->value = 0; } else if (attrib & __GLS_COMMAND_ALIGN_ODD32_BIT) { outAlignment->mask = 7; outAlignment->value = 4; } else { outAlignment->mask = 3; outAlignment->value = 0; } break; case GLS_TEXT: outAlignment->mask = 0; outAlignment->value = 0; break; default: __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } return outAlignment; } GLbitfield glsGetCommandAttrib(GLSopcode inOpcode) { if (!__glsValidateOpcode(inOpcode)) return GLS_NONE; return ( __glsOpcodeAttrib[__glsMapOpcode(inOpcode)] & __GLS_COMMAND_ATTRIB_MASK ); } GLint glsGetConsti(GLSenum inAttrib) { switch (inAttrib) { case GLS_API_COUNT: return __GLS_API_COUNT; case GLS_MAX_CALL_NESTING: return __GLS_MAX_CALL_NESTING; case GLS_MAX_CAPTURE_NESTING: return __GLS_MAX_CAPTURE_NESTING; case GLS_VERSION_MAJOR: return __GLS_VERSION_MAJOR; case GLS_VERSION_MINOR: return __GLS_VERSION_MINOR; } __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } const GLint* glsGetConstiv(GLSenum inAttrib) { switch (inAttrib) { case GLS_ALL_APIS: return (const GLint *)__glsAllAPIs; } __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } const GLubyte* glsGetConstubz(GLSenum inAttrib) { switch (inAttrib) { case GLS_EXTENSIONS: return __glsExtensions; case GLS_PLATFORM: return glsCSTR(__GLS_PLATFORM); case GLS_RELEASE: return glsCSTR(__GLS_RELEASE); case GLS_VENDOR: return glsCSTR(__GLS_VENDOR); } __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } GLuint glsGetCurrentContext(void) { return __GLS_CONTEXT ? __GLS_CONTEXT->name : 0; } GLint* glsGetCurrentTime(GLint *outTime) { GLint i; const time_t t = time(GLS_NONE); struct tm utc, *utcp; __glsBeginCriticalSection(); if (utcp = gmtime(&t)) utc = *utcp; __glsEndCriticalSection(); if (t != (time_t)-1 && utcp) { outTime[0] = 1900 + utc.tm_year; outTime[1] = 1 + utc.tm_mon; outTime[2] = utc.tm_mday; outTime[3] = utc.tm_hour; outTime[4] = utc.tm_min; outTime[5] = utc.tm_sec; return outTime; } for (i = 0 ; i < 6 ; ++i) outTime[i] = 0; return GLS_NONE; } GLSenum glsGetError(GLboolean inClear) { const GLSenum outError = __GLS_ERROR; if (inClear) __GLS_PUT_ERROR(GLS_NONE); return outError; } GLint glsGetOpcodeCount(GLSenum inAPI) { switch (inAPI) { case GLS_API_GLS: return __glsOpcodesGLSCount; case GLS_API_GL: return __glsOpcodesGLCount; } __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } const GLSopcode* glsGetOpcodes(GLSenum inAPI) { switch (inAPI) { case GLS_API_GLS: return __glsOpcodesGLS; case GLS_API_GL: return __glsOpcodesGL; } __GLS_RAISE_ERROR(GLS_INVALID_ENUM); return GLS_NONE; } GLboolean glsIsContext(GLuint inContext) { __GLScontext *ctx; __glsBeginCriticalSection(); ctx = (__GLScontext *)__glsInt2PtrDict_find( __glsContextDict, (GLint)inContext ); __glsEndCriticalSection(); return (GLboolean)(ctx != GLS_NONE); } static GLboolean __glsFindExtension( const GLubyte *inExtension, const GLubyte *inList ) { const GLubyte *p0 = inList; while ( p0 = (const GLubyte *)strstr((const char *)p0, (const char *)inExtension) ) { const GLubyte *const p1 = p0 + strlen((const char *)inExtension); if (!*p1 || *p1 == ' ') return GL_TRUE; p0 = p1; } return GL_FALSE; } GLboolean glsIsExtensionSupported(const GLubyte *inExtension) { if (!__glsValidateString(inExtension)) return GL_FALSE; if (!__glsFindExtension(inExtension, __glsExtensions)) return GL_FALSE; if (!strncmp((const char *)inExtension, "GL_", 3)) { const GLubyte *const p = glGetString(GL_EXTENSIONS); if (!p || !__glsFindExtension(inExtension, p)) return GL_FALSE; } return GL_TRUE; } GLboolean glsIsUTF8String(const GLubyte *inString) { GLuint b; while (b = *inString) { if (b & 0x80) goto slowPath; ++inString; } return GL_TRUE; slowPath: while (*inString) { const GLint n = glsUTF8toUCS4(inString, &b); if (!n) return GL_FALSE; inString += n; } return GL_TRUE; } GLlong glsLong(GLint inHigh, GLuint inLow) { #if __GLS_INT64 return ((GLlong)inHigh) << 32 | inLow; #elif __GLS_MSB_FIRST GLlong outVal; outVal.uint0 = inHigh; outVal.uint1 = inLow; return outVal; #else /* !__GLS_MSB_FIRST */ GLlong outVal; outVal.uint0 = inLow; outVal.uint1 = inHigh; return outVal; #endif /* __GLS_INT64 */ } GLint glsLongHigh(GLlong inVal) { #if __GLS_INT64 return (GLint)(inVal >> 32 & 0xffffffff); #elif __GLS_MSB_FIRST return inVal.uint0; #else /* !__GLS_MSB_FIRST */ return inVal.uint1; #endif /* __GLS_INT64 */ } GLuint glsLongLow(GLlong inVal) { #if __GLS_INT64 return (GLuint)(inVal & 0xffffffff); #elif __GLS_MSB_FIRST return inVal.uint1; #else /* !__GLS_MSB_FIRST */ return inVal.uint0; #endif /* __GLS_INT64 */ } void glsPixelSetup(void) { __glsPixelSetup_pack(); __glsPixelSetup_unpack(); } GLulong glsULong(GLuint inHigh, GLuint inLow) { #if __GLS_INT64 return ((GLulong)inHigh) << 32 | inLow; #elif __GLS_MSB_FIRST GLulong outVal; outVal.uint0 = inHigh; outVal.uint1 = inLow; return outVal; #else /* !__GLS_MSB_FIRST */ GLulong outVal; outVal.uint0 = inLow; outVal.uint1 = inHigh; return outVal; #endif /* __GLS_INT64 */ } GLuint glsULongHigh(GLulong inVal) { #if __GLS_INT64 return (GLuint)(inVal >> 32 & 0xffffffff); #elif __GLS_MSB_FIRST return inVal.uint0; #else /* !__GLS_MSB_FIRST */ return inVal.uint1; #endif /* __GLS_INT64 */ } GLuint glsULongLow(GLulong inVal) { #if __GLS_INT64 return (GLuint)(inVal & 0xffffffff); #elif __GLS_MSB_FIRST return inVal.uint1; #else /* !__GLS_MSB_FIRST */ return inVal.uint0; #endif /* __GLS_INT64 */ } GLint glsUCS4toUTF8(GLuint inUCS4, GLubyte *outUTF8) { const __GLSutf8format *format; GLint outVal = 1; for (format = __glsUTF8formats ; format->mask1 ; ++format, ++outVal) { if (inUCS4 <= format->mask4) { GLuint shift = format->shift; *outUTF8++ = (GLubyte)(format->val1 | (inUCS4 >> shift)); while (shift) { shift -= 6; *outUTF8++ = (GLubyte)(0x80 | ((inUCS4 >> shift) & 0x3f)); } return outVal; } } return 0; } GLubyte* glsUCStoUTF8z( size_t inUCSbytes, const GLvoid *inUCSz, size_t inUTF8max, GLubyte *outUTF8z ) { switch (inUCSbytes) { case 1: return glsUCS1toUTF8z( (const GLubyte *)inUCSz, inUTF8max, outUTF8z ); case 2: return glsUCS2toUTF8z( (const GLushort *)inUCSz, inUTF8max, outUTF8z ); case 4: return glsUCS4toUTF8z( (const GLuint *)inUCSz, inUTF8max, outUTF8z ); default: __GLS_RAISE_ERROR(GLS_INVALID_VALUE); return GLS_NONE; } } GLubyte* glsUCS1toUTF8z( const GLubyte *inUCS1z, size_t inUTF8max, GLubyte *outUTF8z ) { GLuint b; GLubyte *const limit = outUTF8z + inUTF8max - 1; GLubyte *p = outUTF8z; while (b = *inUCS1z++) { if (p >= limit) return GLS_NONE; p += glsUCS4toUTF8(b, p); } if (p > limit) return GLS_NONE; *p = 0; return outUTF8z; } GLubyte* glsUCS2toUTF8z( const GLushort *inUCS2z, size_t inUTF8max, GLubyte *outUTF8z ) { GLuint b; GLubyte buf[3]; GLubyte *const limit = outUTF8z + inUTF8max - 1; GLubyte *p = outUTF8z; while (b = *inUCS2z++) { GLubyte *bufPtr = buf; GLubyte *p0 = p; p += glsUCS4toUTF8(b, bufPtr); if (p > limit) return GLS_NONE; while (p0 < p) *p0++ = *bufPtr++; } *p = 0; return outUTF8z; } GLubyte* glsUCS4toUTF8z( const GLuint *inUCS4z, size_t inUTF8max, GLubyte *outUTF8z ) { GLuint b; GLubyte buf[6]; GLubyte *const limit = outUTF8z + inUTF8max - 1; GLubyte *p = outUTF8z; while (b = *inUCS4z++) { GLubyte *bufPtr = buf; GLubyte *p0 = p; p += glsUCS4toUTF8(b, bufPtr); if (p > limit) return GLS_NONE; while (p0 < p) *p0++ = *bufPtr++; } *p = 0; return outUTF8z; } GLint glsUTF8toUCS4(const GLubyte *inUTF8, GLuint *outUCS4) { GLuint b, b0, ucs4; const __GLSutf8format *format; GLint outVal = 1; ucs4 = b0 = *inUTF8++; for (format = __glsUTF8formats ; format->mask1 ; ++format, ++outVal) { if ((b0 & format->mask1) == format->val1) { ucs4 &= format->mask4; if (ucs4 < format->val4) return 0; *outUCS4 = ucs4; return outVal; } b = *inUTF8++ ^ 0x80; if (b & 0xc0) return 0; ucs4 = (ucs4 << 6) | b; } return 0; } GLboolean glsUTF8toUCSz( size_t inUCSbytes, const GLubyte *inUTF8z, size_t inUCSmax, GLvoid *outUCSz ) { switch (inUCSbytes) { case 1: return glsUTF8toUCS1z(inUTF8z, inUCSmax, (GLubyte *)outUCSz); case 2: return glsUTF8toUCS2z(inUTF8z, inUCSmax, (GLushort *)outUCSz); case 4: return glsUTF8toUCS4z(inUTF8z, inUCSmax, (GLuint *)outUCSz); default: __GLS_RAISE_ERROR(GLS_INVALID_VALUE); return GL_FALSE; } } GLboolean glsUTF8toUCS1z( const GLubyte *inUTF8z, size_t inUCS1max, GLubyte *outUCS1z ) { GLuint b; GLubyte *const limit = outUCS1z + inUCS1max - 1; while (*inUTF8z) { const GLint n = glsUTF8toUCS4(inUTF8z, &b); if (n && b <= 0xff && outUCS1z < limit) { inUTF8z += n; *outUCS1z++ = (GLubyte)b; } else { return GL_FALSE; } } if (outUCS1z > limit) return GL_FALSE; *outUCS1z = 0; return GL_TRUE; } GLboolean glsUTF8toUCS2z( const GLubyte *inUTF8z, size_t inUCS2max, GLushort *outUCS2z ) { GLuint b; GLushort *const limit = outUCS2z + inUCS2max - 1; while (*inUTF8z) { const GLint n = glsUTF8toUCS4(inUTF8z, &b); if (n && b <= 0xffff && outUCS2z < limit) { inUTF8z += n; *outUCS2z++ = (GLushort)b; } else { return GL_FALSE; } } if (outUCS2z > limit) return GL_FALSE; *outUCS2z = 0; return GL_TRUE; } GLboolean glsUTF8toUCS4z( const GLubyte *inUTF8z, size_t inUCS4max, GLuint *outUCS4z ) { GLuint b; GLuint *const limit = outUCS4z + inUCS4max - 1; while (*inUTF8z) { const GLint n = glsUTF8toUCS4(inUTF8z, &b); if (n && outUCS4z < limit) { inUTF8z += n; *outUCS4z++ = b; } else { return GL_FALSE; } } if (outUCS4z > limit) return GL_FALSE; *outUCS4z = 0; return GL_TRUE; }