warzone2100/3rdparty/quesoglc/misc.c

664 lines
21 KiB
C

/* QuesoGLC
* A free implementation of the OpenGL Character Renderer (GLC)
* Copyright (c) 2002, 2004-2009, Bertrand Coconnier
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* $Id$ */
/** \file
* defines miscellaneous utility routines used throughout QuesoGLC.
*/
#include <math.h>
#include "internal.h"
#ifdef DEBUGMODE
GLuint __glcMemAllocCount = 0;
GLuint __glcMemAllocTrigger = 0;
GLboolean __glcMemAllocFailOnce = GL_TRUE;
/* QuesoGLC own allocation and memory management routines */
void* __glcMalloc(size_t size)
{
__glcMemAllocCount++;
if (__glcMemAllocFailOnce) {
if (__glcMemAllocCount == __glcMemAllocTrigger)
return NULL;
}
else if (__glcMemAllocCount >= __glcMemAllocTrigger)
return NULL;
return malloc(size);
}
void __glcFree(void *ptr)
{
/* Not all implementations of free() accept NULL. Moreover this allows to
* detect useless calls.
*/
assert(ptr);
free(ptr);
}
void* __glcRealloc(void *ptr, size_t size)
{
__glcMemAllocCount++;
if (__glcMemAllocFailOnce) {
if (__glcMemAllocCount == __glcMemAllocTrigger)
return NULL;
}
else if (__glcMemAllocCount >= __glcMemAllocTrigger)
return NULL;
return realloc(ptr, size);
}
#endif
#ifndef HAVE_TLS
/* Each thread has to store specific informations so they can be retrieved
* later. __glcGetThreadArea() returns a struct which contains thread specific
* info for GLC.
* If the '__GLCthreadArea' of the current thread does not exist, it is created
* and initialized.
* IMPORTANT NOTE : __glcGetThreadArea() must never use __glcMalloc() and
* __glcFree() since those functions could use the exceptContextStack
* before it is initialized.
*/
__GLCthreadArea* __glcGetThreadArea(void)
{
__GLCthreadArea *area = NULL;
#ifdef __WIN32__
area = (__GLCthreadArea*)TlsGetValue(__glcCommonArea.threadKey);
#else
area = (__GLCthreadArea*)pthread_getspecific(__glcCommonArea.threadKey);
#endif
if (area)
return area;
area = (__GLCthreadArea*)malloc(sizeof(__GLCthreadArea));
if (!area)
return NULL;
area->currentContext = NULL;
area->errorState = GLC_NONE;
area->lockState = 0;
area->exceptionStack.head = NULL;
area->exceptionStack.tail = NULL;
area->failedTry = GLC_NO_EXC;
#ifdef __WIN32__
if (!TlsSetValue(__glcCommonArea.threadKey, (LPVOID)area)) {
free(area);
return NULL;
}
#else
pthread_setspecific(__glcCommonArea.threadKey, (void*)area);
#endif
#ifdef __WIN32__
if (__glcCommonArea.threadID == GetCurrentThreadId())
#else
if (pthread_equal(__glcCommonArea.threadID, pthread_self()))
#endif
__glcThreadArea = area;
return area;
}
/* Raise an error. This function must be called each time the current error
* of the issuing thread must be set
*/
void __glcRaiseError(GLCenum inError)
{
GLCenum error = GLC_NONE;
__GLCthreadArea *area = NULL;
area = GLC_GET_THREAD_AREA();
assert(area);
/* An error can only be raised if the current error value is GLC_NONE.
* However, when inError == GLC_NONE then we must force the current error
* value to GLC_NONE whatever its previous value was.
*/
error = area->errorState;
if (!error || !inError)
area->errorState = inError;
}
/* Get the current context of the issuing thread */
__GLCcontext* __glcGetCurrent(void)
{
__GLCthreadArea *area = NULL;
area = __glcGetThreadArea(); /* Don't use GLC_GET_THREAD_AREA */
assert(area);
return area->currentContext;
}
#endif /* HAVE_TLS */
/* Process the character in order to find a font that maps the code and to
* render the corresponding glyph. Replacement code and '<hexcode>' format
* are issued if necessary. The previous code is updated accordingly.
* 'inCode' must be given in UCS-4 format
*/
void* __glcProcessChar(__GLCcontext *inContext, const GLint inCode,
__GLCcharacter* inPrevCode, const GLboolean inIsRTL,
const __glcProcessCharFunc inProcessCharFunc,
const void* inProcessCharData)
{
GLint repCode = 0;
__GLCfont* font = NULL;
void* ret = NULL;
if (!inCode)
return NULL;
/* Get a font that maps inCode */
font = __glcContextGetFont(inContext, inCode);
if (font) {
/* A font has been found */
if (font != inPrevCode->font)
inPrevCode->code = 0; /* The font has changed, kerning must be disabled */
ret = inProcessCharFunc(inCode, inPrevCode->code, inIsRTL, font, inContext,
inProcessCharData, GL_FALSE);
inPrevCode->code = inCode;
inPrevCode->font = font;
return ret;
}
/* __glcContextGetFont() can not find a font that maps inCode, we then attempt
* to produce an alternate rendering.
*/
/* If the variable GLC_REPLACEMENT_CODE is nonzero, and __glcContextGetFont()
* finds a font that maps the replacement code, we now render the character
* that the replacement code is mapped to
*/
repCode = inContext->stringState.replacementCode;
font = __glcContextGetFont(inContext, repCode);
if (repCode && font) {
if (font != inPrevCode->font)
inPrevCode->code = 0; /* The font has changed, kerning must be disabled */
ret = inProcessCharFunc(repCode, inPrevCode->code, inIsRTL, font, inContext,
inProcessCharData, GL_FALSE);
inPrevCode->code = repCode;
inPrevCode->font = font;
return ret;
}
else {
/* If we get there, we failed to render both the character that inCode maps
* to and the replacement code. Now, we will try to render the character
* sequence "\<hexcode>", where '\' is the character REVERSE SOLIDUS
* (U+5C), '<' is the character LESS-THAN SIGN (U+3C), '>' is the character
* GREATER-THAN SIGN (U+3E), and 'hexcode' is inCode represented as a
* sequence of hexadecimal digits. The sequence has no leading zeros, and
* alphabetic digits are in upper case. The GLC measurement commands treat
* the sequence as a single character.
*/
char buf[11];
GLint i = 0;
GLint n = 0;
/* Check if a font maps hexadecimal digits */
#ifdef _MSC_VER
n = sprintf_s(buf, 11, "\\<%X>", (int)inCode);
if (n < 0) {
__glcRaiseError(GLC_RESOURCE_ERROR);
return NULL;
}
#else
n = snprintf(buf, 11, "\\<%X>", (int)inCode);
#endif
for (i = 0; i < n; i++) {
if (!__glcContextGetFont(inContext, buf[i]))
/* The code is not rendered, the previous code is thus left unchanged */
return NULL;
}
/* Render the '\<hexcode>' sequence */
for (i = 0; i < n; i++) {
GLint pos = inIsRTL ? n-i-1 : i;
font = __glcContextGetFont(inContext, buf[pos]);
if (font != inPrevCode->font)
inPrevCode->code = 0; /*The font has changed, kerning must be disabled*/
ret = inProcessCharFunc(buf[pos], inPrevCode->code, inIsRTL, font,
inContext, inProcessCharData, GL_TRUE);
inPrevCode->code = buf[pos];
inPrevCode->font = font;
}
return ret;
}
}
/* Store an 4x4 identity matrix in 'm' */
static void __glcMakeIdentity(GLfloat* m)
{
memset(m, 0, 16 * sizeof(GLfloat));
m[0] = 1.f;
m[5] = 1.f;
m[10] = 1.f;
m[15] = 1.f;
}
/* Invert a 4x4 matrix stored in inMatrix. The result is stored in outMatrix
* It uses the Gauss-Jordan elimination method
*/
static GLboolean __glcInvertMatrix(const GLfloat* inMatrix, GLfloat* outMatrix)
{
int i, j, k, swap;
GLfloat t;
GLfloat temp[4][4];
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
temp[i][j] = inMatrix[i*4+j];
}
}
__glcMakeIdentity(outMatrix);
for (i = 0; i < 4; i++) {
/* Look for largest element in column */
swap = i;
for (j = i + 1; j < 4; j++) {
if (fabs(temp[j][i]) > fabs(temp[i][i])) {
swap = j;
}
}
if (swap != i) {
/* Swap rows */
for (k = 0; k < 4; k++) {
t = temp[i][k];
temp[i][k] = temp[swap][k];
temp[swap][k] = t;
t = outMatrix[i*4+k];
outMatrix[i*4+k] = outMatrix[swap*4+k];
outMatrix[swap*4+k] = t;
}
}
if (fabs(temp[i][i]) < GLC_EPSILON) {
/* No non-zero pivot. The matrix is singular, which shouldn't
* happen. This means the user gave us a bad matrix.
*/
return GL_FALSE;
}
t = temp[i][i];
for (k = 0; k < 4; k++) {
temp[i][k] /= t;
outMatrix[i*4+k] /= t;
}
for (j = 0; j < 4; j++) {
if (j != i) {
t = temp[j][i];
for (k = 0; k < 4; k++) {
temp[j][k] -= temp[i][k]*t;
outMatrix[j*4+k] -= outMatrix[i*4+k]*t;
}
}
}
}
return GL_TRUE;
}
/* Mutiply two 4x4 matrices, the operands are stored in inMatrix1 and inMatrix2
* The result is stored in outMatrix which can be neither inMatrix1 nor
* inMatrix2.
*/
static void __glcMultMatrices(const GLfloat* inMatrix1,
const GLfloat* inMatrix2, GLfloat* outMatrix)
{
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
outMatrix[i*4+j] =
inMatrix1[i*4+0]*inMatrix2[0*4+j] +
inMatrix1[i*4+1]*inMatrix2[1*4+j] +
inMatrix1[i*4+2]*inMatrix2[2*4+j] +
inMatrix1[i*4+3]*inMatrix2[3*4+j];
}
}
}
/* Compute an optimal size for the glyph to be rendered on the screen if no
* display list is planned to be built.
*/
void __glcGetScale(const __GLCcontext* inContext, GLfloat* outTransformMatrix,
GLfloat* outScaleX, GLfloat* outScaleY)
{
int i = 0;
if ((inContext->renderState.renderStyle != GLC_BITMAP)
&& (inContext->renderState.renderStyle != GLC_PIXMAP_QSO)) {
/* Compute the matrix that transforms object space coordinates to viewport
* coordinates. If we plan to use object space coordinates, this matrix is
* set to identity.
*/
GLfloat projectionMatrix[16];
GLfloat modelviewMatrix[16];
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
__glcMultMatrices(modelviewMatrix, projectionMatrix, outTransformMatrix);
if (!inContext->enableState.glObjects && inContext->enableState.hinting) {
GLfloat rs[16], m[16];
/* Get the scale factors in each X, Y and Z direction */
GLfloat sx = sqrt(outTransformMatrix[0] * outTransformMatrix[0]
+outTransformMatrix[1] * outTransformMatrix[1]
+outTransformMatrix[2] * outTransformMatrix[2]);
GLfloat sy = sqrt(outTransformMatrix[4] * outTransformMatrix[4]
+outTransformMatrix[5] * outTransformMatrix[5]
+outTransformMatrix[6] * outTransformMatrix[6]);
GLfloat sz = sqrt(outTransformMatrix[8] * outTransformMatrix[8]
+outTransformMatrix[9] * outTransformMatrix[9]
+outTransformMatrix[10] * outTransformMatrix[10]);
GLfloat x = 0., y = 0.;
memset(rs, 0, 16 * sizeof(GLfloat));
rs[15] = 1.;
for (i = 0; i < 3; i++) {
rs[0+4*i] = outTransformMatrix[0+4*i] / sx;
rs[1+4*i] = outTransformMatrix[1+4*i] / sy;
rs[2+4*i] = outTransformMatrix[2+4*i] / sz;
}
if (!__glcInvertMatrix(rs, rs)) {
*outScaleX = 0.f;
*outScaleY = 0.f;
return;
}
__glcMultMatrices(rs, outTransformMatrix, m);
x = ((m[0] + m[12])/(m[3] + m[15]) - m[12]/m[15]) * viewport[2] * 0.5;
y = ((m[1] + m[13])/(m[3] + m[15]) - m[13]/m[15]) * viewport[3] * 0.5;
*outScaleX = sqrt(x*x+y*y);
x = ((m[4] + m[12])/(m[7] + m[15]) - m[12]/m[15]) * viewport[2] * 0.5;
y = ((m[5] + m[13])/(m[7] + m[15]) - m[13]/m[15]) * viewport[3] * 0.5;
*outScaleY = sqrt(x*x+y*y);
}
else {
*outScaleX = GLC_POINT_SIZE;
*outScaleY = GLC_POINT_SIZE;
}
}
else {
GLfloat determinant = 0., norm = 0.;
GLfloat *transform = inContext->bitmapMatrix;
/* Compute the norm of the transformation matrix */
for (i = 0; i < 4; i++) {
if (fabsf(transform[i]) > norm)
norm = fabsf(transform[i]);
}
determinant = transform[0] * transform[3] - transform[1] * transform[2];
/* If the transformation is degenerated, nothing needs to be rendered */
if (fabsf(determinant) < norm * GLC_EPSILON) {
*outScaleX = 0.f;
*outScaleY = 0.f;
return;
}
if (inContext->enableState.hinting) {
*outScaleX = sqrt(transform[0]*transform[0]+transform[1]*transform[1]);
*outScaleY = sqrt(transform[2]*transform[2]+transform[3]*transform[3]);
}
else {
*outScaleX = GLC_POINT_SIZE;
*outScaleY = GLC_POINT_SIZE;
}
}
}
/* Save the GL State in a structure */
void __glcSaveGLState(__GLCglState* inGLState, const __GLCcontext* inContext,
const GLboolean inAll)
{
if (inAll || inContext->renderState.renderStyle == GLC_TEXTURE) {
inGLState->blend = glIsEnabled(GL_BLEND);
glGetIntegerv(GL_BLEND_SRC, &inGLState->blendSrc);
glGetIntegerv(GL_BLEND_DST, &inGLState->blendDst);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &inGLState->textureID);
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
&inGLState->textureEnvMode);
if ((inAll || !inContext->enableState.glObjects)
&& GLEW_ARB_pixel_buffer_object)
glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING_ARB,
&inGLState->pixelBufferObjectID);
}
if (inAll || (inContext->renderState.renderStyle == GLC_BITMAP)
|| (inContext->renderState.renderStyle == GLC_PIXMAP_QSO)) {
glGetIntegerv(GL_UNPACK_LSB_FIRST, &inGLState->unpackLsbFirst);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &inGLState->unpackRowLength);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &inGLState->unpackSkipPixels);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &inGLState->unpackSkipRows);
glGetIntegerv(GL_UNPACK_ALIGNMENT, &inGLState->unpackAlignment);
if (inAll || (inContext->renderState.renderStyle == GLC_PIXMAP_QSO)) {
if (!inAll) { /* if inAll, already saved in GLC_TEXTURE's block */
inGLState->blend = glIsEnabled(GL_BLEND);
glGetIntegerv(GL_BLEND_SRC, &inGLState->blendSrc);
glGetIntegerv(GL_BLEND_DST, &inGLState->blendDst);
}
glGetFloatv(GL_RED_BIAS, &inGLState->colorBias[0]);
glGetFloatv(GL_GREEN_BIAS, &inGLState->colorBias[1]);
glGetFloatv(GL_BLUE_BIAS, &inGLState->colorBias[2]);
glGetFloatv(GL_ALPHA_BIAS, &inGLState->colorBias[3]);
glGetFloatv(GL_RED_SCALE, &inGLState->colorScale[0]);
glGetFloatv(GL_GREEN_SCALE, &inGLState->colorScale[1]);
glGetFloatv(GL_BLUE_SCALE, &inGLState->colorScale[2]);
glGetFloatv(GL_ALPHA_SCALE, &inGLState->colorScale[3]);
}
}
if ((inAll || (inContext->enableState.glObjects
&& (inContext->renderState.renderStyle != GLC_BITMAP)
&& (inContext->renderState.renderStyle != GLC_PIXMAP_QSO)))
&& GLEW_ARB_vertex_buffer_object) {
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB,
&inGLState->vertexBufferObjectID);
if (inAll || (inContext->renderState.renderStyle == GLC_TRIANGLE))
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB,
&inGLState->elementBufferObjectID);
}
if (inAll || (inContext->renderState.renderStyle == GLC_TRIANGLE
&& inContext->enableState.glObjects
&& inContext->enableState.extrude))
inGLState->normalize = glIsEnabled(GL_NORMALIZE);
if (inAll || inContext->renderState.renderStyle == GLC_LINE
|| inContext->renderState.renderStyle == GLC_TRIANGLE
|| (inContext->renderState.renderStyle == GLC_TEXTURE
&& inContext->enableState.glObjects
&& GLEW_ARB_vertex_buffer_object)) {
inGLState->vertexArray = glIsEnabled(GL_VERTEX_ARRAY);
if (inGLState->vertexArray == GL_TRUE) {
glGetIntegerv(GL_VERTEX_ARRAY_SIZE, &inGLState->vertexArraySize);
glGetIntegerv(GL_VERTEX_ARRAY_TYPE, &inGLState->vertexArrayType);
glGetIntegerv(GL_VERTEX_ARRAY_STRIDE, &inGLState->vertexArrayStride);
glGetPointerv(GL_VERTEX_ARRAY_POINTER, &inGLState->vertexArrayPointer);
}
inGLState->normalArray = glIsEnabled(GL_NORMAL_ARRAY);
inGLState->colorArray = glIsEnabled(GL_COLOR_ARRAY);
inGLState->indexArray = glIsEnabled(GL_INDEX_ARRAY);
inGLState->texCoordArray = glIsEnabled(GL_TEXTURE_COORD_ARRAY);
if ((inAll || inContext->renderState.renderStyle == GLC_TEXTURE) && inGLState->texCoordArray == GL_TRUE) {
glGetIntegerv(GL_TEXTURE_COORD_ARRAY_SIZE, &inGLState->texCoordArraySize);
glGetIntegerv(GL_TEXTURE_COORD_ARRAY_TYPE, &inGLState->texCoordArrayType);
glGetIntegerv(GL_TEXTURE_COORD_ARRAY_STRIDE,
&inGLState->texCoordArrayStride);
glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER,
&inGLState->texCoordArrayPointer);
}
inGLState->edgeFlagArray = glIsEnabled(GL_EDGE_FLAG_ARRAY);
}
}
/* Restore the GL State from a structure */
void __glcRestoreGLState(const __GLCglState* inGLState,
const __GLCcontext* inContext, const GLboolean inAll)
{
if (inAll || inContext->renderState.renderStyle == GLC_TEXTURE) {
if (!inGLState->blend)
glDisable(GL_BLEND);
glBlendFunc(inGLState->blendSrc, inGLState->blendDst);
glBindTexture(GL_TEXTURE_2D, inGLState->textureID);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, inGLState->textureEnvMode);
if ((inAll || !inContext->enableState.glObjects)
&& GLEW_ARB_pixel_buffer_object)
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB,
inGLState->pixelBufferObjectID);
}
if ((inAll || (inContext->renderState.renderStyle == GLC_BITMAP)
|| (inContext->renderState.renderStyle == GLC_PIXMAP_QSO))) {
glPixelStorei(GL_UNPACK_LSB_FIRST, inGLState->unpackLsbFirst);
glPixelStorei(GL_UNPACK_ROW_LENGTH, inGLState->unpackRowLength);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, inGLState->unpackSkipPixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, inGLState->unpackSkipRows);
glPixelStorei(GL_UNPACK_ALIGNMENT, inGLState->unpackAlignment);
if (inAll || (inContext->renderState.renderStyle == GLC_PIXMAP_QSO)) {
if (!inAll) { /* if inAll, already restored in GLC_TEXTURE's block */
if (!inGLState->blend)
glDisable(GL_BLEND);
glBlendFunc(inGLState->blendSrc, inGLState->blendDst);
}
glPixelTransferf(GL_RED_BIAS, inGLState->colorBias[0]);
glPixelTransferf(GL_GREEN_BIAS, inGLState->colorBias[1]);
glPixelTransferf(GL_BLUE_BIAS, inGLState->colorBias[2]);
glPixelTransferf(GL_ALPHA_BIAS, inGLState->colorBias[3]);
glPixelTransferf(GL_RED_SCALE, inGLState->colorScale[0]);
glPixelTransferf(GL_GREEN_SCALE, inGLState->colorScale[1]);
glPixelTransferf(GL_BLUE_SCALE, inGLState->colorScale[2]);
glPixelTransferf(GL_ALPHA_SCALE, inGLState->colorScale[3]);
}
}
if ((inAll || (inContext->enableState.glObjects
&& (inContext->renderState.renderStyle != GLC_BITMAP)
&& (inContext->renderState.renderStyle != GLC_PIXMAP_QSO)))
&& GLEW_ARB_vertex_buffer_object) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, inGLState->vertexBufferObjectID);
if (inAll || (inContext->renderState.renderStyle == GLC_TRIANGLE))
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
inGLState->elementBufferObjectID);
}
if (inAll || (inContext->renderState.renderStyle == GLC_TRIANGLE
&& inContext->enableState.glObjects
&& inContext->enableState.extrude))
if (!inGLState->normalize)
glDisable(GL_NORMALIZE);
if (inAll || inContext->renderState.renderStyle == GLC_LINE
|| inContext->renderState.renderStyle == GLC_TRIANGLE
|| (inContext->renderState.renderStyle == GLC_TEXTURE
&& inContext->enableState.glObjects
&& GLEW_ARB_vertex_buffer_object)) {
if (!inGLState->vertexArray)
glDisableClientState(GL_VERTEX_ARRAY);
if (inGLState->vertexArray == GL_TRUE) {
glVertexPointer(inGLState->vertexArraySize, inGLState->vertexArrayType,
inGLState->vertexArrayStride,
inGLState->vertexArrayPointer);
}
if (!inGLState->normalArray)
glDisableClientState(GL_NORMAL_ARRAY);
if (!inGLState->colorArray)
glDisableClientState(GL_COLOR_ARRAY);
if (!inGLState->indexArray)
glDisableClientState(GL_INDEX_ARRAY);
if (!inGLState->texCoordArray)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if ((inAll || inContext->renderState.renderStyle == GLC_TEXTURE) && inGLState->texCoordArray == GL_TRUE)
glTexCoordPointer(inGLState->texCoordArraySize,
inGLState->texCoordArrayType,
inGLState->texCoordArrayStride,
inGLState->texCoordArrayPointer);
if (!inGLState->edgeFlagArray)
glDisableClientState(GL_EDGE_FLAG_ARRAY);
}
}
#ifdef GLEW_MX
/* Function for GLEW so that it can get a context */
GLEWContext* __glcGetGlewContext(void)
{
__GLCcontext* ctx = GLC_GET_CURRENT_CONTEXT();
if (!ctx) {
__glcRaiseError(GLC_STATE_ERROR);
return NULL;
}
return &ctx->glewContext;
}
#endif
/* This function initializes the thread management of QuesoGLC when TLS is not
* available. It must be called once (see the macro GLC_INIT_THREAD)
*/
#ifndef HAVE_TLS
void __glcInitThread(void) {
#ifdef __WIN32__
__glcCommonArea.threadID = GetCurrentThreadId();
#else
__glcCommonArea.threadID = pthread_self();
#endif /* __WIN32__ */
}
#endif /* HAVE_TLS */