diff options
Diffstat (limited to 'src/mesa/main')
124 files changed, 87399 insertions, 0 deletions
diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c new file mode 100644 index 00000000000..2f7375bd3a0 --- /dev/null +++ b/src/mesa/main/accum.c @@ -0,0 +1,110 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "accum.h" +#include "context.h" +#include "imports.h" +#include "macros.h" +#include "state.h" +#include "mtypes.h" + + +void GLAPIENTRY +_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) +{ + GLfloat tmp[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + tmp[0] = CLAMP( red, -1.0F, 1.0F ); + tmp[1] = CLAMP( green, -1.0F, 1.0F ); + tmp[2] = CLAMP( blue, -1.0F, 1.0F ); + tmp[3] = CLAMP( alpha, -1.0F, 1.0F ); + + if (TEST_EQ_4V(tmp, ctx->Accum.ClearColor)) + return; + + FLUSH_VERTICES(ctx, _NEW_ACCUM); + COPY_4FV( ctx->Accum.ClearColor, tmp ); +} + + +void GLAPIENTRY +_mesa_Accum( GLenum op, GLfloat value ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (op) { + case GL_ADD: + case GL_MULT: + case GL_ACCUM: + case GL_LOAD: + case GL_RETURN: + /* OK */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glAccum(op)"); + return; + } + + if (ctx->DrawBuffer->Visual.haveAccumBuffer == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glAccum(no accum buffer)"); + return; + } + + if (ctx->DrawBuffer != ctx->ReadBuffer) { + /* See GLX_SGI_make_current_read or WGL_ARB_make_current_read */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glAccum(different read/draw buffers)"); + return; + } + + if (ctx->NewState) + _mesa_update_state(ctx); + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glAccum(incomplete framebuffer)"); + return; + } + + if (ctx->RenderMode == GL_RENDER) { + GLint x = ctx->DrawBuffer->_Xmin; + GLint y = ctx->DrawBuffer->_Ymin; + GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + ctx->Driver.Accum(ctx, op, value, x, y, width, height); + } +} + + + +void +_mesa_init_accum( GLcontext *ctx ) +{ + /* Accumulate buffer group */ + ASSIGN_4V( ctx->Accum.ClearColor, 0.0, 0.0, 0.0, 0.0 ); +} diff --git a/src/mesa/main/accum.h b/src/mesa/main/accum.h new file mode 100644 index 00000000000..ce92688a5b9 --- /dev/null +++ b/src/mesa/main/accum.h @@ -0,0 +1,62 @@ +/** + * \file accum.h + * Accumulation buffer operations. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef ACCUM_H +#define ACCUM_H + + +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_Accum( GLenum op, GLfloat value ); + + +extern void GLAPIENTRY +_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ); + +extern void +_mesa_init_accum( GLcontext *ctx ); + +#else + +/** No-op */ +#define _mesa_init_accum( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c new file mode 100644 index 00000000000..41adc1d1d29 --- /dev/null +++ b/src/mesa/main/api_arrayelt.c @@ -0,0 +1,796 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Author: + * Keith Whitwell <[email protected]> + */ + +#include "glheader.h" +#include "api_arrayelt.h" +#include "context.h" +#include "glapi.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "glapioffsets.h" +#include "dispatch.h" + +typedef void (GLAPIENTRY *array_func)( const void * ); + +typedef struct { + const struct gl_client_array *array; + int offset; +} AEarray; + +typedef void (GLAPIENTRY *attrib_func)( GLuint indx, const void *data ); + +typedef struct { + const struct gl_client_array *array; + attrib_func func; + GLuint index; +} AEattrib; + +typedef struct { + AEarray arrays[32]; + AEattrib attribs[VERT_ATTRIB_MAX + 1]; + GLuint NewState; +} AEcontext; + +#define AE_CONTEXT(ctx) ((AEcontext *)(ctx)->aelt_context) + + +/* + * Convert GL_BYTE, GL_UNSIGNED_BYTE, .. GL_DOUBLE into an integer + * in the range [0, 7]. Luckily these type tokens are sequentially + * numbered in gl.h, except for GL_DOUBLE. + */ +#define TYPE_IDX(t) ( (t) == GL_DOUBLE ? 7 : (t) & 7 ) + +static const int ColorFuncs[2][8] = { + { + _gloffset_Color3bv, + _gloffset_Color3ubv, + _gloffset_Color3sv, + _gloffset_Color3usv, + _gloffset_Color3iv, + _gloffset_Color3uiv, + _gloffset_Color3fv, + _gloffset_Color3dv, + }, + { + _gloffset_Color4bv, + _gloffset_Color4ubv, + _gloffset_Color4sv, + _gloffset_Color4usv, + _gloffset_Color4iv, + _gloffset_Color4uiv, + _gloffset_Color4fv, + _gloffset_Color4dv, + }, +}; + +static const int VertexFuncs[3][8] = { + { + -1, + -1, + _gloffset_Vertex2sv, + -1, + _gloffset_Vertex2iv, + -1, + _gloffset_Vertex2fv, + _gloffset_Vertex2dv, + }, + { + -1, + -1, + _gloffset_Vertex3sv, + -1, + _gloffset_Vertex3iv, + -1, + _gloffset_Vertex3fv, + _gloffset_Vertex3dv, + }, + { + -1, + -1, + _gloffset_Vertex4sv, + -1, + _gloffset_Vertex4iv, + -1, + _gloffset_Vertex4fv, + _gloffset_Vertex4dv, + }, +}; + +static const int IndexFuncs[8] = { + -1, + _gloffset_Indexubv, + _gloffset_Indexsv, + -1, + _gloffset_Indexiv, + -1, + _gloffset_Indexfv, + _gloffset_Indexdv, +}; + +static const int NormalFuncs[8] = { + _gloffset_Normal3bv, + -1, + _gloffset_Normal3sv, + -1, + _gloffset_Normal3iv, + -1, + _gloffset_Normal3fv, + _gloffset_Normal3dv, +}; + +#if defined(IN_DRI_DRIVER) +static int SecondaryColorFuncs[8]; +static int FogCoordFuncs[8] = { + -1, + -1, + -1, + -1, + -1, + -1, + 0, + 0, +}; +#else +static const int SecondaryColorFuncs[8] = { + _gloffset_SecondaryColor3bvEXT, + _gloffset_SecondaryColor3ubvEXT, + _gloffset_SecondaryColor3svEXT, + _gloffset_SecondaryColor3usvEXT, + _gloffset_SecondaryColor3ivEXT, + _gloffset_SecondaryColor3uivEXT, + _gloffset_SecondaryColor3fvEXT, + _gloffset_SecondaryColor3dvEXT, +}; + +static const int FogCoordFuncs[8] = { + -1, + -1, + -1, + -1, + -1, + -1, + _gloffset_FogCoordfvEXT, + _gloffset_FogCoorddvEXT +}; +#endif + +/**********************************************************************/ + +/* GL_BYTE attributes */ + +static void GLAPIENTRY VertexAttrib1NbvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]))); +} + +static void GLAPIENTRY VertexAttrib1bvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, v[0])); +} + +static void GLAPIENTRY VertexAttrib2NbvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]))); +} + +static void GLAPIENTRY VertexAttrib2bvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, v[0], v[1])); +} + +static void GLAPIENTRY VertexAttrib3NbvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]), + BYTE_TO_FLOAT(v[1]), + BYTE_TO_FLOAT(v[2]))); +} + +static void GLAPIENTRY VertexAttrib3bvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, v[0], v[1], v[2])); +} + +static void GLAPIENTRY VertexAttrib4NbvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, BYTE_TO_FLOAT(v[0]), + BYTE_TO_FLOAT(v[1]), + BYTE_TO_FLOAT(v[2]), + BYTE_TO_FLOAT(v[3]))); +} + +static void GLAPIENTRY VertexAttrib4bvNV(GLuint index, const GLbyte *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, v[0], v[1], v[2], v[3])); +} + +/* GL_UNSIGNED_BYTE attributes */ + +static void GLAPIENTRY VertexAttrib1NubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]))); +} + +static void GLAPIENTRY VertexAttrib1ubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, v[0])); +} + +static void GLAPIENTRY VertexAttrib2NubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]), + UBYTE_TO_FLOAT(v[1]))); +} + +static void GLAPIENTRY VertexAttrib2ubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, v[0], v[1])); +} + +static void GLAPIENTRY VertexAttrib3NubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]), + UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2]))); +} +static void GLAPIENTRY VertexAttrib3ubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, v[0], v[1], v[2])); +} + +static void GLAPIENTRY VertexAttrib4NubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, UBYTE_TO_FLOAT(v[0]), + UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2]), + UBYTE_TO_FLOAT(v[3]))); +} + +static void GLAPIENTRY VertexAttrib4ubvNV(GLuint index, const GLubyte *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, v[0], v[1], v[2], v[3])); +} + +/* GL_SHORT attributes */ + +static void GLAPIENTRY VertexAttrib1NsvNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]))); +} + +static void GLAPIENTRY VertexAttrib1svNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, v[0])); +} + +static void GLAPIENTRY VertexAttrib2NsvNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]), + SHORT_TO_FLOAT(v[1]))); +} + +static void GLAPIENTRY VertexAttrib2svNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, v[0], v[1])); +} + +static void GLAPIENTRY VertexAttrib3NsvNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]), + SHORT_TO_FLOAT(v[1]), + SHORT_TO_FLOAT(v[2]))); +} + +static void GLAPIENTRY VertexAttrib3svNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, v[0], v[1], v[2])); +} + +static void GLAPIENTRY VertexAttrib4NsvNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, SHORT_TO_FLOAT(v[0]), + SHORT_TO_FLOAT(v[1]), + SHORT_TO_FLOAT(v[2]), + SHORT_TO_FLOAT(v[3]))); +} + +static void GLAPIENTRY VertexAttrib4svNV(GLuint index, const GLshort *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, v[0], v[1], v[2], v[3])); +} + +/* GL_UNSIGNED_SHORT attributes */ + +static void GLAPIENTRY VertexAttrib1NusvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]))); +} + +static void GLAPIENTRY VertexAttrib1usvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, v[0])); +} + +static void GLAPIENTRY VertexAttrib2NusvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]), + USHORT_TO_FLOAT(v[1]))); +} + +static void GLAPIENTRY VertexAttrib2usvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, v[0], v[1])); +} + +static void GLAPIENTRY VertexAttrib3NusvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]), + USHORT_TO_FLOAT(v[1]), + USHORT_TO_FLOAT(v[2]))); +} + +static void GLAPIENTRY VertexAttrib3usvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, v[0], v[1], v[2])); +} + +static void GLAPIENTRY VertexAttrib4NusvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, USHORT_TO_FLOAT(v[0]), + USHORT_TO_FLOAT(v[1]), + USHORT_TO_FLOAT(v[2]), + USHORT_TO_FLOAT(v[3]))); +} + +static void GLAPIENTRY VertexAttrib4usvNV(GLuint index, const GLushort *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, v[0], v[1], v[2], v[3])); +} + +/* GL_INT attributes */ + +static void GLAPIENTRY VertexAttrib1NivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]))); +} + +static void GLAPIENTRY VertexAttrib1ivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, v[0])); +} + +static void GLAPIENTRY VertexAttrib2NivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]), + INT_TO_FLOAT(v[1]))); +} + +static void GLAPIENTRY VertexAttrib2ivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, v[0], v[1])); +} + +static void GLAPIENTRY VertexAttrib3NivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]), + INT_TO_FLOAT(v[1]), + INT_TO_FLOAT(v[2]))); +} + +static void GLAPIENTRY VertexAttrib3ivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, v[0], v[1], v[2])); +} + +static void GLAPIENTRY VertexAttrib4NivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, INT_TO_FLOAT(v[0]), + INT_TO_FLOAT(v[1]), + INT_TO_FLOAT(v[2]), + INT_TO_FLOAT(v[3]))); +} + +static void GLAPIENTRY VertexAttrib4ivNV(GLuint index, const GLint *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, v[0], v[1], v[2], v[3])); +} + +/* GL_UNSIGNED_INT attributes */ + +static void GLAPIENTRY VertexAttrib1NuivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]))); +} + +static void GLAPIENTRY VertexAttrib1uivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib1fNV(GET_DISPATCH(), (index, v[0])); +} + +static void GLAPIENTRY VertexAttrib2NuivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]), + UINT_TO_FLOAT(v[1]))); +} + +static void GLAPIENTRY VertexAttrib2uivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib2fNV(GET_DISPATCH(), (index, v[0], v[1])); +} + +static void GLAPIENTRY VertexAttrib3NuivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]), + UINT_TO_FLOAT(v[1]), + UINT_TO_FLOAT(v[2]))); +} + +static void GLAPIENTRY VertexAttrib3uivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib3fNV(GET_DISPATCH(), (index, v[0], v[1], v[2])); +} + +static void GLAPIENTRY VertexAttrib4NuivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, UINT_TO_FLOAT(v[0]), + UINT_TO_FLOAT(v[1]), + UINT_TO_FLOAT(v[2]), + UINT_TO_FLOAT(v[3]))); +} + +static void GLAPIENTRY VertexAttrib4uivNV(GLuint index, const GLuint *v) +{ + CALL_VertexAttrib4fNV(GET_DISPATCH(), (index, v[0], v[1], v[2], v[3])); +} + +/* GL_FLOAT attributes */ + +static void GLAPIENTRY VertexAttrib1fvNV(GLuint index, const GLfloat *v) +{ + CALL_VertexAttrib1fvNV(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY VertexAttrib2fvNV(GLuint index, const GLfloat *v) +{ + CALL_VertexAttrib2fvNV(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY VertexAttrib3fvNV(GLuint index, const GLfloat *v) +{ + CALL_VertexAttrib3fvNV(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY VertexAttrib4fvNV(GLuint index, const GLfloat *v) +{ + CALL_VertexAttrib4fvNV(GET_DISPATCH(), (index, v)); +} + +/* GL_DOUBLE attributes */ + +static void GLAPIENTRY VertexAttrib1dvNV(GLuint index, const GLdouble *v) +{ + CALL_VertexAttrib1dvNV(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY VertexAttrib2dvNV(GLuint index, const GLdouble *v) +{ + CALL_VertexAttrib2dvNV(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY VertexAttrib3dvNV(GLuint index, const GLdouble *v) +{ + CALL_VertexAttrib3dvNV(GET_DISPATCH(), (index, v)); +} + +static void GLAPIENTRY VertexAttrib4dvNV(GLuint index, const GLdouble *v) +{ + CALL_VertexAttrib4dvNV(GET_DISPATCH(), (index, v)); +} + + +/* + * Array [size][type] of VertexAttrib functions + */ +static attrib_func AttribFuncsNV[2][4][8] = { + { + /* non-normalized */ + { + /* size 1 */ + (attrib_func) VertexAttrib1bvNV, + (attrib_func) VertexAttrib1ubvNV, + (attrib_func) VertexAttrib1svNV, + (attrib_func) VertexAttrib1usvNV, + (attrib_func) VertexAttrib1ivNV, + (attrib_func) VertexAttrib1uivNV, + (attrib_func) VertexAttrib1fvNV, + (attrib_func) VertexAttrib1dvNV + }, + { + /* size 2 */ + (attrib_func) VertexAttrib2bvNV, + (attrib_func) VertexAttrib2ubvNV, + (attrib_func) VertexAttrib2svNV, + (attrib_func) VertexAttrib2usvNV, + (attrib_func) VertexAttrib2ivNV, + (attrib_func) VertexAttrib2uivNV, + (attrib_func) VertexAttrib2fvNV, + (attrib_func) VertexAttrib2dvNV + }, + { + /* size 3 */ + (attrib_func) VertexAttrib3bvNV, + (attrib_func) VertexAttrib3ubvNV, + (attrib_func) VertexAttrib3svNV, + (attrib_func) VertexAttrib3usvNV, + (attrib_func) VertexAttrib3ivNV, + (attrib_func) VertexAttrib3uivNV, + (attrib_func) VertexAttrib3fvNV, + (attrib_func) VertexAttrib3dvNV + }, + { + /* size 4 */ + (attrib_func) VertexAttrib4bvNV, + (attrib_func) VertexAttrib4ubvNV, + (attrib_func) VertexAttrib4svNV, + (attrib_func) VertexAttrib4usvNV, + (attrib_func) VertexAttrib4ivNV, + (attrib_func) VertexAttrib4uivNV, + (attrib_func) VertexAttrib4fvNV, + (attrib_func) VertexAttrib4dvNV + } + }, + { + /* normalized (except for float/double) */ + { + /* size 1 */ + (attrib_func) VertexAttrib1NbvNV, + (attrib_func) VertexAttrib1NubvNV, + (attrib_func) VertexAttrib1NsvNV, + (attrib_func) VertexAttrib1NusvNV, + (attrib_func) VertexAttrib1NivNV, + (attrib_func) VertexAttrib1NuivNV, + (attrib_func) VertexAttrib1fvNV, + (attrib_func) VertexAttrib1dvNV + }, + { + /* size 2 */ + (attrib_func) VertexAttrib2NbvNV, + (attrib_func) VertexAttrib2NubvNV, + (attrib_func) VertexAttrib2NsvNV, + (attrib_func) VertexAttrib2NusvNV, + (attrib_func) VertexAttrib2NivNV, + (attrib_func) VertexAttrib2NuivNV, + (attrib_func) VertexAttrib2fvNV, + (attrib_func) VertexAttrib2dvNV + }, + { + /* size 3 */ + (attrib_func) VertexAttrib3NbvNV, + (attrib_func) VertexAttrib3NubvNV, + (attrib_func) VertexAttrib3NsvNV, + (attrib_func) VertexAttrib3NusvNV, + (attrib_func) VertexAttrib3NivNV, + (attrib_func) VertexAttrib3NuivNV, + (attrib_func) VertexAttrib3fvNV, + (attrib_func) VertexAttrib3dvNV + }, + { + /* size 4 */ + (attrib_func) VertexAttrib4NbvNV, + (attrib_func) VertexAttrib4NubvNV, + (attrib_func) VertexAttrib4NsvNV, + (attrib_func) VertexAttrib4NusvNV, + (attrib_func) VertexAttrib4NivNV, + (attrib_func) VertexAttrib4NuivNV, + (attrib_func) VertexAttrib4fvNV, + (attrib_func) VertexAttrib4dvNV + } + } +}; + +/**********************************************************************/ + + +GLboolean _ae_create_context( GLcontext *ctx ) +{ + if (ctx->aelt_context) + return GL_TRUE; + +#if defined(IN_DRI_DRIVER) + SecondaryColorFuncs[0] = _gloffset_SecondaryColor3bvEXT; + SecondaryColorFuncs[1] = _gloffset_SecondaryColor3ubvEXT; + SecondaryColorFuncs[2] = _gloffset_SecondaryColor3svEXT; + SecondaryColorFuncs[3] = _gloffset_SecondaryColor3usvEXT; + SecondaryColorFuncs[4] = _gloffset_SecondaryColor3ivEXT; + SecondaryColorFuncs[5] = _gloffset_SecondaryColor3uivEXT; + SecondaryColorFuncs[6] = _gloffset_SecondaryColor3fvEXT; + SecondaryColorFuncs[7] = _gloffset_SecondaryColor3dvEXT; + + FogCoordFuncs[6] = _gloffset_FogCoordfvEXT; + FogCoordFuncs[7] = _gloffset_FogCoorddvEXT; +#endif + + ctx->aelt_context = MALLOC( sizeof(AEcontext) ); + if (!ctx->aelt_context) + return GL_FALSE; + + AE_CONTEXT(ctx)->NewState = ~0; + return GL_TRUE; +} + + +void _ae_destroy_context( GLcontext *ctx ) +{ + if ( AE_CONTEXT( ctx ) ) { + FREE( ctx->aelt_context ); + ctx->aelt_context = NULL; + } +} + + +/** + * Make a list of per-vertex functions to call for each glArrayElement call. + * These functions access the array data (i.e. glVertex, glColor, glNormal, + * etc). + * Note: this may be called during display list construction. + */ +static void _ae_update_state( GLcontext *ctx ) +{ + AEcontext *actx = AE_CONTEXT(ctx); + AEarray *aa = actx->arrays; + AEattrib *at = actx->attribs; + GLuint i; + + /* conventional vertex arrays */ + if (ctx->Array.Index.Enabled) { + aa->array = &ctx->Array.Index; + aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)]; + aa++; + } + if (ctx->Array.EdgeFlag.Enabled) { + aa->array = &ctx->Array.EdgeFlag; + aa->offset = _gloffset_EdgeFlagv; + aa++; + } + if (ctx->Array.Normal.Enabled) { + aa->array = &ctx->Array.Normal; + aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)]; + aa++; + } + if (ctx->Array.Color.Enabled) { + aa->array = &ctx->Array.Color; + aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)]; + aa++; + } + if (ctx->Array.SecondaryColor.Enabled) { + aa->array = &ctx->Array.SecondaryColor; + aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)]; + aa++; + } + if (ctx->Array.FogCoord.Enabled) { + aa->array = &ctx->Array.FogCoord; + aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)]; + aa++; + } + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + if (ctx->Array.TexCoord[i].Enabled) { + /* NOTE: we use generic glVertexAttrib functions here. + * If we ever de-alias conventional/generic vertex attribs this + * will have to change. + */ + struct gl_client_array *attribArray = &ctx->Array.TexCoord[i]; + at->array = attribArray; + at->func = AttribFuncsNV[at->array->Normalized][at->array->Size-1][TYPE_IDX(at->array->Type)]; + at->index = VERT_ATTRIB_TEX0 + i; + at++; + } + } + + /* generic vertex attribute arrays */ + for (i = 1; i < VERT_ATTRIB_MAX; i++) { /* skip zero! */ + if (ctx->Array.VertexAttrib[i].Enabled) { + struct gl_client_array *attribArray = &ctx->Array.VertexAttrib[i]; + at->array = attribArray; + /* Note: we can't grab the _glapi_Dispatch->VertexAttrib1fvNV + * function pointer here (for float arrays) since the pointer may + * change from one execution of _ae_loopback_array_elt() to + * the next. Doing so caused UT to break. + */ + at->func = AttribFuncsNV[at->array->Normalized][at->array->Size-1][TYPE_IDX(at->array->Type)]; + at->index = i; + at++; + } + } + + /* finally, vertex position */ + if (ctx->Array.VertexAttrib[0].Enabled) { + /* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's + * issued as the last (proviking) attribute). + */ + aa->array = &ctx->Array.VertexAttrib[0]; + assert(aa->array->Size >= 2); /* XXX fix someday? */ + aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; + aa++; + } + else if (ctx->Array.Vertex.Enabled) { + aa->array = &ctx->Array.Vertex; + aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; + aa++; + } + + ASSERT(at - actx->attribs <= VERT_ATTRIB_MAX); + ASSERT(aa - actx->arrays < 32); + at->func = NULL; /* terminate the list */ + aa->offset = -1; /* terminate the list */ + + actx->NewState = 0; +} + + +/** + * Called via glArrayElement() and glDrawArrays(). + * Issue the glNormal, glVertex, glColor, glVertexAttrib, etc functions + * for all enabled vertex arrays (for elt-th element). + * Note: this may be called during display list construction. + */ +void GLAPIENTRY _ae_loopback_array_elt( GLint elt ) +{ + GET_CURRENT_CONTEXT(ctx); + const AEcontext *actx = AE_CONTEXT(ctx); + const AEarray *aa; + const AEattrib *at; + const struct _glapi_table * const disp = GET_DISPATCH(); + + + if (actx->NewState) + _ae_update_state( ctx ); + + /* generic attributes */ + for (at = actx->attribs; at->func; at++) { + const GLubyte *src = at->array->BufferObj->Data + + (uintptr_t) at->array->Ptr + + elt * at->array->StrideB; + at->func( at->index, src ); + } + + /* conventional arrays */ + for (aa = actx->arrays; aa->offset != -1 ; aa++) { + const GLubyte *src = aa->array->BufferObj->Data + + (uintptr_t) aa->array->Ptr + + elt * aa->array->StrideB; + CALL_by_offset( disp, (array_func), aa->offset, + ((const void *) src) ); + } +} + + +void _ae_invalidate_state( GLcontext *ctx, GLuint new_state ) +{ + AE_CONTEXT(ctx)->NewState |= new_state; +} diff --git a/src/mesa/main/api_arrayelt.h b/src/mesa/main/api_arrayelt.h new file mode 100644 index 00000000000..1c0af9f3ea8 --- /dev/null +++ b/src/mesa/main/api_arrayelt.h @@ -0,0 +1,37 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef API_ARRAYELT_H +#define API_ARRAYELT_H + +#include "mtypes.h" + +extern GLboolean _ae_create_context( GLcontext *ctx ); +extern void _ae_destroy_context( GLcontext *ctx ); +extern void _ae_invalidate_state( GLcontext *ctx, GLuint new_state ); +extern void GLAPIENTRY _ae_loopback_array_elt( GLint elt ); + +#endif diff --git a/src/mesa/main/api_eval.h b/src/mesa/main/api_eval.h new file mode 100644 index 00000000000..d6cb38c9f8c --- /dev/null +++ b/src/mesa/main/api_eval.h @@ -0,0 +1,42 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef API_EVAL_H +#define API_EVAL_H + +#include "mtypes.h" + +extern void _mesa_EvalPoint1( GLint i ); +extern void _mesa_EvalPoint2( GLint i, GLint j ); +extern void _mesa_EvalCoord1f( GLfloat u ); +extern void _mesa_EvalCoord2f( GLfloat u, GLfloat v ); +extern void _mesa_EvalCoord1fv( const GLfloat *u ); +extern void _mesa_EvalCoord2fv( const GLfloat *u ); + +#endif + + + diff --git a/src/mesa/main/api_loopback.c b/src/mesa/main/api_loopback.c new file mode 100644 index 00000000000..db30059e61d --- /dev/null +++ b/src/mesa/main/api_loopback.c @@ -0,0 +1,1647 @@ +/** + * \file api_loopback.c + * + * \author Keith Whitwell <[email protected]> + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "glapi.h" +#include "glapitable.h" +#include "macros.h" +#include "colormac.h" +#include "api_loopback.h" +#include "glthread.h" +#include "mtypes.h" +#include "dispatch.h" + +/* KW: A set of functions to convert unusual Color/Normal/Vertex/etc + * calls to a smaller set of driver-provided formats. Currently just + * go back to dispatch to find these (eg. call glNormal3f directly), + * hence 'loopback'. + * + * The driver must supply all of the remaining entry points, which are + * listed in dd.h. The easiest way for a driver to do this is to + * install the supplied software t&l module. + */ +#define COLORF(r,g,b,a) CALL_Color4f(GET_DISPATCH(), (r,g,b,a)) +#define VERTEX2(x,y) CALL_Vertex2f(GET_DISPATCH(), (x,y)) +#define VERTEX3(x,y,z) CALL_Vertex3f(GET_DISPATCH(), (x,y,z)) +#define VERTEX4(x,y,z,w) CALL_Vertex4f(GET_DISPATCH(), (x,y,z,w)) +#define NORMAL(x,y,z) CALL_Normal3f(GET_DISPATCH(), (x,y,z)) +#define TEXCOORD1(s) CALL_TexCoord1f(GET_DISPATCH(), (s)) +#define TEXCOORD2(s,t) CALL_TexCoord2f(GET_DISPATCH(), (s,t)) +#define TEXCOORD3(s,t,u) CALL_TexCoord3f(GET_DISPATCH(), (s,t,u)) +#define TEXCOORD4(s,t,u,v) CALL_TexCoord4f(GET_DISPATCH(), (s,t,u,v)) +#define INDEX(c) CALL_Indexf(GET_DISPATCH(), (c)) +#define MULTI_TEXCOORD1(z,s) CALL_MultiTexCoord1fARB(GET_DISPATCH(), (z,s)) +#define MULTI_TEXCOORD2(z,s,t) CALL_MultiTexCoord2fARB(GET_DISPATCH(), (z,s,t)) +#define MULTI_TEXCOORD3(z,s,t,u) CALL_MultiTexCoord3fARB(GET_DISPATCH(), (z,s,t,u)) +#define MULTI_TEXCOORD4(z,s,t,u,v) CALL_MultiTexCoord4fARB(GET_DISPATCH(), (z,s,t,u,v)) +#define EVALCOORD1(x) CALL_EvalCoord1f(GET_DISPATCH(), (x)) +#define EVALCOORD2(x,y) CALL_EvalCoord2f(GET_DISPATCH(), (x,y)) +#define MATERIALFV(a,b,c) CALL_Materialfv(GET_DISPATCH(), (a,b,c)) +#define RECTF(a,b,c,d) CALL_Rectf(GET_DISPATCH(), (a,b,c,d)) + +#define ATTRIB1NV(index,x) CALL_VertexAttrib1fNV(GET_DISPATCH(), (index,x)) +#define ATTRIB2NV(index,x,y) CALL_VertexAttrib2fNV(GET_DISPATCH(), (index,x,y)) +#define ATTRIB3NV(index,x,y,z) CALL_VertexAttrib3fNV(GET_DISPATCH(), (index,x,y,z)) +#define ATTRIB4NV(index,x,y,z,w) CALL_VertexAttrib4fNV(GET_DISPATCH(), (index,x,y,z,w)) +#define ATTRIB1ARB(index,x) CALL_VertexAttrib1fARB(GET_DISPATCH(), (index,x)) +#define ATTRIB2ARB(index,x,y) CALL_VertexAttrib2fARB(GET_DISPATCH(), (index,x,y)) +#define ATTRIB3ARB(index,x,y,z) CALL_VertexAttrib3fARB(GET_DISPATCH(), (index,x,y,z)) +#define ATTRIB4ARB(index,x,y,z,w) CALL_VertexAttrib4fARB(GET_DISPATCH(), (index,x,y,z,w)) +#define FOGCOORDF(x) CALL_FogCoordfEXT(GET_DISPATCH(), (x)) +#define SECONDARYCOLORF(a,b,c) CALL_SecondaryColor3fEXT(GET_DISPATCH(), (a,b,c)) + +static void GLAPIENTRY +loopback_Color3b_f( GLbyte red, GLbyte green, GLbyte blue ) +{ + COLORF( BYTE_TO_FLOAT(red), + BYTE_TO_FLOAT(green), + BYTE_TO_FLOAT(blue), + 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3d_f( GLdouble red, GLdouble green, GLdouble blue ) +{ + COLORF( (GLfloat) red, (GLfloat) green, (GLfloat) blue, 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3i_f( GLint red, GLint green, GLint blue ) +{ + COLORF( INT_TO_FLOAT(red), INT_TO_FLOAT(green), + INT_TO_FLOAT(blue), 1.0); +} + +static void GLAPIENTRY +loopback_Color3s_f( GLshort red, GLshort green, GLshort blue ) +{ + COLORF( SHORT_TO_FLOAT(red), SHORT_TO_FLOAT(green), + SHORT_TO_FLOAT(blue), 1.0); +} + +static void GLAPIENTRY +loopback_Color3ui_f( GLuint red, GLuint green, GLuint blue ) +{ + COLORF( UINT_TO_FLOAT(red), UINT_TO_FLOAT(green), + UINT_TO_FLOAT(blue), 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3us_f( GLushort red, GLushort green, GLushort blue ) +{ + COLORF( USHORT_TO_FLOAT(red), USHORT_TO_FLOAT(green), + USHORT_TO_FLOAT(blue), 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3ub_f( GLubyte red, GLubyte green, GLubyte blue ) +{ + COLORF( UBYTE_TO_FLOAT(red), UBYTE_TO_FLOAT(green), + UBYTE_TO_FLOAT(blue), 1.0 ); +} + + +static void GLAPIENTRY +loopback_Color3bv_f( const GLbyte *v ) +{ + COLORF( BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]), + BYTE_TO_FLOAT(v[2]), 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3dv_f( const GLdouble *v ) +{ + COLORF( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3iv_f( const GLint *v ) +{ + COLORF( INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]), + INT_TO_FLOAT(v[2]), INT_TO_FLOAT(v[3]) ); +} + +static void GLAPIENTRY +loopback_Color3sv_f( const GLshort *v ) +{ + COLORF( SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]), + SHORT_TO_FLOAT(v[2]), 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3uiv_f( const GLuint *v ) +{ + COLORF( UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]), + UINT_TO_FLOAT(v[2]), 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3usv_f( const GLushort *v ) +{ + COLORF( USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]), + USHORT_TO_FLOAT(v[2]), 1.0 ); +} + +static void GLAPIENTRY +loopback_Color3ubv_f( const GLubyte *v ) +{ + COLORF( UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2]), 1.0 ); +} + + +static void GLAPIENTRY +loopback_Color4b_f( GLbyte red, GLbyte green, GLbyte blue, + GLbyte alpha ) +{ + COLORF( BYTE_TO_FLOAT(red), BYTE_TO_FLOAT(green), + BYTE_TO_FLOAT(blue), BYTE_TO_FLOAT(alpha) ); +} + +static void GLAPIENTRY +loopback_Color4d_f( GLdouble red, GLdouble green, GLdouble blue, + GLdouble alpha ) +{ + COLORF( (GLfloat) red, (GLfloat) green, (GLfloat) blue, (GLfloat) alpha ); +} + +static void GLAPIENTRY +loopback_Color4i_f( GLint red, GLint green, GLint blue, GLint alpha ) +{ + COLORF( INT_TO_FLOAT(red), INT_TO_FLOAT(green), + INT_TO_FLOAT(blue), INT_TO_FLOAT(alpha) ); +} + +static void GLAPIENTRY +loopback_Color4s_f( GLshort red, GLshort green, GLshort blue, + GLshort alpha ) +{ + COLORF( SHORT_TO_FLOAT(red), SHORT_TO_FLOAT(green), + SHORT_TO_FLOAT(blue), SHORT_TO_FLOAT(alpha) ); +} + +static void GLAPIENTRY +loopback_Color4ui_f( GLuint red, GLuint green, GLuint blue, GLuint alpha ) +{ + COLORF( UINT_TO_FLOAT(red), UINT_TO_FLOAT(green), + UINT_TO_FLOAT(blue), UINT_TO_FLOAT(alpha) ); +} + +static void GLAPIENTRY +loopback_Color4us_f( GLushort red, GLushort green, GLushort blue, GLushort alpha ) +{ + COLORF( USHORT_TO_FLOAT(red), USHORT_TO_FLOAT(green), + USHORT_TO_FLOAT(blue), USHORT_TO_FLOAT(alpha) ); +} + +static void GLAPIENTRY +loopback_Color4ub_f( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) +{ + COLORF( UBYTE_TO_FLOAT(red), UBYTE_TO_FLOAT(green), + UBYTE_TO_FLOAT(blue), UBYTE_TO_FLOAT(alpha) ); +} + + +static void GLAPIENTRY +loopback_Color4iv_f( const GLint *v ) +{ + COLORF( INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]), + INT_TO_FLOAT(v[2]), INT_TO_FLOAT(v[3]) ); +} + + +static void GLAPIENTRY +loopback_Color4bv_f( const GLbyte *v ) +{ + COLORF( BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]), + BYTE_TO_FLOAT(v[2]), BYTE_TO_FLOAT(v[3]) ); +} + +static void GLAPIENTRY +loopback_Color4dv_f( const GLdouble *v ) +{ + COLORF( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3] ); +} + + +static void GLAPIENTRY +loopback_Color4sv_f( const GLshort *v) +{ + COLORF( SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]), + SHORT_TO_FLOAT(v[2]), SHORT_TO_FLOAT(v[3]) ); +} + + +static void GLAPIENTRY +loopback_Color4uiv_f( const GLuint *v) +{ + COLORF( UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]), + UINT_TO_FLOAT(v[2]), UINT_TO_FLOAT(v[3]) ); +} + +static void GLAPIENTRY +loopback_Color4usv_f( const GLushort *v) +{ + COLORF( USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]), + USHORT_TO_FLOAT(v[2]), USHORT_TO_FLOAT(v[3]) ); +} + +static void GLAPIENTRY +loopback_Color4ubv_f( const GLubyte *v) +{ + COLORF( UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3]) ); +} + +static void GLAPIENTRY +loopback_FogCoorddEXT( GLdouble d ) +{ + FOGCOORDF( (GLfloat) d ); +} + +static void GLAPIENTRY +loopback_FogCoorddvEXT( const GLdouble *v ) +{ + FOGCOORDF( (GLfloat) *v ); +} + + +static void GLAPIENTRY +loopback_Indexd( GLdouble c ) +{ + INDEX( (GLfloat) c ); +} + +static void GLAPIENTRY +loopback_Indexi( GLint c ) +{ + INDEX( (GLfloat) c ); +} + +static void GLAPIENTRY +loopback_Indexs( GLshort c ) +{ + INDEX( (GLfloat) c ); +} + +static void GLAPIENTRY +loopback_Indexub( GLubyte c ) +{ + INDEX( (GLfloat) c ); +} + +static void GLAPIENTRY +loopback_Indexdv( const GLdouble *c ) +{ + INDEX( (GLfloat) *c ); +} + +static void GLAPIENTRY +loopback_Indexiv( const GLint *c ) +{ + INDEX( (GLfloat) *c ); +} + +static void GLAPIENTRY +loopback_Indexsv( const GLshort *c ) +{ + INDEX( (GLfloat) *c ); +} + +static void GLAPIENTRY +loopback_Indexubv( const GLubyte *c ) +{ + INDEX( (GLfloat) *c ); +} + +static void GLAPIENTRY +loopback_Normal3b( GLbyte nx, GLbyte ny, GLbyte nz ) +{ + NORMAL( BYTE_TO_FLOAT(nx), BYTE_TO_FLOAT(ny), BYTE_TO_FLOAT(nz) ); +} + +static void GLAPIENTRY +loopback_Normal3d( GLdouble nx, GLdouble ny, GLdouble nz ) +{ + NORMAL((GLfloat) nx, (GLfloat) ny, (GLfloat) nz); +} + +static void GLAPIENTRY +loopback_Normal3i( GLint nx, GLint ny, GLint nz ) +{ + NORMAL( INT_TO_FLOAT(nx), INT_TO_FLOAT(ny), INT_TO_FLOAT(nz) ); +} + +static void GLAPIENTRY +loopback_Normal3s( GLshort nx, GLshort ny, GLshort nz ) +{ + NORMAL( SHORT_TO_FLOAT(nx), SHORT_TO_FLOAT(ny), SHORT_TO_FLOAT(nz) ); +} + +static void GLAPIENTRY +loopback_Normal3bv( const GLbyte *v ) +{ + NORMAL( BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]), BYTE_TO_FLOAT(v[2]) ); +} + +static void GLAPIENTRY +loopback_Normal3dv( const GLdouble *v ) +{ + NORMAL( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_Normal3iv( const GLint *v ) +{ + NORMAL( INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]), INT_TO_FLOAT(v[2]) ); +} + +static void GLAPIENTRY +loopback_Normal3sv( const GLshort *v ) +{ + NORMAL( SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]), SHORT_TO_FLOAT(v[2]) ); +} + +static void GLAPIENTRY +loopback_TexCoord1d( GLdouble s ) +{ + TEXCOORD1((GLfloat) s); +} + +static void GLAPIENTRY +loopback_TexCoord1i( GLint s ) +{ + TEXCOORD1((GLfloat) s); +} + +static void GLAPIENTRY +loopback_TexCoord1s( GLshort s ) +{ + TEXCOORD1((GLfloat) s); +} + +static void GLAPIENTRY +loopback_TexCoord2d( GLdouble s, GLdouble t ) +{ + TEXCOORD2((GLfloat) s,(GLfloat) t); +} + +static void GLAPIENTRY +loopback_TexCoord2s( GLshort s, GLshort t ) +{ + TEXCOORD2((GLfloat) s,(GLfloat) t); +} + +static void GLAPIENTRY +loopback_TexCoord2i( GLint s, GLint t ) +{ + TEXCOORD2((GLfloat) s,(GLfloat) t); +} + +static void GLAPIENTRY +loopback_TexCoord3d( GLdouble s, GLdouble t, GLdouble r ) +{ + TEXCOORD3((GLfloat) s,(GLfloat) t,(GLfloat) r); +} + +static void GLAPIENTRY +loopback_TexCoord3i( GLint s, GLint t, GLint r ) +{ + TEXCOORD3((GLfloat) s,(GLfloat) t,(GLfloat) r); +} + +static void GLAPIENTRY +loopback_TexCoord3s( GLshort s, GLshort t, GLshort r ) +{ + TEXCOORD3((GLfloat) s,(GLfloat) t,(GLfloat) r); +} + +static void GLAPIENTRY +loopback_TexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q ) +{ + TEXCOORD4((GLfloat) s,(GLfloat) t,(GLfloat) r,(GLfloat) q); +} + +static void GLAPIENTRY +loopback_TexCoord4i( GLint s, GLint t, GLint r, GLint q ) +{ + TEXCOORD4((GLfloat) s,(GLfloat) t,(GLfloat) r,(GLfloat) q); +} + +static void GLAPIENTRY +loopback_TexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q ) +{ + TEXCOORD4((GLfloat) s,(GLfloat) t,(GLfloat) r,(GLfloat) q); +} + +static void GLAPIENTRY +loopback_TexCoord1dv( const GLdouble *v ) +{ + TEXCOORD1((GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_TexCoord1iv( const GLint *v ) +{ + TEXCOORD1((GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_TexCoord1sv( const GLshort *v ) +{ + TEXCOORD1((GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_TexCoord2dv( const GLdouble *v ) +{ + TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_TexCoord2iv( const GLint *v ) +{ + TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_TexCoord2sv( const GLshort *v ) +{ + TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_TexCoord3dv( const GLdouble *v ) +{ + TEXCOORD2((GLfloat) v[0],(GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_TexCoord3iv( const GLint *v ) +{ + TEXCOORD3((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2]); +} + +static void GLAPIENTRY +loopback_TexCoord3sv( const GLshort *v ) +{ + TEXCOORD3((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2]); +} + +static void GLAPIENTRY +loopback_TexCoord4dv( const GLdouble *v ) +{ + TEXCOORD4((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2],(GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_TexCoord4iv( const GLint *v ) +{ + TEXCOORD4((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2],(GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_TexCoord4sv( const GLshort *v ) +{ + TEXCOORD4((GLfloat) v[0],(GLfloat) v[1],(GLfloat) v[2],(GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_Vertex2d( GLdouble x, GLdouble y ) +{ + VERTEX2( (GLfloat) x, (GLfloat) y ); +} + +static void GLAPIENTRY +loopback_Vertex2i( GLint x, GLint y ) +{ + VERTEX2( (GLfloat) x, (GLfloat) y ); +} + +static void GLAPIENTRY +loopback_Vertex2s( GLshort x, GLshort y ) +{ + VERTEX2( (GLfloat) x, (GLfloat) y ); +} + +static void GLAPIENTRY +loopback_Vertex3d( GLdouble x, GLdouble y, GLdouble z ) +{ + VERTEX3( (GLfloat) x, (GLfloat) y, (GLfloat) z ); +} + +static void GLAPIENTRY +loopback_Vertex3i( GLint x, GLint y, GLint z ) +{ + VERTEX3( (GLfloat) x, (GLfloat) y, (GLfloat) z ); +} + +static void GLAPIENTRY +loopback_Vertex3s( GLshort x, GLshort y, GLshort z ) +{ + VERTEX3( (GLfloat) x, (GLfloat) y, (GLfloat) z ); +} + +static void GLAPIENTRY +loopback_Vertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w ) +{ + VERTEX4( (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w ); +} + +static void GLAPIENTRY +loopback_Vertex4i( GLint x, GLint y, GLint z, GLint w ) +{ + VERTEX4( (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w ); +} + +static void GLAPIENTRY +loopback_Vertex4s( GLshort x, GLshort y, GLshort z, GLshort w ) +{ + VERTEX4( (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w ); +} + +static void GLAPIENTRY +loopback_Vertex2dv( const GLdouble *v ) +{ + VERTEX2( (GLfloat) v[0], (GLfloat) v[1] ); +} + +static void GLAPIENTRY +loopback_Vertex2iv( const GLint *v ) +{ + VERTEX2( (GLfloat) v[0], (GLfloat) v[1] ); +} + +static void GLAPIENTRY +loopback_Vertex2sv( const GLshort *v ) +{ + VERTEX2( (GLfloat) v[0], (GLfloat) v[1] ); +} + +static void GLAPIENTRY +loopback_Vertex3dv( const GLdouble *v ) +{ + VERTEX3( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_Vertex3iv( const GLint *v ) +{ + VERTEX3( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_Vertex3sv( const GLshort *v ) +{ + VERTEX3( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_Vertex4dv( const GLdouble *v ) +{ + VERTEX4( (GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3] ); +} + +static void GLAPIENTRY +loopback_Vertex4iv( const GLint *v ) +{ + VERTEX4( (GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3] ); +} + +static void GLAPIENTRY +loopback_Vertex4sv( const GLshort *v ) +{ + VERTEX4( (GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord1dARB(GLenum target, GLdouble s) +{ + MULTI_TEXCOORD1( target, (GLfloat) s ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord1dvARB(GLenum target, const GLdouble *v) +{ + MULTI_TEXCOORD1( target, (GLfloat) v[0] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord1iARB(GLenum target, GLint s) +{ + MULTI_TEXCOORD1( target, (GLfloat) s ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord1ivARB(GLenum target, const GLint *v) +{ + MULTI_TEXCOORD1( target, (GLfloat) v[0] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord1sARB(GLenum target, GLshort s) +{ + MULTI_TEXCOORD1( target, (GLfloat) s ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord1svARB(GLenum target, const GLshort *v) +{ + MULTI_TEXCOORD1( target, (GLfloat) v[0] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t) +{ + MULTI_TEXCOORD2( target, (GLfloat) s, (GLfloat) t ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord2dvARB(GLenum target, const GLdouble *v) +{ + MULTI_TEXCOORD2( target, (GLfloat) v[0], (GLfloat) v[1] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord2iARB(GLenum target, GLint s, GLint t) +{ + MULTI_TEXCOORD2( target, (GLfloat) s, (GLfloat) t ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord2ivARB(GLenum target, const GLint *v) +{ + MULTI_TEXCOORD2( target, (GLfloat) v[0], (GLfloat) v[1] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord2sARB(GLenum target, GLshort s, GLshort t) +{ + MULTI_TEXCOORD2( target, (GLfloat) s, (GLfloat) t ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord2svARB(GLenum target, const GLshort *v) +{ + MULTI_TEXCOORD2( target, (GLfloat) v[0], (GLfloat) v[1] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r) +{ + MULTI_TEXCOORD3( target, (GLfloat) s, (GLfloat) t, (GLfloat) r ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord3dvARB(GLenum target, const GLdouble *v) +{ + MULTI_TEXCOORD3( target, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r) +{ + MULTI_TEXCOORD3( target, (GLfloat) s, (GLfloat) t, (GLfloat) r ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord3ivARB(GLenum target, const GLint *v) +{ + MULTI_TEXCOORD3( target, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r) +{ + MULTI_TEXCOORD3( target, (GLfloat) s, (GLfloat) t, (GLfloat) r ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord3svARB(GLenum target, const GLshort *v) +{ + MULTI_TEXCOORD3( target, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q) +{ + MULTI_TEXCOORD4( target, (GLfloat) s, (GLfloat) t, + (GLfloat) r, (GLfloat) q ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord4dvARB(GLenum target, const GLdouble *v) +{ + MULTI_TEXCOORD4( target, (GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q) +{ + MULTI_TEXCOORD4( target, (GLfloat) s, (GLfloat) t, + (GLfloat) r, (GLfloat) q ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord4ivARB(GLenum target, const GLint *v) +{ + MULTI_TEXCOORD4( target, (GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3] ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q) +{ + MULTI_TEXCOORD4( target, (GLfloat) s, (GLfloat) t, + (GLfloat) r, (GLfloat) q ); +} + +static void GLAPIENTRY +loopback_MultiTexCoord4svARB(GLenum target, const GLshort *v) +{ + MULTI_TEXCOORD4( target, (GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3] ); +} + +static void GLAPIENTRY +loopback_EvalCoord2dv( const GLdouble *u ) +{ + EVALCOORD2( (GLfloat) u[0], (GLfloat) u[1] ); +} + +static void GLAPIENTRY +loopback_EvalCoord2fv( const GLfloat *u ) +{ + EVALCOORD2( u[0], u[1] ); +} + +static void GLAPIENTRY +loopback_EvalCoord2d( GLdouble u, GLdouble v ) +{ + EVALCOORD2( (GLfloat) u, (GLfloat) v ); +} + +static void GLAPIENTRY +loopback_EvalCoord1dv( const GLdouble *u ) +{ + EVALCOORD1( (GLfloat) *u ); +} + +static void GLAPIENTRY +loopback_EvalCoord1fv( const GLfloat *u ) +{ + EVALCOORD1( (GLfloat) *u ); +} + +static void GLAPIENTRY +loopback_EvalCoord1d( GLdouble u ) +{ + EVALCOORD1( (GLfloat) u ); +} + +static void GLAPIENTRY +loopback_Materialf( GLenum face, GLenum pname, GLfloat param ) +{ + GLfloat fparam[4]; + fparam[0] = param; + MATERIALFV( face, pname, fparam ); +} + +static void GLAPIENTRY +loopback_Materiali(GLenum face, GLenum pname, GLint param ) +{ + GLfloat p = (GLfloat) param; + MATERIALFV(face, pname, &p); +} + +static void GLAPIENTRY +loopback_Materialiv(GLenum face, GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + switch (pname) { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_EMISSION: + case GL_AMBIENT_AND_DIFFUSE: + fparam[0] = INT_TO_FLOAT( params[0] ); + fparam[1] = INT_TO_FLOAT( params[1] ); + fparam[2] = INT_TO_FLOAT( params[2] ); + fparam[3] = INT_TO_FLOAT( params[3] ); + break; + case GL_SHININESS: + fparam[0] = (GLfloat) params[0]; + break; + case GL_COLOR_INDEXES: + fparam[0] = (GLfloat) params[0]; + fparam[1] = (GLfloat) params[1]; + fparam[2] = (GLfloat) params[2]; + break; + default: + ; + } + MATERIALFV(face, pname, fparam); +} + + +static void GLAPIENTRY +loopback_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) +{ + RECTF((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); +} + +static void GLAPIENTRY +loopback_Rectdv(const GLdouble *v1, const GLdouble *v2) +{ + RECTF((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); +} + +static void GLAPIENTRY +loopback_Rectfv(const GLfloat *v1, const GLfloat *v2) +{ + RECTF(v1[0], v1[1], v2[0], v2[1]); +} + +static void GLAPIENTRY +loopback_Recti(GLint x1, GLint y1, GLint x2, GLint y2) +{ + RECTF((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); +} + +static void GLAPIENTRY +loopback_Rectiv(const GLint *v1, const GLint *v2) +{ + RECTF((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); +} + +static void GLAPIENTRY +loopback_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) +{ + RECTF((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); +} + +static void GLAPIENTRY +loopback_Rectsv(const GLshort *v1, const GLshort *v2) +{ + RECTF((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); +} + +static void GLAPIENTRY +loopback_SecondaryColor3bEXT_f( GLbyte red, GLbyte green, GLbyte blue ) +{ + SECONDARYCOLORF( BYTE_TO_FLOAT(red), + BYTE_TO_FLOAT(green), + BYTE_TO_FLOAT(blue) ); +} + +static void GLAPIENTRY +loopback_SecondaryColor3dEXT_f( GLdouble red, GLdouble green, GLdouble blue ) +{ + SECONDARYCOLORF( (GLfloat) red, (GLfloat) green, (GLfloat) blue ); +} + +static void GLAPIENTRY +loopback_SecondaryColor3iEXT_f( GLint red, GLint green, GLint blue ) +{ + SECONDARYCOLORF( INT_TO_FLOAT(red), + INT_TO_FLOAT(green), + INT_TO_FLOAT(blue)); +} + +static void GLAPIENTRY +loopback_SecondaryColor3sEXT_f( GLshort red, GLshort green, GLshort blue ) +{ + SECONDARYCOLORF(SHORT_TO_FLOAT(red), + SHORT_TO_FLOAT(green), + SHORT_TO_FLOAT(blue)); +} + +static void GLAPIENTRY +loopback_SecondaryColor3uiEXT_f( GLuint red, GLuint green, GLuint blue ) +{ + SECONDARYCOLORF(UINT_TO_FLOAT(red), + UINT_TO_FLOAT(green), + UINT_TO_FLOAT(blue)); +} + +static void GLAPIENTRY +loopback_SecondaryColor3usEXT_f( GLushort red, GLushort green, GLushort blue ) +{ + SECONDARYCOLORF(USHORT_TO_FLOAT(red), + USHORT_TO_FLOAT(green), + USHORT_TO_FLOAT(blue)); +} + +static void GLAPIENTRY +loopback_SecondaryColor3ubEXT_f( GLubyte red, GLubyte green, GLubyte blue ) +{ + SECONDARYCOLORF(UBYTE_TO_FLOAT(red), + UBYTE_TO_FLOAT(green), + UBYTE_TO_FLOAT(blue)); +} + +static void GLAPIENTRY +loopback_SecondaryColor3bvEXT_f( const GLbyte *v ) +{ + SECONDARYCOLORF(BYTE_TO_FLOAT(v[0]), + BYTE_TO_FLOAT(v[1]), + BYTE_TO_FLOAT(v[2])); +} + +static void GLAPIENTRY +loopback_SecondaryColor3dvEXT_f( const GLdouble *v ) +{ + SECONDARYCOLORF( (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] ); +} +static void GLAPIENTRY +loopback_SecondaryColor3ivEXT_f( const GLint *v ) +{ + SECONDARYCOLORF(INT_TO_FLOAT(v[0]), + INT_TO_FLOAT(v[1]), + INT_TO_FLOAT(v[2])); +} + +static void GLAPIENTRY +loopback_SecondaryColor3svEXT_f( const GLshort *v ) +{ + SECONDARYCOLORF(SHORT_TO_FLOAT(v[0]), + SHORT_TO_FLOAT(v[1]), + SHORT_TO_FLOAT(v[2])); +} + +static void GLAPIENTRY +loopback_SecondaryColor3uivEXT_f( const GLuint *v ) +{ + SECONDARYCOLORF(UINT_TO_FLOAT(v[0]), + UINT_TO_FLOAT(v[1]), + UINT_TO_FLOAT(v[2])); +} + +static void GLAPIENTRY +loopback_SecondaryColor3usvEXT_f( const GLushort *v ) +{ + SECONDARYCOLORF(USHORT_TO_FLOAT(v[0]), + USHORT_TO_FLOAT(v[1]), + USHORT_TO_FLOAT(v[2])); +} + +static void GLAPIENTRY +loopback_SecondaryColor3ubvEXT_f( const GLubyte *v ) +{ + SECONDARYCOLORF(UBYTE_TO_FLOAT(v[0]), + UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2])); +} + + +/* + * GL_NV_vertex_program: + * Always loop-back to one of the VertexAttrib[1234]f[v]NV functions. + */ + +static void GLAPIENTRY +loopback_VertexAttrib1sNV(GLuint index, GLshort x) +{ + ATTRIB1NV(index, (GLfloat) x); +} + +static void GLAPIENTRY +loopback_VertexAttrib1dNV(GLuint index, GLdouble x) +{ + ATTRIB1NV(index, (GLfloat) x); +} + +static void GLAPIENTRY +loopback_VertexAttrib2sNV(GLuint index, GLshort x, GLshort y) +{ + ATTRIB2NV(index, (GLfloat) x, y); +} + +static void GLAPIENTRY +loopback_VertexAttrib2dNV(GLuint index, GLdouble x, GLdouble y) +{ + ATTRIB2NV(index, (GLfloat) x, (GLfloat) y); +} + +static void GLAPIENTRY +loopback_VertexAttrib3sNV(GLuint index, GLshort x, GLshort y, GLshort z) +{ + ATTRIB3NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z); +} + +static void GLAPIENTRY +loopback_VertexAttrib3dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + ATTRIB4NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +static void GLAPIENTRY +loopback_VertexAttrib4sNV(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + ATTRIB4NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY +loopback_VertexAttrib4dNV(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + ATTRIB4NV(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY +loopback_VertexAttrib4ubNV(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + ATTRIB4NV(index, UBYTE_TO_FLOAT(x), UBYTE_TO_FLOAT(y), + UBYTE_TO_FLOAT(z), UBYTE_TO_FLOAT(w)); +} + +static void GLAPIENTRY +loopback_VertexAttrib1svNV(GLuint index, const GLshort *v) +{ + ATTRIB1NV(index, (GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_VertexAttrib1dvNV(GLuint index, const GLdouble *v) +{ + ATTRIB1NV(index, (GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_VertexAttrib2svNV(GLuint index, const GLshort *v) +{ + ATTRIB2NV(index, (GLfloat) v[0], (GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_VertexAttrib2dvNV(GLuint index, const GLdouble *v) +{ + ATTRIB2NV(index, (GLfloat) v[0], (GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_VertexAttrib3svNV(GLuint index, const GLshort *v) +{ + ATTRIB3NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + +static void GLAPIENTRY +loopback_VertexAttrib3dvNV(GLuint index, const GLdouble *v) +{ + ATTRIB3NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4svNV(GLuint index, const GLshort *v) +{ + ATTRIB4NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + (GLfloat)v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4dvNV(GLuint index, const GLdouble *v) +{ + ATTRIB4NV(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4ubvNV(GLuint index, const GLubyte *v) +{ + ATTRIB4NV(index, UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3])); +} + + +static void GLAPIENTRY +loopback_VertexAttribs1svNV(GLuint index, GLsizei n, const GLshort *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib1svNV(index + i, v + i); +} + +static void GLAPIENTRY +loopback_VertexAttribs1fvNV(GLuint index, GLsizei n, const GLfloat *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + ATTRIB1NV(index + i, v[i]); +} + +static void GLAPIENTRY +loopback_VertexAttribs1dvNV(GLuint index, GLsizei n, const GLdouble *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib1dvNV(index + i, v + i); +} + +static void GLAPIENTRY +loopback_VertexAttribs2svNV(GLuint index, GLsizei n, const GLshort *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib2svNV(index + i, v + 2 * i); +} + +static void GLAPIENTRY +loopback_VertexAttribs2fvNV(GLuint index, GLsizei n, const GLfloat *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + ATTRIB2NV(index + i, v[2 * i], v[2 * i + 1]); +} + +static void GLAPIENTRY +loopback_VertexAttribs2dvNV(GLuint index, GLsizei n, const GLdouble *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib2dvNV(index + i, v + 2 * i); +} + +static void GLAPIENTRY +loopback_VertexAttribs3svNV(GLuint index, GLsizei n, const GLshort *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib3svNV(index + i, v + 3 * i); +} + +static void GLAPIENTRY +loopback_VertexAttribs3fvNV(GLuint index, GLsizei n, const GLfloat *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + ATTRIB3NV(index + i, v[3 * i], v[3 * i + 1], v[3 * i + 2]); +} + +static void GLAPIENTRY +loopback_VertexAttribs3dvNV(GLuint index, GLsizei n, const GLdouble *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib3dvNV(index + i, v + 3 * i); +} + +static void GLAPIENTRY +loopback_VertexAttribs4svNV(GLuint index, GLsizei n, const GLshort *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib4svNV(index + i, v + 4 * i); +} + +static void GLAPIENTRY +loopback_VertexAttribs4fvNV(GLuint index, GLsizei n, const GLfloat *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + ATTRIB4NV(index + i, v[4 * i], v[4 * i + 1], v[4 * i + 2], v[4 * i + 3]); +} + +static void GLAPIENTRY +loopback_VertexAttribs4dvNV(GLuint index, GLsizei n, const GLdouble *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib4dvNV(index + i, v + 4 * i); +} + +static void GLAPIENTRY +loopback_VertexAttribs4ubvNV(GLuint index, GLsizei n, const GLubyte *v) +{ + GLint i; + for (i = n - 1; i >= 0; i--) + loopback_VertexAttrib4ubvNV(index + i, v + 4 * i); +} + + +/* + * GL_ARB_vertex_program + * Always loop-back to one of the VertexAttrib[1234]f[v]ARB functions. + */ + +static void GLAPIENTRY +loopback_VertexAttrib1sARB(GLuint index, GLshort x) +{ + ATTRIB1ARB(index, (GLfloat) x); +} + +static void GLAPIENTRY +loopback_VertexAttrib1dARB(GLuint index, GLdouble x) +{ + ATTRIB1ARB(index, (GLfloat) x); +} + +static void GLAPIENTRY +loopback_VertexAttrib2sARB(GLuint index, GLshort x, GLshort y) +{ + ATTRIB2ARB(index, (GLfloat) x, y); +} + +static void GLAPIENTRY +loopback_VertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y) +{ + ATTRIB2ARB(index, (GLfloat) x, (GLfloat) y); +} + +static void GLAPIENTRY +loopback_VertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z) +{ + ATTRIB3ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z); +} + +static void GLAPIENTRY +loopback_VertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z) +{ + ATTRIB4ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +static void GLAPIENTRY +loopback_VertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w) +{ + ATTRIB4ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY +loopback_VertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + ATTRIB4ARB(index, (GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY +loopback_VertexAttrib1svARB(GLuint index, const GLshort *v) +{ + ATTRIB1ARB(index, (GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_VertexAttrib1dvARB(GLuint index, const GLdouble *v) +{ + ATTRIB1ARB(index, (GLfloat) v[0]); +} + +static void GLAPIENTRY +loopback_VertexAttrib2svARB(GLuint index, const GLshort *v) +{ + ATTRIB2ARB(index, (GLfloat) v[0], (GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_VertexAttrib2dvARB(GLuint index, const GLdouble *v) +{ + ATTRIB2ARB(index, (GLfloat) v[0], (GLfloat) v[1]); +} + +static void GLAPIENTRY +loopback_VertexAttrib3svARB(GLuint index, const GLshort *v) +{ + ATTRIB3ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + +static void GLAPIENTRY +loopback_VertexAttrib3dvARB(GLuint index, const GLdouble *v) +{ + ATTRIB3ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4svARB(GLuint index, const GLshort *v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], + (GLfloat)v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4dvARB(GLuint index, const GLdouble *v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4bvARB(GLuint index, const GLbyte * v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4ivARB(GLuint index, const GLint * v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4ubvARB(GLuint index, const GLubyte * v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4usvARB(GLuint index, const GLushort * v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4uivARB(GLuint index, const GLuint * v) +{ + ATTRIB4ARB(index, (GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NbvARB(GLuint index, const GLbyte * v) +{ + ATTRIB4ARB(index, BYTE_TO_FLOAT(v[0]), BYTE_TO_FLOAT(v[1]), + BYTE_TO_FLOAT(v[2]), BYTE_TO_FLOAT(v[3])); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NsvARB(GLuint index, const GLshort * v) +{ + ATTRIB4ARB(index, SHORT_TO_FLOAT(v[0]), SHORT_TO_FLOAT(v[1]), + SHORT_TO_FLOAT(v[2]), SHORT_TO_FLOAT(v[3])); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NivARB(GLuint index, const GLint * v) +{ + ATTRIB4ARB(index, INT_TO_FLOAT(v[0]), INT_TO_FLOAT(v[1]), + INT_TO_FLOAT(v[2]), INT_TO_FLOAT(v[3])); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w) +{ + ATTRIB4ARB(index, UBYTE_TO_FLOAT(x), UBYTE_TO_FLOAT(y), + UBYTE_TO_FLOAT(z), UBYTE_TO_FLOAT(w)); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NubvARB(GLuint index, const GLubyte * v) +{ + ATTRIB4ARB(index, UBYTE_TO_FLOAT(v[0]), UBYTE_TO_FLOAT(v[1]), + UBYTE_TO_FLOAT(v[2]), UBYTE_TO_FLOAT(v[3])); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NusvARB(GLuint index, const GLushort * v) +{ + ATTRIB4ARB(index, USHORT_TO_FLOAT(v[0]), USHORT_TO_FLOAT(v[1]), + USHORT_TO_FLOAT(v[2]), USHORT_TO_FLOAT(v[3])); +} + +static void GLAPIENTRY +loopback_VertexAttrib4NuivARB(GLuint index, const GLuint * v) +{ + ATTRIB4ARB(index, UINT_TO_FLOAT(v[0]), UINT_TO_FLOAT(v[1]), + UINT_TO_FLOAT(v[2]), UINT_TO_FLOAT(v[3])); +} + + + + +/* + * This code never registers handlers for any of the entry points + * listed in vtxfmt.h. + */ +void +_mesa_loopback_init_api_table( struct _glapi_table *dest ) +{ + SET_Color3b(dest, loopback_Color3b_f); + SET_Color3d(dest, loopback_Color3d_f); + SET_Color3i(dest, loopback_Color3i_f); + SET_Color3s(dest, loopback_Color3s_f); + SET_Color3ui(dest, loopback_Color3ui_f); + SET_Color3us(dest, loopback_Color3us_f); + SET_Color3ub(dest, loopback_Color3ub_f); + SET_Color4b(dest, loopback_Color4b_f); + SET_Color4d(dest, loopback_Color4d_f); + SET_Color4i(dest, loopback_Color4i_f); + SET_Color4s(dest, loopback_Color4s_f); + SET_Color4ui(dest, loopback_Color4ui_f); + SET_Color4us(dest, loopback_Color4us_f); + SET_Color4ub(dest, loopback_Color4ub_f); + SET_Color3bv(dest, loopback_Color3bv_f); + SET_Color3dv(dest, loopback_Color3dv_f); + SET_Color3iv(dest, loopback_Color3iv_f); + SET_Color3sv(dest, loopback_Color3sv_f); + SET_Color3uiv(dest, loopback_Color3uiv_f); + SET_Color3usv(dest, loopback_Color3usv_f); + SET_Color3ubv(dest, loopback_Color3ubv_f); + SET_Color4bv(dest, loopback_Color4bv_f); + SET_Color4dv(dest, loopback_Color4dv_f); + SET_Color4iv(dest, loopback_Color4iv_f); + SET_Color4sv(dest, loopback_Color4sv_f); + SET_Color4uiv(dest, loopback_Color4uiv_f); + SET_Color4usv(dest, loopback_Color4usv_f); + SET_Color4ubv(dest, loopback_Color4ubv_f); + + SET_SecondaryColor3bEXT(dest, loopback_SecondaryColor3bEXT_f); + SET_SecondaryColor3dEXT(dest, loopback_SecondaryColor3dEXT_f); + SET_SecondaryColor3iEXT(dest, loopback_SecondaryColor3iEXT_f); + SET_SecondaryColor3sEXT(dest, loopback_SecondaryColor3sEXT_f); + SET_SecondaryColor3uiEXT(dest, loopback_SecondaryColor3uiEXT_f); + SET_SecondaryColor3usEXT(dest, loopback_SecondaryColor3usEXT_f); + SET_SecondaryColor3ubEXT(dest, loopback_SecondaryColor3ubEXT_f); + SET_SecondaryColor3bvEXT(dest, loopback_SecondaryColor3bvEXT_f); + SET_SecondaryColor3dvEXT(dest, loopback_SecondaryColor3dvEXT_f); + SET_SecondaryColor3ivEXT(dest, loopback_SecondaryColor3ivEXT_f); + SET_SecondaryColor3svEXT(dest, loopback_SecondaryColor3svEXT_f); + SET_SecondaryColor3uivEXT(dest, loopback_SecondaryColor3uivEXT_f); + SET_SecondaryColor3usvEXT(dest, loopback_SecondaryColor3usvEXT_f); + SET_SecondaryColor3ubvEXT(dest, loopback_SecondaryColor3ubvEXT_f); + + SET_Indexd(dest, loopback_Indexd); + SET_Indexi(dest, loopback_Indexi); + SET_Indexs(dest, loopback_Indexs); + SET_Indexub(dest, loopback_Indexub); + SET_Indexdv(dest, loopback_Indexdv); + SET_Indexiv(dest, loopback_Indexiv); + SET_Indexsv(dest, loopback_Indexsv); + SET_Indexubv(dest, loopback_Indexubv); + SET_Normal3b(dest, loopback_Normal3b); + SET_Normal3d(dest, loopback_Normal3d); + SET_Normal3i(dest, loopback_Normal3i); + SET_Normal3s(dest, loopback_Normal3s); + SET_Normal3bv(dest, loopback_Normal3bv); + SET_Normal3dv(dest, loopback_Normal3dv); + SET_Normal3iv(dest, loopback_Normal3iv); + SET_Normal3sv(dest, loopback_Normal3sv); + SET_TexCoord1d(dest, loopback_TexCoord1d); + SET_TexCoord1i(dest, loopback_TexCoord1i); + SET_TexCoord1s(dest, loopback_TexCoord1s); + SET_TexCoord2d(dest, loopback_TexCoord2d); + SET_TexCoord2s(dest, loopback_TexCoord2s); + SET_TexCoord2i(dest, loopback_TexCoord2i); + SET_TexCoord3d(dest, loopback_TexCoord3d); + SET_TexCoord3i(dest, loopback_TexCoord3i); + SET_TexCoord3s(dest, loopback_TexCoord3s); + SET_TexCoord4d(dest, loopback_TexCoord4d); + SET_TexCoord4i(dest, loopback_TexCoord4i); + SET_TexCoord4s(dest, loopback_TexCoord4s); + SET_TexCoord1dv(dest, loopback_TexCoord1dv); + SET_TexCoord1iv(dest, loopback_TexCoord1iv); + SET_TexCoord1sv(dest, loopback_TexCoord1sv); + SET_TexCoord2dv(dest, loopback_TexCoord2dv); + SET_TexCoord2iv(dest, loopback_TexCoord2iv); + SET_TexCoord2sv(dest, loopback_TexCoord2sv); + SET_TexCoord3dv(dest, loopback_TexCoord3dv); + SET_TexCoord3iv(dest, loopback_TexCoord3iv); + SET_TexCoord3sv(dest, loopback_TexCoord3sv); + SET_TexCoord4dv(dest, loopback_TexCoord4dv); + SET_TexCoord4iv(dest, loopback_TexCoord4iv); + SET_TexCoord4sv(dest, loopback_TexCoord4sv); + SET_Vertex2d(dest, loopback_Vertex2d); + SET_Vertex2i(dest, loopback_Vertex2i); + SET_Vertex2s(dest, loopback_Vertex2s); + SET_Vertex3d(dest, loopback_Vertex3d); + SET_Vertex3i(dest, loopback_Vertex3i); + SET_Vertex3s(dest, loopback_Vertex3s); + SET_Vertex4d(dest, loopback_Vertex4d); + SET_Vertex4i(dest, loopback_Vertex4i); + SET_Vertex4s(dest, loopback_Vertex4s); + SET_Vertex2dv(dest, loopback_Vertex2dv); + SET_Vertex2iv(dest, loopback_Vertex2iv); + SET_Vertex2sv(dest, loopback_Vertex2sv); + SET_Vertex3dv(dest, loopback_Vertex3dv); + SET_Vertex3iv(dest, loopback_Vertex3iv); + SET_Vertex3sv(dest, loopback_Vertex3sv); + SET_Vertex4dv(dest, loopback_Vertex4dv); + SET_Vertex4iv(dest, loopback_Vertex4iv); + SET_Vertex4sv(dest, loopback_Vertex4sv); + SET_MultiTexCoord1dARB(dest, loopback_MultiTexCoord1dARB); + SET_MultiTexCoord1dvARB(dest, loopback_MultiTexCoord1dvARB); + SET_MultiTexCoord1iARB(dest, loopback_MultiTexCoord1iARB); + SET_MultiTexCoord1ivARB(dest, loopback_MultiTexCoord1ivARB); + SET_MultiTexCoord1sARB(dest, loopback_MultiTexCoord1sARB); + SET_MultiTexCoord1svARB(dest, loopback_MultiTexCoord1svARB); + SET_MultiTexCoord2dARB(dest, loopback_MultiTexCoord2dARB); + SET_MultiTexCoord2dvARB(dest, loopback_MultiTexCoord2dvARB); + SET_MultiTexCoord2iARB(dest, loopback_MultiTexCoord2iARB); + SET_MultiTexCoord2ivARB(dest, loopback_MultiTexCoord2ivARB); + SET_MultiTexCoord2sARB(dest, loopback_MultiTexCoord2sARB); + SET_MultiTexCoord2svARB(dest, loopback_MultiTexCoord2svARB); + SET_MultiTexCoord3dARB(dest, loopback_MultiTexCoord3dARB); + SET_MultiTexCoord3dvARB(dest, loopback_MultiTexCoord3dvARB); + SET_MultiTexCoord3iARB(dest, loopback_MultiTexCoord3iARB); + SET_MultiTexCoord3ivARB(dest, loopback_MultiTexCoord3ivARB); + SET_MultiTexCoord3sARB(dest, loopback_MultiTexCoord3sARB); + SET_MultiTexCoord3svARB(dest, loopback_MultiTexCoord3svARB); + SET_MultiTexCoord4dARB(dest, loopback_MultiTexCoord4dARB); + SET_MultiTexCoord4dvARB(dest, loopback_MultiTexCoord4dvARB); + SET_MultiTexCoord4iARB(dest, loopback_MultiTexCoord4iARB); + SET_MultiTexCoord4ivARB(dest, loopback_MultiTexCoord4ivARB); + SET_MultiTexCoord4sARB(dest, loopback_MultiTexCoord4sARB); + SET_MultiTexCoord4svARB(dest, loopback_MultiTexCoord4svARB); + SET_EvalCoord2dv(dest, loopback_EvalCoord2dv); + SET_EvalCoord2fv(dest, loopback_EvalCoord2fv); + SET_EvalCoord2d(dest, loopback_EvalCoord2d); + SET_EvalCoord1dv(dest, loopback_EvalCoord1dv); + SET_EvalCoord1fv(dest, loopback_EvalCoord1fv); + SET_EvalCoord1d(dest, loopback_EvalCoord1d); + SET_Materialf(dest, loopback_Materialf); + SET_Materiali(dest, loopback_Materiali); + SET_Materialiv(dest, loopback_Materialiv); + SET_Rectd(dest, loopback_Rectd); + SET_Rectdv(dest, loopback_Rectdv); + SET_Rectfv(dest, loopback_Rectfv); + SET_Recti(dest, loopback_Recti); + SET_Rectiv(dest, loopback_Rectiv); + SET_Rects(dest, loopback_Rects); + SET_Rectsv(dest, loopback_Rectsv); + SET_FogCoorddEXT(dest, loopback_FogCoorddEXT); + SET_FogCoorddvEXT(dest, loopback_FogCoorddvEXT); + + SET_VertexAttrib1sNV(dest, loopback_VertexAttrib1sNV); + SET_VertexAttrib1dNV(dest, loopback_VertexAttrib1dNV); + SET_VertexAttrib2sNV(dest, loopback_VertexAttrib2sNV); + SET_VertexAttrib2dNV(dest, loopback_VertexAttrib2dNV); + SET_VertexAttrib3sNV(dest, loopback_VertexAttrib3sNV); + SET_VertexAttrib3dNV(dest, loopback_VertexAttrib3dNV); + SET_VertexAttrib4sNV(dest, loopback_VertexAttrib4sNV); + SET_VertexAttrib4dNV(dest, loopback_VertexAttrib4dNV); + SET_VertexAttrib4ubNV(dest, loopback_VertexAttrib4ubNV); + SET_VertexAttrib1svNV(dest, loopback_VertexAttrib1svNV); + SET_VertexAttrib1dvNV(dest, loopback_VertexAttrib1dvNV); + SET_VertexAttrib2svNV(dest, loopback_VertexAttrib2svNV); + SET_VertexAttrib2dvNV(dest, loopback_VertexAttrib2dvNV); + SET_VertexAttrib3svNV(dest, loopback_VertexAttrib3svNV); + SET_VertexAttrib3dvNV(dest, loopback_VertexAttrib3dvNV); + SET_VertexAttrib4svNV(dest, loopback_VertexAttrib4svNV); + SET_VertexAttrib4dvNV(dest, loopback_VertexAttrib4dvNV); + SET_VertexAttrib4ubvNV(dest, loopback_VertexAttrib4ubvNV); + SET_VertexAttribs1svNV(dest, loopback_VertexAttribs1svNV); + SET_VertexAttribs1fvNV(dest, loopback_VertexAttribs1fvNV); + SET_VertexAttribs1dvNV(dest, loopback_VertexAttribs1dvNV); + SET_VertexAttribs2svNV(dest, loopback_VertexAttribs2svNV); + SET_VertexAttribs2fvNV(dest, loopback_VertexAttribs2fvNV); + SET_VertexAttribs2dvNV(dest, loopback_VertexAttribs2dvNV); + SET_VertexAttribs3svNV(dest, loopback_VertexAttribs3svNV); + SET_VertexAttribs3fvNV(dest, loopback_VertexAttribs3fvNV); + SET_VertexAttribs3dvNV(dest, loopback_VertexAttribs3dvNV); + SET_VertexAttribs4svNV(dest, loopback_VertexAttribs4svNV); + SET_VertexAttribs4fvNV(dest, loopback_VertexAttribs4fvNV); + SET_VertexAttribs4dvNV(dest, loopback_VertexAttribs4dvNV); + SET_VertexAttribs4ubvNV(dest, loopback_VertexAttribs4ubvNV); + + SET_VertexAttrib1sARB(dest, loopback_VertexAttrib1sARB); + SET_VertexAttrib1dARB(dest, loopback_VertexAttrib1dARB); + SET_VertexAttrib2sARB(dest, loopback_VertexAttrib2sARB); + SET_VertexAttrib2dARB(dest, loopback_VertexAttrib2dARB); + SET_VertexAttrib3sARB(dest, loopback_VertexAttrib3sARB); + SET_VertexAttrib3dARB(dest, loopback_VertexAttrib3dARB); + SET_VertexAttrib4sARB(dest, loopback_VertexAttrib4sARB); + SET_VertexAttrib4dARB(dest, loopback_VertexAttrib4dARB); + SET_VertexAttrib1svARB(dest, loopback_VertexAttrib1svARB); + SET_VertexAttrib1dvARB(dest, loopback_VertexAttrib1dvARB); + SET_VertexAttrib2svARB(dest, loopback_VertexAttrib2svARB); + SET_VertexAttrib2dvARB(dest, loopback_VertexAttrib2dvARB); + SET_VertexAttrib3svARB(dest, loopback_VertexAttrib3svARB); + SET_VertexAttrib3dvARB(dest, loopback_VertexAttrib3dvARB); + SET_VertexAttrib4svARB(dest, loopback_VertexAttrib4svARB); + SET_VertexAttrib4dvARB(dest, loopback_VertexAttrib4dvARB); + SET_VertexAttrib4NubARB(dest, loopback_VertexAttrib4NubARB); + SET_VertexAttrib4NubvARB(dest, loopback_VertexAttrib4NubvARB); + SET_VertexAttrib4bvARB(dest, loopback_VertexAttrib4bvARB); + SET_VertexAttrib4ivARB(dest, loopback_VertexAttrib4ivARB); + SET_VertexAttrib4ubvARB(dest, loopback_VertexAttrib4ubvARB); + SET_VertexAttrib4usvARB(dest, loopback_VertexAttrib4usvARB); + SET_VertexAttrib4uivARB(dest, loopback_VertexAttrib4uivARB); + SET_VertexAttrib4NbvARB(dest, loopback_VertexAttrib4NbvARB); + SET_VertexAttrib4NsvARB(dest, loopback_VertexAttrib4NsvARB); + SET_VertexAttrib4NivARB(dest, loopback_VertexAttrib4NivARB); + SET_VertexAttrib4NusvARB(dest, loopback_VertexAttrib4NusvARB); + SET_VertexAttrib4NuivARB(dest, loopback_VertexAttrib4NuivARB); +} diff --git a/src/mesa/main/api_loopback.h b/src/mesa/main/api_loopback.h new file mode 100644 index 00000000000..6f85bbc1d92 --- /dev/null +++ b/src/mesa/main/api_loopback.h @@ -0,0 +1,37 @@ +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef API_LOOPBACK_H +#define API_LOOPBACK_H + +#include "glheader.h" + + +struct _glapi_table; + +extern void _mesa_loopback_init_api_table( struct _glapi_table *dest ); + +#endif diff --git a/src/mesa/main/api_noop.c b/src/mesa/main/api_noop.c new file mode 100644 index 00000000000..f42f166ae31 --- /dev/null +++ b/src/mesa/main/api_noop.c @@ -0,0 +1,964 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "api_noop.h" +#include "api_validate.h" +#include "api_arrayelt.h" +#include "context.h" +#include "colormac.h" +#include "light.h" +#include "macros.h" +#include "mtypes.h" +#include "dlist.h" +#include "dispatch.h" + + +/* In states where certain vertex components are required for t&l or + * rasterization, we still need to keep track of the current values. + * These functions provide this service by keeping uptodate the + * 'ctx->Current' struct for all data elements not included in the + * currently enabled hardware vertex. + * I.e. these functions would typically be used when outside of glBegin/End. + */ + + +void GLAPIENTRY _mesa_noop_EdgeFlag( GLboolean b ) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Current.EdgeFlag = b; +} + +void GLAPIENTRY _mesa_noop_EdgeFlagv( const GLboolean *b ) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Current.EdgeFlag = *b; +} + +void GLAPIENTRY _mesa_noop_Indexf( GLfloat f ) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Current.Index = f; +} + +void GLAPIENTRY _mesa_noop_Indexfv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + ctx->Current.Index = *v; +} + +void GLAPIENTRY _mesa_noop_FogCoordfEXT( GLfloat a ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_FOG]; + dest[0] = a; + dest[1] = 0.0; + dest[2] = 0.0; + dest[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_FogCoordfvEXT( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_FOG]; + dest[0] = v[0]; + dest[1] = 0.0; + dest[2] = 0.0; + dest[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_Normal3f( GLfloat a, GLfloat b, GLfloat c ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; + dest[0] = a; + dest[1] = b; + dest[2] = c; + dest[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_Normal3fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_Color4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; + color[0] = a; + color[1] = b; + color[2] = c; + color[3] = d; +} + +void GLAPIENTRY _mesa_noop_Color4fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; + color[0] = v[0]; + color[1] = v[1]; + color[2] = v[2]; + color[3] = v[3]; +} + +void GLAPIENTRY _mesa_noop_Color3f( GLfloat a, GLfloat b, GLfloat c ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; + color[0] = a; + color[1] = b; + color[2] = c; + color[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_Color3fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; + color[0] = v[0]; + color[1] = v[1]; + color[2] = v[2]; + color[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord1fARB( GLenum target, GLfloat a ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = a; + dest[1] = 0; + dest[2] = 0; + dest[3] = 1; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord1fvARB( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = v[0]; + dest[1] = 0; + dest[2] = 0; + dest[3] = 1; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord2fARB( GLenum target, GLfloat a, GLfloat b ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = a; + dest[1] = b; + dest[2] = 0; + dest[3] = 1; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord2fvARB( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = 0; + dest[3] = 1; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord3fARB( GLenum target, GLfloat a, GLfloat b, GLfloat c) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = a; + dest[1] = b; + dest[2] = c; + dest[3] = 1; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord3fvARB( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = 1; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord4fARB( GLenum target, GLfloat a, GLfloat b, + GLfloat c, GLfloat d ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = a; + dest[1] = b; + dest[2] = c; + dest[3] = d; + } +} + +void GLAPIENTRY _mesa_noop_MultiTexCoord4fvARB( GLenum target, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = target - GL_TEXTURE0_ARB; + + /* unit is unsigned -- cannot be less than zero. + */ + if (unit < MAX_TEXTURE_COORD_UNITS) + { + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + unit]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = v[3]; + } +} + +void GLAPIENTRY _mesa_noop_SecondaryColor3fEXT( GLfloat a, GLfloat b, GLfloat c ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR1]; + color[0] = a; + color[1] = b; + color[2] = c; + color[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_SecondaryColor3fvEXT( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Attrib[VERT_ATTRIB_COLOR1]; + color[0] = v[0]; + color[1] = v[1]; + color[2] = v[2]; + color[3] = 1.0; +} + +void GLAPIENTRY _mesa_noop_TexCoord1f( GLfloat a ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = a; + dest[1] = 0; + dest[2] = 0; + dest[3] = 1; +} + +void GLAPIENTRY _mesa_noop_TexCoord1fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = v[0]; + dest[1] = 0; + dest[2] = 0; + dest[3] = 1; +} + +void GLAPIENTRY _mesa_noop_TexCoord2f( GLfloat a, GLfloat b ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = a; + dest[1] = b; + dest[2] = 0; + dest[3] = 1; +} + +void GLAPIENTRY _mesa_noop_TexCoord2fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = 0; + dest[3] = 1; +} + +void GLAPIENTRY _mesa_noop_TexCoord3f( GLfloat a, GLfloat b, GLfloat c ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = a; + dest[1] = b; + dest[2] = c; + dest[3] = 1; +} + +void GLAPIENTRY _mesa_noop_TexCoord3fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = 1; +} + +void GLAPIENTRY _mesa_noop_TexCoord4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = a; + dest[1] = b; + dest[2] = c; + dest[3] = d; +} + +void GLAPIENTRY _mesa_noop_TexCoord4fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = v[3]; +} + + + +void GLAPIENTRY _mesa_noop_VertexAttrib1fNV( GLuint index, GLfloat x ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, 0, 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib1fNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], 0, 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib1fvNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, y, 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib2fNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib2fvNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib3fNV( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib3fNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib3fvNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib4fNV( GLuint index, GLfloat x, + GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, w); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib4fNV" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], v[3]); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib4fvNV" ); +} + + +/* + * XXX Un-alias attribs here + */ + +void GLAPIENTRY _mesa_noop_VertexAttrib1fARB( GLuint index, GLfloat x ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, 0, 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib1fARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib1fvARB( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], 0, 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib1fvARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib2fARB( GLuint index, GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, y, 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib2fARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib2fvARB( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], 0, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib2fvARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib3fARB( GLuint index, GLfloat x, + GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib3fARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib3fvARB( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], 1); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib3fvARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib4fARB( GLuint index, GLfloat x, + GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], x, y, z, w); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib4fARB" ); +} + +void GLAPIENTRY _mesa_noop_VertexAttrib4fvARB( GLuint index, const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + if (index < VERT_ATTRIB_MAX) { + ASSIGN_4V(ctx->Current.Attrib[index], v[0], v[1], v[2], v[3]); + } + else + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttrib4fvARB" ); +} + + + +/* Material + */ +void GLAPIENTRY _mesa_noop_Materialfv( GLenum face, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i, nr; + struct gl_material *mat = &ctx->Light.Material; + GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0, + "_mesa_noop_Materialfv" ); + + if (ctx->Light.ColorMaterialEnabled) + bitmask &= ~ctx->Light.ColorMaterialBitmask; + + if (bitmask == 0) + return; + + switch (face) { + case GL_SHININESS: nr = 1; break; + case GL_COLOR_INDEXES: nr = 3; break; + default: nr = 4 ; break; + } + + for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) + if (bitmask & (1<<i)) + COPY_SZ_4V( mat->Attrib[i], nr, params ); + + _mesa_update_material( ctx, bitmask ); +} + +/* These really are noops outside begin/end: + */ +void GLAPIENTRY _mesa_noop_Vertex2fv( const GLfloat *v ) +{ + (void) v; +} + +void GLAPIENTRY _mesa_noop_Vertex3fv( const GLfloat *v ) +{ + (void) v; +} + +void GLAPIENTRY _mesa_noop_Vertex4fv( const GLfloat *v ) +{ + (void) v; +} + +void GLAPIENTRY _mesa_noop_Vertex2f( GLfloat a, GLfloat b ) +{ + (void) a; (void) b; +} + +void GLAPIENTRY _mesa_noop_Vertex3f( GLfloat a, GLfloat b, GLfloat c ) +{ + (void) a; (void) b; (void) c; +} + +void GLAPIENTRY _mesa_noop_Vertex4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d ) +{ + (void) a; (void) b; (void) c; (void) d; +} + +/* Similarly, these have no effect outside begin/end: + */ +void GLAPIENTRY _mesa_noop_EvalCoord1f( GLfloat a ) +{ + (void) a; +} + +void GLAPIENTRY _mesa_noop_EvalCoord1fv( const GLfloat *v ) +{ + (void) v; +} + +void GLAPIENTRY _mesa_noop_EvalCoord2f( GLfloat a, GLfloat b ) +{ + (void) a; (void) b; +} + +void GLAPIENTRY _mesa_noop_EvalCoord2fv( const GLfloat *v ) +{ + (void) v; +} + +void GLAPIENTRY _mesa_noop_EvalPoint1( GLint a ) +{ + (void) a; +} + +void GLAPIENTRY _mesa_noop_EvalPoint2( GLint a, GLint b ) +{ + (void) a; (void) b; +} + + +/* Begin -- call into driver, should result in the vtxfmt being + * swapped out: + */ +void GLAPIENTRY _mesa_noop_Begin( GLenum mode ) +{ + (void) mode; +} + + +/* End -- just raise an error + */ +void GLAPIENTRY _mesa_noop_End( void ) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); +} + + +/* Execute a glRectf() function. This is not suitable for GL_COMPILE + * modes (as the test for outside begin/end is not compiled), + * but may be useful for drivers in circumstances which exclude + * display list interactions. + * + * (None of the functions in this file are suitable for GL_COMPILE + * modes). + */ +void GLAPIENTRY _mesa_noop_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + { + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + } + + CALL_Begin(GET_DISPATCH(), (GL_QUADS)); + CALL_Vertex2f(GET_DISPATCH(), (x1, y1)); + CALL_Vertex2f(GET_DISPATCH(), (x2, y1)); + CALL_Vertex2f(GET_DISPATCH(), (x2, y2)); + CALL_Vertex2f(GET_DISPATCH(), (x1, y2)); + CALL_End(GET_DISPATCH(), ()); +} + + +/* Some very basic support for arrays. Drivers without explicit array + * support can hook these in, but still need to supply an array-elt + * implementation. + */ +void GLAPIENTRY _mesa_noop_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) + return; + + CALL_Begin(GET_DISPATCH(), (mode)); + for (i = 0; i < count; i++) + CALL_ArrayElement(GET_DISPATCH(), (start + i)); + CALL_End(GET_DISPATCH(), ()); +} + + +void GLAPIENTRY _mesa_noop_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + CALL_Begin(GET_DISPATCH(), (mode)); + + switch (type) { + case GL_UNSIGNED_BYTE: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] )); + break; + case GL_UNSIGNED_SHORT: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] )); + break; + case GL_UNSIGNED_INT: + for (i = 0 ; i < count ; i++) + CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] )); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + break; + } + + CALL_End(GET_DISPATCH(), ()); +} + +void GLAPIENTRY _mesa_noop_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + + if (_mesa_validate_DrawRangeElements( ctx, mode, + start, end, + count, type, indices )) + CALL_DrawElements(GET_DISPATCH(), (mode, count, type, indices)); +} + +/* + * Eval Mesh + */ + +/* KW: If are compiling, we don't know whether eval will produce a + * vertex when it is run in the future. If this is pure immediate + * mode, eval is a noop if neither vertex map is enabled. + * + * Thus we need to have a check in the display list code or + * elsewhere for eval(1,2) vertices in the case where + * map(1,2)_vertex is disabled, and to purge those vertices from + * the vb. + */ +void GLAPIENTRY _mesa_noop_EvalMesh1( GLenum mode, GLint i1, GLint i2 ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + GLfloat u, du; + GLenum prim; + + switch (mode) { + case GL_POINT: + prim = GL_POINTS; + break; + case GL_LINE: + prim = GL_LINE_STRIP; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" ); + return; + } + + /* No effect if vertex maps disabled. + */ + if (!ctx->Eval.Map1Vertex4 && + !ctx->Eval.Map1Vertex3 && + !(ctx->VertexProgram._Enabled && ctx->Eval.Map1Attrib[VERT_ATTRIB_POS])) + return; + + du = ctx->Eval.MapGrid1du; + u = ctx->Eval.MapGrid1u1 + i1 * du; + + CALL_Begin(GET_DISPATCH(), (prim)); + for (i=i1;i<=i2;i++,u+=du) { + CALL_EvalCoord1f(GET_DISPATCH(), (u)); + } + CALL_End(GET_DISPATCH(), ()); +} + + + +void GLAPIENTRY _mesa_noop_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat u, du, v, dv, v1, u1; + GLint i, j; + + switch (mode) { + case GL_POINT: + case GL_LINE: + case GL_FILL: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" ); + return; + } + + /* No effect if vertex maps disabled. + */ + if (!ctx->Eval.Map2Vertex4 && + !ctx->Eval.Map2Vertex3 && + !(ctx->VertexProgram._Enabled && ctx->Eval.Map2Attrib[VERT_ATTRIB_POS])) + return; + + du = ctx->Eval.MapGrid2du; + dv = ctx->Eval.MapGrid2dv; + v1 = ctx->Eval.MapGrid2v1 + j1 * dv; + u1 = ctx->Eval.MapGrid2u1 + i1 * du; + + switch (mode) { + case GL_POINT: + CALL_Begin(GET_DISPATCH(), (GL_POINTS)); + for (v=v1,j=j1;j<=j2;j++,v+=dv) { + for (u=u1,i=i1;i<=i2;i++,u+=du) { + CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); + } + } + CALL_End(GET_DISPATCH(), ()); + break; + case GL_LINE: + for (v=v1,j=j1;j<=j2;j++,v+=dv) { + CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP)); + for (u=u1,i=i1;i<=i2;i++,u+=du) { + CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); + } + CALL_End(GET_DISPATCH(), ()); + } + for (u=u1,i=i1;i<=i2;i++,u+=du) { + CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP)); + for (v=v1,j=j1;j<=j2;j++,v+=dv) { + CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); + } + CALL_End(GET_DISPATCH(), ()); + } + break; + case GL_FILL: + for (v=v1,j=j1;j<j2;j++,v+=dv) { + CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP)); + for (u=u1,i=i1;i<=i2;i++,u+=du) { + CALL_EvalCoord2f(GET_DISPATCH(), (u, v)); + CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv)); + } + CALL_End(GET_DISPATCH(), ()); + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" ); + return; + } +} + + + +/* Build a vertexformat full of things to use outside begin/end pairs. + * + * TODO -- build a whole dispatch table for this purpose, and likewise + * for inside begin/end. + */ +void _mesa_noop_vtxfmt_init( GLvertexformat *vfmt ) +{ + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = _mesa_noop_Begin; + vfmt->CallList = _mesa_CallList; + vfmt->CallLists = _mesa_CallLists; + vfmt->Color3f = _mesa_noop_Color3f; + vfmt->Color3fv = _mesa_noop_Color3fv; + vfmt->Color4f = _mesa_noop_Color4f; + vfmt->Color4fv = _mesa_noop_Color4fv; + vfmt->EdgeFlag = _mesa_noop_EdgeFlag; + vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; + vfmt->End = _mesa_noop_End; + vfmt->EvalCoord1f = _mesa_noop_EvalCoord1f; + vfmt->EvalCoord1fv = _mesa_noop_EvalCoord1fv; + vfmt->EvalCoord2f = _mesa_noop_EvalCoord2f; + vfmt->EvalCoord2fv = _mesa_noop_EvalCoord2fv; + vfmt->EvalPoint1 = _mesa_noop_EvalPoint1; + vfmt->EvalPoint2 = _mesa_noop_EvalPoint2; + vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT; + vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT; + vfmt->Indexf = _mesa_noop_Indexf; + vfmt->Indexfv = _mesa_noop_Indexfv; + vfmt->Materialfv = _mesa_noop_Materialfv; + vfmt->MultiTexCoord1fARB = _mesa_noop_MultiTexCoord1fARB; + vfmt->MultiTexCoord1fvARB = _mesa_noop_MultiTexCoord1fvARB; + vfmt->MultiTexCoord2fARB = _mesa_noop_MultiTexCoord2fARB; + vfmt->MultiTexCoord2fvARB = _mesa_noop_MultiTexCoord2fvARB; + vfmt->MultiTexCoord3fARB = _mesa_noop_MultiTexCoord3fARB; + vfmt->MultiTexCoord3fvARB = _mesa_noop_MultiTexCoord3fvARB; + vfmt->MultiTexCoord4fARB = _mesa_noop_MultiTexCoord4fARB; + vfmt->MultiTexCoord4fvARB = _mesa_noop_MultiTexCoord4fvARB; + vfmt->Normal3f = _mesa_noop_Normal3f; + vfmt->Normal3fv = _mesa_noop_Normal3fv; + vfmt->SecondaryColor3fEXT = _mesa_noop_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = _mesa_noop_SecondaryColor3fvEXT; + vfmt->TexCoord1f = _mesa_noop_TexCoord1f; + vfmt->TexCoord1fv = _mesa_noop_TexCoord1fv; + vfmt->TexCoord2f = _mesa_noop_TexCoord2f; + vfmt->TexCoord2fv = _mesa_noop_TexCoord2fv; + vfmt->TexCoord3f = _mesa_noop_TexCoord3f; + vfmt->TexCoord3fv = _mesa_noop_TexCoord3fv; + vfmt->TexCoord4f = _mesa_noop_TexCoord4f; + vfmt->TexCoord4fv = _mesa_noop_TexCoord4fv; + vfmt->Vertex2f = _mesa_noop_Vertex2f; + vfmt->Vertex2fv = _mesa_noop_Vertex2fv; + vfmt->Vertex3f = _mesa_noop_Vertex3f; + vfmt->Vertex3fv = _mesa_noop_Vertex3fv; + vfmt->Vertex4f = _mesa_noop_Vertex4f; + vfmt->Vertex4fv = _mesa_noop_Vertex4fv; + vfmt->VertexAttrib1fNV = _mesa_noop_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = _mesa_noop_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = _mesa_noop_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = _mesa_noop_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = _mesa_noop_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = _mesa_noop_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = _mesa_noop_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = _mesa_noop_VertexAttrib4fvNV; + vfmt->VertexAttrib1fARB = _mesa_noop_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = _mesa_noop_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = _mesa_noop_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = _mesa_noop_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = _mesa_noop_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = _mesa_noop_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = _mesa_noop_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = _mesa_noop_VertexAttrib4fvARB; + + vfmt->Rectf = _mesa_noop_Rectf; + + vfmt->DrawArrays = _mesa_noop_DrawArrays; + vfmt->DrawElements = _mesa_noop_DrawElements; + vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; + vfmt->EvalMesh1 = _mesa_noop_EvalMesh1; + vfmt->EvalMesh2 = _mesa_noop_EvalMesh2; +} diff --git a/src/mesa/main/api_noop.h b/src/mesa/main/api_noop.h new file mode 100644 index 00000000000..56d930e3b04 --- /dev/null +++ b/src/mesa/main/api_noop.h @@ -0,0 +1,147 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _API_NOOP_H +#define _API_NOOP_H + + +#include "glheader.h" +#include "mtypes.h" +#include "context.h" + +/* In states where certain vertex components are required for t&l or + * rasterization, we still need to keep track of the current values. + * These functions provide this service by keeping uptodate the + * 'ctx->Current' struct for all data elements not included in the + * currently enabled hardware vertex. + * + */ +extern void GLAPIENTRY _mesa_noop_EdgeFlag( GLboolean b ); +extern void GLAPIENTRY _mesa_noop_EdgeFlagv( const GLboolean *b ); + +extern void GLAPIENTRY _mesa_noop_FogCoordfEXT( GLfloat a ); +extern void GLAPIENTRY _mesa_noop_FogCoordfvEXT( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_Indexf( GLfloat i ); +extern void GLAPIENTRY _mesa_noop_Indexfv( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_Normal3f( GLfloat a, GLfloat b, GLfloat c ); +extern void GLAPIENTRY _mesa_noop_Normal3fv( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_Materialfv( GLenum face, GLenum pname, const GLfloat *param ); + +extern void _mesa_noop_Color4ub( GLubyte a, GLubyte b, GLubyte c, GLubyte d ); +extern void _mesa_noop_Color4ubv( const GLubyte *v ); +extern void GLAPIENTRY _mesa_noop_Color4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d ); +extern void GLAPIENTRY _mesa_noop_Color4fv( const GLfloat *v ); +extern void _mesa_noop_Color3ub( GLubyte a, GLubyte b, GLubyte c ); +extern void _mesa_noop_Color3ubv( const GLubyte *v ); +extern void GLAPIENTRY _mesa_noop_Color3f( GLfloat a, GLfloat b, GLfloat c ); +extern void GLAPIENTRY _mesa_noop_Color3fv( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_MultiTexCoord1fARB( GLenum target, GLfloat a ); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord1fvARB( GLenum target, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord2fARB( GLenum target, GLfloat a, GLfloat b ); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord2fvARB( GLenum target, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord3fARB( GLenum target, GLfloat a, GLfloat b, GLfloat c); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord3fvARB( GLenum target, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord4fARB( GLenum target, GLfloat a, GLfloat b, GLfloat c, GLfloat d ); +extern void GLAPIENTRY _mesa_noop_MultiTexCoord4fvARB( GLenum target, const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_SecondaryColor3ubEXT( GLubyte a, GLubyte b, GLubyte c ); +extern void GLAPIENTRY _mesa_noop_SecondaryColor3ubvEXT( const GLubyte *v ); +extern void GLAPIENTRY _mesa_noop_SecondaryColor3fEXT( GLfloat a, GLfloat b, GLfloat c ); +extern void GLAPIENTRY _mesa_noop_SecondaryColor3fvEXT( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_TexCoord1f( GLfloat a ); +extern void GLAPIENTRY _mesa_noop_TexCoord1fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_TexCoord2f( GLfloat a, GLfloat b ); +extern void GLAPIENTRY _mesa_noop_TexCoord2fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_TexCoord3f( GLfloat a, GLfloat b, GLfloat c ); +extern void GLAPIENTRY _mesa_noop_TexCoord3fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_TexCoord4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d ); +extern void GLAPIENTRY _mesa_noop_TexCoord4fv( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_Vertex2f( GLfloat a, GLfloat b ); +extern void GLAPIENTRY _mesa_noop_Vertex2fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_Vertex3f( GLfloat a, GLfloat b, GLfloat c ); +extern void GLAPIENTRY _mesa_noop_Vertex3fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_Vertex4f( GLfloat a, GLfloat b, GLfloat c, GLfloat d ); +extern void GLAPIENTRY _mesa_noop_Vertex4fv( const GLfloat *v ); + +extern void GLAPIENTRY _mesa_noop_VertexAttrib1fNV( GLuint index, GLfloat x ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib1fvNV( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib2fvNV( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib3fvNV( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + +extern void GLAPIENTRY _mesa_noop_VertexAttrib4fvNV( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib1fARB( GLuint index, GLfloat x ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib1fvARB( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib2fARB( GLuint index, GLfloat x, GLfloat y ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib2fvARB( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib3fARB( GLuint index, GLfloat x, GLfloat y, GLfloat z ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib3fvARB( GLuint index, const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib4fARB( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ); +extern void GLAPIENTRY _mesa_noop_VertexAttrib4fvARB( GLuint index, const GLfloat *v ); + + +extern void GLAPIENTRY _mesa_noop_End( void ); +extern void GLAPIENTRY _mesa_noop_Begin( GLenum mode ); +extern void GLAPIENTRY _mesa_noop_EvalPoint2( GLint a, GLint b ); +extern void GLAPIENTRY _mesa_noop_EvalPoint1( GLint a ); +extern void GLAPIENTRY _mesa_noop_EvalCoord2fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_EvalCoord2f( GLfloat a, GLfloat b ); +extern void GLAPIENTRY _mesa_noop_EvalCoord1fv( const GLfloat *v ); +extern void GLAPIENTRY _mesa_noop_EvalCoord1f( GLfloat a ); + +extern void _mesa_noop_vtxfmt_init( GLvertexformat *vfmt ); + +extern void GLAPIENTRY _mesa_noop_EvalMesh2( GLenum mode, GLint i1, GLint i2, + GLint j1, GLint j2 ); + +extern void GLAPIENTRY _mesa_noop_EvalMesh1( GLenum mode, GLint i1, GLint i2 ); + + +/* Not strictly a noop -- translate Rectf down to Begin/End and + * vertices. Closer to the loopback operations, but doesn't meet the + * criteria for inclusion there (cannot be used in the Save table). + */ +extern void GLAPIENTRY _mesa_noop_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ); + + +extern void GLAPIENTRY _mesa_noop_DrawArrays(GLenum mode, GLint start, GLsizei count); +extern void GLAPIENTRY _mesa_noop_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices); +extern void GLAPIENTRY _mesa_noop_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices); + + + +#endif diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c new file mode 100644 index 00000000000..d1c8f42e747 --- /dev/null +++ b/src/mesa/main/api_validate.c @@ -0,0 +1,238 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "api_validate.h" +#include "context.h" +#include "imports.h" +#include "mtypes.h" +#include "state.h" + + +GLboolean +_mesa_validate_DrawElements(GLcontext *ctx, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (count <= 0) { + if (count < 0) + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); + return GL_FALSE; + } + + if (mode > GL_POLYGON) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)" ); + return GL_FALSE; + } + + if (type != GL_UNSIGNED_INT && + type != GL_UNSIGNED_BYTE && + type != GL_UNSIGNED_SHORT) + { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + return GL_FALSE; + } + + if (ctx->NewState) + _mesa_update_state(ctx); + + /* Always need vertex positions */ + if (!ctx->Array.Vertex.Enabled + && !(ctx->VertexProgram._Enabled && ctx->Array.VertexAttrib[0].Enabled)) + return GL_FALSE; + + /* Vertex buffer object tests */ + if (ctx->Array.ElementArrayBufferObj->Name) { + GLuint indexBytes; + + /* use indices in the buffer object */ + if (!ctx->Array.ElementArrayBufferObj->Data) { + _mesa_warning(ctx, "DrawElements with empty vertex elements buffer!"); + return GL_FALSE; + } + + /* make sure count doesn't go outside buffer bounds */ + if (type == GL_UNSIGNED_INT) { + indexBytes = count * sizeof(GLuint); + } + else if (type == GL_UNSIGNED_BYTE) { + indexBytes = count * sizeof(GLubyte); + } + else { + ASSERT(type == GL_UNSIGNED_SHORT); + indexBytes = count * sizeof(GLushort); + } + + if ((GLubyte *) indices + indexBytes > + ctx->Array.ElementArrayBufferObj->Data + + ctx->Array.ElementArrayBufferObj->Size) { + _mesa_warning(ctx, "glDrawElements index out of buffer bounds"); + return GL_FALSE; + } + + /* Actual address is the sum of pointers. Indices may be used below. */ + if (ctx->Const.CheckArrayBounds) { + indices = (const GLvoid *) + ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, + (const GLubyte *) indices); + } + } + + if (ctx->Const.CheckArrayBounds) { + /* find max array index */ + GLuint max = 0; + GLint i; + if (type == GL_UNSIGNED_INT) { + for (i = 0; i < count; i++) + if (((GLuint *) indices)[i] > max) + max = ((GLuint *) indices)[i]; + } + else if (type == GL_UNSIGNED_SHORT) { + for (i = 0; i < count; i++) + if (((GLushort *) indices)[i] > max) + max = ((GLushort *) indices)[i]; + } + else { + ASSERT(type == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) + if (((GLubyte *) indices)[i] > max) + max = ((GLubyte *) indices)[i]; + } + if (max >= ctx->Array._MaxElement) { + /* the max element is out of bounds of one or more enabled arrays */ + return GL_FALSE; + } + } + + return GL_TRUE; +} + + +GLboolean +_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (count <= 0) { + if (count < 0) + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" ); + return GL_FALSE; + } + + if (mode > GL_POLYGON) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" ); + return GL_FALSE; + } + + if (end < start) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)"); + return GL_FALSE; + } + + if (type != GL_UNSIGNED_INT && + type != GL_UNSIGNED_BYTE && + type != GL_UNSIGNED_SHORT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)" ); + return GL_FALSE; + } + + if (ctx->NewState) + _mesa_update_state(ctx); + + /* Always need vertex positions */ + if (!ctx->Array.Vertex.Enabled + && !(ctx->VertexProgram._Enabled && ctx->Array.VertexAttrib[0].Enabled)) + return GL_FALSE; + + if (ctx->Const.CheckArrayBounds) { + /* Find max array index. + * We don't trust the user's start and end values. + */ + GLuint max = 0; + GLint i; + if (type == GL_UNSIGNED_INT) { + for (i = 0; i < count; i++) + if (((GLuint *) indices)[i] > max) + max = ((GLuint *) indices)[i]; + } + else if (type == GL_UNSIGNED_SHORT) { + for (i = 0; i < count; i++) + if (((GLushort *) indices)[i] > max) + max = ((GLushort *) indices)[i]; + } + else { + ASSERT(type == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) + if (((GLubyte *) indices)[i] > max) + max = ((GLubyte *) indices)[i]; + } + if (max >= ctx->Array._MaxElement) { + /* the max element is out of bounds of one or more enabled arrays */ + return GL_FALSE; + } + } + + return GL_TRUE; +} + + +/** + * Called from the tnl module to error check the function parameters and + * verify that we really can draw something. + */ +GLboolean +_mesa_validate_DrawArrays(GLcontext *ctx, + GLenum mode, GLint start, GLsizei count) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (count < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" ); + return GL_FALSE; + } + + if (mode > GL_POLYGON) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); + return GL_FALSE; + } + + if (ctx->NewState) + _mesa_update_state(ctx); + + /* Always need vertex positions */ + if (!ctx->Array.Vertex.Enabled && !ctx->Array.VertexAttrib[0].Enabled) + return GL_FALSE; + + if (ctx->Const.CheckArrayBounds) { + if (start + count > (GLint) ctx->Array._MaxElement) + return GL_FALSE; + } + + return GL_TRUE; +} diff --git a/src/mesa/main/api_validate.h b/src/mesa/main/api_validate.h new file mode 100644 index 00000000000..10f0c34e663 --- /dev/null +++ b/src/mesa/main/api_validate.h @@ -0,0 +1,49 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef API_VALIDATE_H +#define API_VALIDATE_H + + +#include "mtypes.h" + +extern GLboolean +_mesa_validate_DrawArrays(GLcontext *ctx, + GLenum mode, GLint start, GLsizei count); + +extern GLboolean +_mesa_validate_DrawElements(GLcontext *ctx, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices); + +extern GLboolean +_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices); + + +#endif diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c new file mode 100644 index 00000000000..28456942cba --- /dev/null +++ b/src/mesa/main/attrib.c @@ -0,0 +1,1328 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "imports.h" +#include "accum.h" +#include "attrib.h" +#include "blend.h" +#include "buffers.h" +#include "bufferobj.h" +#include "colormac.h" +#include "colortab.h" +#include "context.h" +#include "depth.h" +#include "enable.h" +#include "enums.h" +#include "fog.h" +#include "hint.h" +#include "light.h" +#include "lines.h" +#include "matrix.h" +#include "points.h" +#include "polygon.h" +#include "simple_list.h" +#include "stencil.h" +#include "texobj.h" +#include "texstate.h" +#include "mtypes.h" +#include "math/m_xform.h" + + +/* + * Allocate a new attribute state node. These nodes have a + * "kind" value and a pointer to a struct of state data. + */ +static struct gl_attrib_node * +new_attrib_node( GLbitfield kind ) +{ + struct gl_attrib_node *an = MALLOC_STRUCT(gl_attrib_node); + if (an) { + an->kind = kind; + } + return an; +} + + +void GLAPIENTRY +_mesa_PushAttrib(GLbitfield mask) +{ + struct gl_attrib_node *newnode; + struct gl_attrib_node *head; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glPushAttrib %x\n", (int) mask); + + if (ctx->AttribStackDepth >= MAX_ATTRIB_STACK_DEPTH) { + _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushAttrib" ); + return; + } + + /* Build linked list of attribute nodes which save all attribute */ + /* groups specified by the mask. */ + head = NULL; + + if (mask & GL_ACCUM_BUFFER_BIT) { + struct gl_accum_attrib *attr; + attr = MALLOC_STRUCT( gl_accum_attrib ); + MEMCPY( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) ); + newnode = new_attrib_node( GL_ACCUM_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_COLOR_BUFFER_BIT) { + struct gl_colorbuffer_attrib *attr; + attr = MALLOC_STRUCT( gl_colorbuffer_attrib ); + MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) ); + newnode = new_attrib_node( GL_COLOR_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_CURRENT_BIT) { + struct gl_current_attrib *attr; + FLUSH_CURRENT( ctx, 0 ); + attr = MALLOC_STRUCT( gl_current_attrib ); + MEMCPY( attr, &ctx->Current, sizeof(struct gl_current_attrib) ); + newnode = new_attrib_node( GL_CURRENT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_DEPTH_BUFFER_BIT) { + struct gl_depthbuffer_attrib *attr; + attr = MALLOC_STRUCT( gl_depthbuffer_attrib ); + MEMCPY( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) ); + newnode = new_attrib_node( GL_DEPTH_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_ENABLE_BIT) { + struct gl_enable_attrib *attr; + GLuint i; + attr = MALLOC_STRUCT( gl_enable_attrib ); + /* Copy enable flags from all other attributes into the enable struct. */ + attr->AlphaTest = ctx->Color.AlphaEnabled; + attr->AutoNormal = ctx->Eval.AutoNormal; + attr->Blend = ctx->Color.BlendEnabled; + attr->ClipPlanes = ctx->Transform.ClipPlanesEnabled; + attr->ColorMaterial = ctx->Light.ColorMaterialEnabled; + attr->ColorTable = ctx->Pixel.ColorTableEnabled; + attr->PostColorMatrixColorTable = ctx->Pixel.PostColorMatrixColorTableEnabled; + attr->PostConvolutionColorTable = ctx->Pixel.PostConvolutionColorTableEnabled; + attr->Convolution1D = ctx->Pixel.Convolution1DEnabled; + attr->Convolution2D = ctx->Pixel.Convolution2DEnabled; + attr->Separable2D = ctx->Pixel.Separable2DEnabled; + attr->CullFace = ctx->Polygon.CullFlag; + attr->DepthTest = ctx->Depth.Test; + attr->Dither = ctx->Color.DitherFlag; + attr->Fog = ctx->Fog.Enabled; + for (i=0;i<MAX_LIGHTS;i++) { + attr->Light[i] = ctx->Light.Light[i].Enabled; + } + attr->Lighting = ctx->Light.Enabled; + attr->LineSmooth = ctx->Line.SmoothFlag; + attr->LineStipple = ctx->Line.StippleFlag; + attr->Histogram = ctx->Pixel.HistogramEnabled; + attr->MinMax = ctx->Pixel.MinMaxEnabled; + attr->IndexLogicOp = ctx->Color.IndexLogicOpEnabled; + attr->ColorLogicOp = ctx->Color.ColorLogicOpEnabled; + attr->Map1Color4 = ctx->Eval.Map1Color4; + attr->Map1Index = ctx->Eval.Map1Index; + attr->Map1Normal = ctx->Eval.Map1Normal; + attr->Map1TextureCoord1 = ctx->Eval.Map1TextureCoord1; + attr->Map1TextureCoord2 = ctx->Eval.Map1TextureCoord2; + attr->Map1TextureCoord3 = ctx->Eval.Map1TextureCoord3; + attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4; + attr->Map1Vertex3 = ctx->Eval.Map1Vertex3; + attr->Map1Vertex4 = ctx->Eval.Map1Vertex4; + MEMCPY(attr->Map1Attrib, ctx->Eval.Map1Attrib, sizeof(ctx->Eval.Map1Attrib)); + attr->Map2Color4 = ctx->Eval.Map2Color4; + attr->Map2Index = ctx->Eval.Map2Index; + attr->Map2Normal = ctx->Eval.Map2Normal; + attr->Map2TextureCoord1 = ctx->Eval.Map2TextureCoord1; + attr->Map2TextureCoord2 = ctx->Eval.Map2TextureCoord2; + attr->Map2TextureCoord3 = ctx->Eval.Map2TextureCoord3; + attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4; + attr->Map2Vertex3 = ctx->Eval.Map2Vertex3; + attr->Map2Vertex4 = ctx->Eval.Map2Vertex4; + MEMCPY(attr->Map2Attrib, ctx->Eval.Map2Attrib, sizeof(ctx->Eval.Map2Attrib)); + attr->Normalize = ctx->Transform.Normalize; + attr->RasterPositionUnclipped = ctx->Transform.RasterPositionUnclipped; + attr->PixelTexture = ctx->Pixel.PixelTextureEnabled; + attr->PointSmooth = ctx->Point.SmoothFlag; + attr->PointSprite = ctx->Point.PointSprite; + attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint; + attr->PolygonOffsetLine = ctx->Polygon.OffsetLine; + attr->PolygonOffsetFill = ctx->Polygon.OffsetFill; + attr->PolygonSmooth = ctx->Polygon.SmoothFlag; + attr->PolygonStipple = ctx->Polygon.StippleFlag; + attr->RescaleNormals = ctx->Transform.RescaleNormals; + attr->Scissor = ctx->Scissor.Enabled; + attr->Stencil = ctx->Stencil.Enabled; + attr->StencilTwoSide = ctx->Stencil.TestTwoSide; + attr->MultisampleEnabled = ctx->Multisample.Enabled; + attr->SampleAlphaToCoverage = ctx->Multisample.SampleAlphaToCoverage; + attr->SampleAlphaToOne = ctx->Multisample.SampleAlphaToOne; + attr->SampleCoverage = ctx->Multisample.SampleCoverage; + attr->SampleCoverageInvert = ctx->Multisample.SampleCoverageInvert; + for (i=0; i<MAX_TEXTURE_UNITS; i++) { + attr->Texture[i] = ctx->Texture.Unit[i].Enabled; + attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled; + attr->TextureColorTable[i] = ctx->Texture.Unit[i].ColorTableEnabled; + } + /* GL_NV_vertex_program */ + attr->VertexProgram = ctx->VertexProgram.Enabled; + attr->VertexProgramPointSize = ctx->VertexProgram.PointSizeEnabled; + attr->VertexProgramTwoSide = ctx->VertexProgram.TwoSideEnabled; + newnode = new_attrib_node( GL_ENABLE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_EVAL_BIT) { + struct gl_eval_attrib *attr; + attr = MALLOC_STRUCT( gl_eval_attrib ); + MEMCPY( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) ); + newnode = new_attrib_node( GL_EVAL_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_FOG_BIT) { + struct gl_fog_attrib *attr; + attr = MALLOC_STRUCT( gl_fog_attrib ); + MEMCPY( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) ); + newnode = new_attrib_node( GL_FOG_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_HINT_BIT) { + struct gl_hint_attrib *attr; + attr = MALLOC_STRUCT( gl_hint_attrib ); + MEMCPY( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) ); + newnode = new_attrib_node( GL_HINT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_LIGHTING_BIT) { + struct gl_light_attrib *attr; + FLUSH_CURRENT(ctx, 0); /* flush material changes */ + attr = MALLOC_STRUCT( gl_light_attrib ); + MEMCPY( attr, &ctx->Light, sizeof(struct gl_light_attrib) ); + newnode = new_attrib_node( GL_LIGHTING_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_LINE_BIT) { + struct gl_line_attrib *attr; + attr = MALLOC_STRUCT( gl_line_attrib ); + MEMCPY( attr, &ctx->Line, sizeof(struct gl_line_attrib) ); + newnode = new_attrib_node( GL_LINE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_LIST_BIT) { + struct gl_list_attrib *attr; + attr = MALLOC_STRUCT( gl_list_attrib ); + MEMCPY( attr, &ctx->List, sizeof(struct gl_list_attrib) ); + newnode = new_attrib_node( GL_LIST_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_PIXEL_MODE_BIT) { + struct gl_pixel_attrib *attr; + attr = MALLOC_STRUCT( gl_pixel_attrib ); + MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) ); + newnode = new_attrib_node( GL_PIXEL_MODE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_POINT_BIT) { + struct gl_point_attrib *attr; + attr = MALLOC_STRUCT( gl_point_attrib ); + MEMCPY( attr, &ctx->Point, sizeof(struct gl_point_attrib) ); + newnode = new_attrib_node( GL_POINT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_POLYGON_BIT) { + struct gl_polygon_attrib *attr; + attr = MALLOC_STRUCT( gl_polygon_attrib ); + MEMCPY( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) ); + newnode = new_attrib_node( GL_POLYGON_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_POLYGON_STIPPLE_BIT) { + GLuint *stipple; + stipple = (GLuint *) MALLOC( 32*sizeof(GLuint) ); + MEMCPY( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) ); + newnode = new_attrib_node( GL_POLYGON_STIPPLE_BIT ); + newnode->data = stipple; + newnode->next = head; + head = newnode; + } + + if (mask & GL_SCISSOR_BIT) { + struct gl_scissor_attrib *attr; + attr = MALLOC_STRUCT( gl_scissor_attrib ); + MEMCPY( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) ); + newnode = new_attrib_node( GL_SCISSOR_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + struct gl_stencil_attrib *attr; + attr = MALLOC_STRUCT( gl_stencil_attrib ); + MEMCPY( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) ); + newnode = new_attrib_node( GL_STENCIL_BUFFER_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_TEXTURE_BIT) { + struct gl_texture_attrib *attr; + GLuint u; + /* Bump the texture object reference counts so that they don't + * inadvertantly get deleted. + */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + ctx->Texture.Unit[u].Current1D->RefCount++; + ctx->Texture.Unit[u].Current2D->RefCount++; + ctx->Texture.Unit[u].Current3D->RefCount++; + ctx->Texture.Unit[u].CurrentCubeMap->RefCount++; + ctx->Texture.Unit[u].CurrentRect->RefCount++; + } + attr = MALLOC_STRUCT( gl_texture_attrib ); + MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) ); + /* copy state of the currently bound texture objects */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + _mesa_copy_texture_object(&attr->Unit[u].Saved1D, + attr->Unit[u].Current1D); + _mesa_copy_texture_object(&attr->Unit[u].Saved2D, + attr->Unit[u].Current2D); + _mesa_copy_texture_object(&attr->Unit[u].Saved3D, + attr->Unit[u].Current3D); + _mesa_copy_texture_object(&attr->Unit[u].SavedCubeMap, + attr->Unit[u].CurrentCubeMap); + _mesa_copy_texture_object(&attr->Unit[u].SavedRect, + attr->Unit[u].CurrentRect); + } + newnode = new_attrib_node( GL_TEXTURE_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_TRANSFORM_BIT) { + struct gl_transform_attrib *attr; + attr = MALLOC_STRUCT( gl_transform_attrib ); + MEMCPY( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) ); + newnode = new_attrib_node( GL_TRANSFORM_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + if (mask & GL_VIEWPORT_BIT) { + struct gl_viewport_attrib *attr; + attr = MALLOC_STRUCT( gl_viewport_attrib ); + MEMCPY( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) ); + newnode = new_attrib_node( GL_VIEWPORT_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + /* GL_ARB_multisample */ + if (mask & GL_MULTISAMPLE_BIT_ARB) { + struct gl_multisample_attrib *attr; + attr = MALLOC_STRUCT( gl_multisample_attrib ); + MEMCPY( attr, &ctx->Multisample, sizeof(struct gl_multisample_attrib) ); + newnode = new_attrib_node( GL_MULTISAMPLE_BIT_ARB ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + + ctx->AttribStack[ctx->AttribStackDepth] = head; + ctx->AttribStackDepth++; +} + + + +static void +pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable) +{ + GLuint i; + +#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \ + if ((VALUE) != (NEWVALUE)) { \ + _mesa_set_enable( ctx, ENUM, (NEWVALUE) ); \ + } + + TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST); + TEST_AND_UPDATE(ctx->Color.BlendEnabled, enable->Blend, GL_BLEND); + + for (i=0;i<MAX_CLIP_PLANES;i++) { + const GLuint mask = 1 << i; + if ((ctx->Transform.ClipPlanesEnabled & mask) != (enable->ClipPlanes & mask)) + _mesa_set_enable(ctx, (GLenum) (GL_CLIP_PLANE0 + i), + (GLboolean) ((enable->ClipPlanes & mask) ? GL_TRUE : GL_FALSE)); + } + + TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial, + GL_COLOR_MATERIAL); + TEST_AND_UPDATE(ctx->Pixel.ColorTableEnabled, enable->ColorTable, + GL_COLOR_TABLE); + TEST_AND_UPDATE(ctx->Pixel.PostColorMatrixColorTableEnabled, + enable->PostColorMatrixColorTable, + GL_POST_COLOR_MATRIX_COLOR_TABLE); + TEST_AND_UPDATE(ctx->Pixel.PostConvolutionColorTableEnabled, + enable->PostConvolutionColorTable, + GL_POST_CONVOLUTION_COLOR_TABLE); + TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE); + TEST_AND_UPDATE(ctx->Depth.Test, enable->DepthTest, GL_DEPTH_TEST); + TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER); + TEST_AND_UPDATE(ctx->Pixel.Convolution1DEnabled, enable->Convolution1D, + GL_CONVOLUTION_1D); + TEST_AND_UPDATE(ctx->Pixel.Convolution2DEnabled, enable->Convolution2D, + GL_CONVOLUTION_2D); + TEST_AND_UPDATE(ctx->Pixel.Separable2DEnabled, enable->Separable2D, + GL_SEPARABLE_2D); + TEST_AND_UPDATE(ctx->Fog.Enabled, enable->Fog, GL_FOG); + TEST_AND_UPDATE(ctx->Light.Enabled, enable->Lighting, GL_LIGHTING); + TEST_AND_UPDATE(ctx->Line.SmoothFlag, enable->LineSmooth, GL_LINE_SMOOTH); + TEST_AND_UPDATE(ctx->Line.StippleFlag, enable->LineStipple, + GL_LINE_STIPPLE); + TEST_AND_UPDATE(ctx->Color.IndexLogicOpEnabled, enable->IndexLogicOp, + GL_INDEX_LOGIC_OP); + TEST_AND_UPDATE(ctx->Color.ColorLogicOpEnabled, enable->ColorLogicOp, + GL_COLOR_LOGIC_OP); + + TEST_AND_UPDATE(ctx->Eval.Map1Color4, enable->Map1Color4, GL_MAP1_COLOR_4); + TEST_AND_UPDATE(ctx->Eval.Map1Index, enable->Map1Index, GL_MAP1_INDEX); + TEST_AND_UPDATE(ctx->Eval.Map1Normal, enable->Map1Normal, GL_MAP1_NORMAL); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord1, enable->Map1TextureCoord1, + GL_MAP1_TEXTURE_COORD_1); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord2, enable->Map1TextureCoord2, + GL_MAP1_TEXTURE_COORD_2); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord3, enable->Map1TextureCoord3, + GL_MAP1_TEXTURE_COORD_3); + TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord4, enable->Map1TextureCoord4, + GL_MAP1_TEXTURE_COORD_4); + TEST_AND_UPDATE(ctx->Eval.Map1Vertex3, enable->Map1Vertex3, + GL_MAP1_VERTEX_3); + TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4, + GL_MAP1_VERTEX_4); + for (i = 0; i < 16; i++) { + TEST_AND_UPDATE(ctx->Eval.Map1Attrib[i], enable->Map1Attrib[i], + GL_MAP1_VERTEX_ATTRIB0_4_NV + i); + } + + TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4); + TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX); + TEST_AND_UPDATE(ctx->Eval.Map2Normal, enable->Map2Normal, GL_MAP2_NORMAL); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord1, enable->Map2TextureCoord1, + GL_MAP2_TEXTURE_COORD_1); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord2, enable->Map2TextureCoord2, + GL_MAP2_TEXTURE_COORD_2); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord3, enable->Map2TextureCoord3, + GL_MAP2_TEXTURE_COORD_3); + TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord4, enable->Map2TextureCoord4, + GL_MAP2_TEXTURE_COORD_4); + TEST_AND_UPDATE(ctx->Eval.Map2Vertex3, enable->Map2Vertex3, + GL_MAP2_VERTEX_3); + TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4, + GL_MAP2_VERTEX_4); + for (i = 0; i < 16; i++) { + TEST_AND_UPDATE(ctx->Eval.Map2Attrib[i], enable->Map2Attrib[i], + GL_MAP2_VERTEX_ATTRIB0_4_NV + i); + } + + TEST_AND_UPDATE(ctx->Eval.AutoNormal, enable->AutoNormal, GL_AUTO_NORMAL); + TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE); + TEST_AND_UPDATE(ctx->Transform.RescaleNormals, enable->RescaleNormals, + GL_RESCALE_NORMAL_EXT); + TEST_AND_UPDATE(ctx->Transform.RasterPositionUnclipped, + enable->RasterPositionUnclipped, + GL_RASTER_POSITION_UNCLIPPED_IBM); + TEST_AND_UPDATE(ctx->Pixel.PixelTextureEnabled, enable->PixelTexture, + GL_POINT_SMOOTH); + TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth, + GL_POINT_SMOOTH); + if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite) { + TEST_AND_UPDATE(ctx->Point.PointSprite, enable->PointSprite, + GL_POINT_SPRITE_NV); + } + TEST_AND_UPDATE(ctx->Polygon.OffsetPoint, enable->PolygonOffsetPoint, + GL_POLYGON_OFFSET_POINT); + TEST_AND_UPDATE(ctx->Polygon.OffsetLine, enable->PolygonOffsetLine, + GL_POLYGON_OFFSET_LINE); + TEST_AND_UPDATE(ctx->Polygon.OffsetFill, enable->PolygonOffsetFill, + GL_POLYGON_OFFSET_FILL); + TEST_AND_UPDATE(ctx->Polygon.SmoothFlag, enable->PolygonSmooth, + GL_POLYGON_SMOOTH); + TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple, + GL_POLYGON_STIPPLE); + TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST); + TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST); + if (ctx->Extensions.EXT_stencil_two_side) { + TEST_AND_UPDATE(ctx->Stencil.TestTwoSide, enable->StencilTwoSide, GL_STENCIL_TEST_TWO_SIDE_EXT); + } + TEST_AND_UPDATE(ctx->Multisample.Enabled, enable->MultisampleEnabled, + GL_MULTISAMPLE_ARB); + TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToCoverage, + enable->SampleAlphaToCoverage, + GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); + TEST_AND_UPDATE(ctx->Multisample.SampleAlphaToOne, + enable->SampleAlphaToOne, + GL_SAMPLE_ALPHA_TO_ONE_ARB); + TEST_AND_UPDATE(ctx->Multisample.SampleCoverage, + enable->SampleCoverage, + GL_SAMPLE_COVERAGE_ARB); + TEST_AND_UPDATE(ctx->Multisample.SampleCoverageInvert, + enable->SampleCoverageInvert, + GL_SAMPLE_COVERAGE_INVERT_ARB); + /* GL_NV_vertex_program */ + TEST_AND_UPDATE(ctx->VertexProgram.Enabled, + enable->VertexProgram, + GL_VERTEX_PROGRAM_NV); + TEST_AND_UPDATE(ctx->VertexProgram.PointSizeEnabled, + enable->VertexProgramPointSize, + GL_VERTEX_PROGRAM_POINT_SIZE_NV); + TEST_AND_UPDATE(ctx->VertexProgram.TwoSideEnabled, + enable->VertexProgramTwoSide, + GL_VERTEX_PROGRAM_TWO_SIDE_NV); + +#undef TEST_AND_UPDATE + + /* texture unit enables */ + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + if (ctx->Texture.Unit[i].Enabled != enable->Texture[i]) { + ctx->Texture.Unit[i].Enabled = enable->Texture[i]; + if (ctx->Driver.Enable) { + if (ctx->Driver.ActiveTexture) { + (*ctx->Driver.ActiveTexture)(ctx, i); + } + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_1D, + (GLboolean) (enable->Texture[i] & TEXTURE_1D_BIT) ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_2D, + (GLboolean) (enable->Texture[i] & TEXTURE_2D_BIT) ); + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_3D, + (GLboolean) (enable->Texture[i] & TEXTURE_3D_BIT) ); + if (ctx->Extensions.ARB_texture_cube_map) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_CUBE_MAP_ARB, + (GLboolean) (enable->Texture[i] & TEXTURE_CUBE_BIT) ); + if (ctx->Extensions.NV_texture_rectangle) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_RECTANGLE_NV, + (GLboolean) (enable->Texture[i] & TEXTURE_RECT_BIT) ); + } + } + + if (ctx->Texture.Unit[i].TexGenEnabled != enable->TexGen[i]) { + ctx->Texture.Unit[i].TexGenEnabled = enable->TexGen[i]; + if (ctx->Driver.Enable) { + if (ctx->Driver.ActiveTexture) { + (*ctx->Driver.ActiveTexture)(ctx, i); + } + if (enable->TexGen[i] & S_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_FALSE); + if (enable->TexGen[i] & T_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_FALSE); + if (enable->TexGen[i] & R_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_FALSE); + if (enable->TexGen[i] & Q_BIT) + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_TRUE); + else + (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_FALSE); + } + } + + /* GL_SGI_texture_color_table */ + ctx->Texture.Unit[i].ColorTableEnabled = enable->TextureColorTable[i]; + } + + if (ctx->Driver.ActiveTexture) { + (*ctx->Driver.ActiveTexture)(ctx, ctx->Texture.CurrentUnit); + } +} + + +static void +pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib) +{ + GLuint u; + + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + const struct gl_texture_unit *unit = &texAttrib->Unit[u]; + GLuint i; + + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u); + _mesa_set_enable(ctx, GL_TEXTURE_1D, + (GLboolean) (unit->Enabled & TEXTURE_1D_BIT ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_2D, + (GLboolean) (unit->Enabled & TEXTURE_2D_BIT ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_3D, + (GLboolean) (unit->Enabled & TEXTURE_3D_BIT ? GL_TRUE : GL_FALSE)); + if (ctx->Extensions.ARB_texture_cube_map) { + _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP_ARB, + (GLboolean) (unit->Enabled & TEXTURE_CUBE_BIT ? GL_TRUE : GL_FALSE)); + } + if (ctx->Extensions.NV_texture_rectangle) { + _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE_NV, + (GLboolean) (unit->Enabled & TEXTURE_RECT_BIT ? GL_TRUE : GL_FALSE)); + } + if (ctx->Extensions.SGI_texture_color_table) { + _mesa_set_enable(ctx, GL_TEXTURE_COLOR_TABLE_SGI, + unit->ColorTableEnabled); + } + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->EnvMode); + _mesa_TexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, unit->EnvColor); + _mesa_TexGeni(GL_S, GL_TEXTURE_GEN_MODE, unit->GenModeS); + _mesa_TexGeni(GL_T, GL_TEXTURE_GEN_MODE, unit->GenModeT); + _mesa_TexGeni(GL_R, GL_TEXTURE_GEN_MODE, unit->GenModeR); + _mesa_TexGeni(GL_Q, GL_TEXTURE_GEN_MODE, unit->GenModeQ); + _mesa_TexGenfv(GL_S, GL_OBJECT_PLANE, unit->ObjectPlaneS); + _mesa_TexGenfv(GL_T, GL_OBJECT_PLANE, unit->ObjectPlaneT); + _mesa_TexGenfv(GL_R, GL_OBJECT_PLANE, unit->ObjectPlaneR); + _mesa_TexGenfv(GL_Q, GL_OBJECT_PLANE, unit->ObjectPlaneQ); + _mesa_TexGenfv(GL_S, GL_EYE_PLANE, unit->EyePlaneS); + _mesa_TexGenfv(GL_T, GL_EYE_PLANE, unit->EyePlaneT); + _mesa_TexGenfv(GL_R, GL_EYE_PLANE, unit->EyePlaneR); + _mesa_TexGenfv(GL_Q, GL_EYE_PLANE, unit->EyePlaneQ); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, + ((unit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, + ((unit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, + ((unit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE)); + _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, + ((unit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE)); + if (ctx->Extensions.EXT_texture_lod_bias) { + _mesa_TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, + GL_TEXTURE_LOD_BIAS_EXT, unit->LodBias); + } + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, + unit->Combine.ModeRGB); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, + unit->Combine.ModeA); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, + unit->Combine.SourceRGB[0]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, + unit->Combine.SourceRGB[1]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, + unit->Combine.SourceRGB[2]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, + unit->Combine.SourceA[0]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, + unit->Combine.SourceA[1]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, + unit->Combine.SourceA[2]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, + unit->Combine.OperandRGB[0]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, + unit->Combine.OperandRGB[1]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, + unit->Combine.OperandRGB[2]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, + unit->Combine.OperandA[0]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, + unit->Combine.OperandA[1]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, + unit->Combine.OperandA[2]); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, + 1 << unit->Combine.ScaleShiftRGB); + _mesa_TexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, + 1 << unit->Combine.ScaleShiftA); + } + + /* Restore texture object state */ + for (i = 0; i < NUM_TEXTURE_TARGETS; i++) { + GLenum target = 0; + const struct gl_texture_object *obj = NULL; + GLfloat bordColor[4]; + + switch (i) { + case 0: + target = GL_TEXTURE_1D; + obj = &unit->Saved1D; + break; + case 1: + target = GL_TEXTURE_2D; + obj = &unit->Saved2D; + break; + case 2: + target = GL_TEXTURE_3D; + obj = &unit->Saved3D; + break; + case 3: + if (!ctx->Extensions.ARB_texture_cube_map) + continue; + target = GL_TEXTURE_CUBE_MAP_ARB; + obj = &unit->SavedCubeMap; + break; + case 4: + if (!ctx->Extensions.NV_texture_rectangle) + continue; + target = GL_TEXTURE_RECTANGLE_NV; + obj = &unit->SavedRect; + break; + default: + ; /* silence warnings */ + } + + _mesa_BindTexture(target, obj->Name); + + bordColor[0] = CHAN_TO_FLOAT(obj->BorderColor[0]); + bordColor[1] = CHAN_TO_FLOAT(obj->BorderColor[1]); + bordColor[2] = CHAN_TO_FLOAT(obj->BorderColor[2]); + bordColor[3] = CHAN_TO_FLOAT(obj->BorderColor[3]); + + _mesa_TexParameterf(target, GL_TEXTURE_PRIORITY, obj->Priority); + _mesa_TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, bordColor); + _mesa_TexParameteri(target, GL_TEXTURE_WRAP_S, obj->WrapS); + _mesa_TexParameteri(target, GL_TEXTURE_WRAP_T, obj->WrapT); + _mesa_TexParameteri(target, GL_TEXTURE_WRAP_R, obj->WrapR); + _mesa_TexParameteri(target, GL_TEXTURE_MIN_FILTER, obj->MinFilter); + _mesa_TexParameteri(target, GL_TEXTURE_MAG_FILTER, obj->MagFilter); + _mesa_TexParameterf(target, GL_TEXTURE_MIN_LOD, obj->MinLod); + _mesa_TexParameterf(target, GL_TEXTURE_MAX_LOD, obj->MaxLod); + _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, obj->BaseLevel); + _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, obj->MaxLevel); + if (ctx->Extensions.EXT_texture_filter_anisotropic) { + _mesa_TexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, + obj->MaxAnisotropy); + } + if (ctx->Extensions.SGIX_shadow) { + _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_SGIX, + obj->CompareFlag); + _mesa_TexParameteri(target, GL_TEXTURE_COMPARE_OPERATOR_SGIX, + obj->CompareOperator); + } + if (ctx->Extensions.SGIX_shadow_ambient) { + _mesa_TexParameterf(target, GL_SHADOW_AMBIENT_SGIX, + obj->ShadowAmbient); + } + + } + } + _mesa_ActiveTextureARB(GL_TEXTURE0_ARB + + texAttrib->CurrentUnit); + + /* "un-bump" the texture object reference counts. We did that so they + * wouldn't inadvertantly get deleted while they were still referenced + * inside the attribute state stack. + */ + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + ctx->Texture.Unit[u].Current1D->RefCount--; + ctx->Texture.Unit[u].Current2D->RefCount--; + ctx->Texture.Unit[u].Current3D->RefCount--; + ctx->Texture.Unit[u].CurrentCubeMap->RefCount--; + ctx->Texture.Unit[u].CurrentRect->RefCount--; + } +} + + +/* + * This function is kind of long just because we have to call a lot + * of device driver functions to update device driver state. + * + * XXX As it is now, most of the pop-code calls immediate-mode Mesa functions + * in order to restore GL state. This isn't terribly efficient but it + * ensures that dirty flags and any derived state gets updated correctly. + * We could at least check if the value to restore equals the current value + * and then skip the Mesa call. + */ +void GLAPIENTRY +_mesa_PopAttrib(void) +{ + struct gl_attrib_node *attr, *next; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->AttribStackDepth == 0) { + _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" ); + return; + } + + ctx->AttribStackDepth--; + attr = ctx->AttribStack[ctx->AttribStackDepth]; + + while (attr) { + + if (MESA_VERBOSE & VERBOSE_API) { + _mesa_debug(ctx, "glPopAttrib %s\n", + _mesa_lookup_enum_by_nr(attr->kind)); + } + + switch (attr->kind) { + case GL_ACCUM_BUFFER_BIT: + { + const struct gl_accum_attrib *accum; + accum = (const struct gl_accum_attrib *) attr->data; + _mesa_ClearAccum(accum->ClearColor[0], + accum->ClearColor[1], + accum->ClearColor[2], + accum->ClearColor[3]); + } + break; + case GL_COLOR_BUFFER_BIT: + { + const struct gl_colorbuffer_attrib *color; + color = (const struct gl_colorbuffer_attrib *) attr->data; + _mesa_ClearIndex((GLfloat) color->ClearIndex); + _mesa_ClearColor(color->ClearColor[0], + color->ClearColor[1], + color->ClearColor[2], + color->ClearColor[3]); + _mesa_IndexMask(color->IndexMask); + _mesa_ColorMask((GLboolean) (color->ColorMask[0] != 0), + (GLboolean) (color->ColorMask[1] != 0), + (GLboolean) (color->ColorMask[2] != 0), + (GLboolean) (color->ColorMask[3] != 0)); +#if 0 + _mesa_DrawBuffersARB(ctx->Const.MaxDrawBuffers, + color->DrawBuffer); +#else + _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + color->DrawBuffer, NULL); +#endif + _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled); + _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef); + _mesa_set_enable(ctx, GL_BLEND, color->BlendEnabled); + _mesa_BlendFuncSeparateEXT(color->BlendSrcRGB, + color->BlendDstRGB, + color->BlendSrcA, + color->BlendDstA); + /* This special case is because glBlendEquationSeparateEXT + * cannot take GL_LOGIC_OP as a parameter. + */ + if ( color->BlendEquationRGB == color->BlendEquationA ) { + _mesa_BlendEquation(color->BlendEquationRGB); + } + else { + _mesa_BlendEquationSeparateEXT(color->BlendEquationRGB, + color->BlendEquationA); + } + _mesa_BlendColor(color->BlendColor[0], + color->BlendColor[1], + color->BlendColor[2], + color->BlendColor[3]); + _mesa_LogicOp(color->LogicOp); + _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, + color->ColorLogicOpEnabled); + _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP, + color->IndexLogicOpEnabled); + _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag); + } + break; + case GL_CURRENT_BIT: + FLUSH_CURRENT( ctx, 0 ); + MEMCPY( &ctx->Current, attr->data, + sizeof(struct gl_current_attrib) ); + break; + case GL_DEPTH_BUFFER_BIT: + { + const struct gl_depthbuffer_attrib *depth; + depth = (const struct gl_depthbuffer_attrib *) attr->data; + _mesa_DepthFunc(depth->Func); + _mesa_ClearDepth(depth->Clear); + _mesa_set_enable(ctx, GL_DEPTH_TEST, depth->Test); + _mesa_DepthMask(depth->Mask); + if (ctx->Extensions.HP_occlusion_test) + _mesa_set_enable(ctx, GL_OCCLUSION_TEST_HP, + depth->OcclusionTest); + } + break; + case GL_ENABLE_BIT: + { + const struct gl_enable_attrib *enable; + enable = (const struct gl_enable_attrib *) attr->data; + pop_enable_group(ctx, enable); + ctx->NewState |= _NEW_ALL; + } + break; + case GL_EVAL_BIT: + MEMCPY( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) ); + ctx->NewState |= _NEW_EVAL; + break; + case GL_FOG_BIT: + { + const struct gl_fog_attrib *fog; + fog = (const struct gl_fog_attrib *) attr->data; + _mesa_set_enable(ctx, GL_FOG, fog->Enabled); + _mesa_Fogfv(GL_FOG_COLOR, fog->Color); + _mesa_Fogf(GL_FOG_DENSITY, fog->Density); + _mesa_Fogf(GL_FOG_START, fog->Start); + _mesa_Fogf(GL_FOG_END, fog->End); + _mesa_Fogf(GL_FOG_INDEX, fog->Index); + _mesa_Fogi(GL_FOG_MODE, fog->Mode); + } + break; + case GL_HINT_BIT: + { + const struct gl_hint_attrib *hint; + hint = (const struct gl_hint_attrib *) attr->data; + _mesa_Hint(GL_PERSPECTIVE_CORRECTION_HINT, + hint->PerspectiveCorrection ); + _mesa_Hint(GL_POINT_SMOOTH_HINT, hint->PointSmooth); + _mesa_Hint(GL_LINE_SMOOTH_HINT, hint->LineSmooth); + _mesa_Hint(GL_POLYGON_SMOOTH_HINT, hint->PolygonSmooth); + _mesa_Hint(GL_FOG_HINT, hint->Fog); + _mesa_Hint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, + hint->ClipVolumeClipping); + if (ctx->Extensions.ARB_texture_compression) + _mesa_Hint(GL_TEXTURE_COMPRESSION_HINT_ARB, + hint->TextureCompression); + } + break; + case GL_LIGHTING_BIT: + { + GLuint i; + const struct gl_light_attrib *light; + light = (const struct gl_light_attrib *) attr->data; + /* lighting enable */ + _mesa_set_enable(ctx, GL_LIGHTING, light->Enabled); + /* per-light state */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + + for (i = 0; i < MAX_LIGHTS; i++) { + GLenum lgt = (GLenum) (GL_LIGHT0 + i); + const struct gl_light *l = &light->Light[i]; + GLfloat tmp[4]; + _mesa_set_enable(ctx, lgt, l->Enabled); + _mesa_Lightfv( lgt, GL_AMBIENT, l->Ambient ); + _mesa_Lightfv( lgt, GL_DIFFUSE, l->Diffuse ); + _mesa_Lightfv( lgt, GL_SPECULAR, l->Specular ); + TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->inv, l->EyePosition ); + _mesa_Lightfv( lgt, GL_POSITION, tmp ); + TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->m, l->EyeDirection ); + _mesa_Lightfv( lgt, GL_SPOT_DIRECTION, tmp ); + _mesa_Lightfv( lgt, GL_SPOT_EXPONENT, &l->SpotExponent ); + _mesa_Lightfv( lgt, GL_SPOT_CUTOFF, &l->SpotCutoff ); + _mesa_Lightfv( lgt, GL_CONSTANT_ATTENUATION, + &l->ConstantAttenuation ); + _mesa_Lightfv( lgt, GL_LINEAR_ATTENUATION, + &l->LinearAttenuation ); + _mesa_Lightfv( lgt, GL_QUADRATIC_ATTENUATION, + &l->QuadraticAttenuation ); + } + /* light model */ + _mesa_LightModelfv(GL_LIGHT_MODEL_AMBIENT, + light->Model.Ambient); + _mesa_LightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, + (GLfloat) light->Model.LocalViewer); + _mesa_LightModelf(GL_LIGHT_MODEL_TWO_SIDE, + (GLfloat) light->Model.TwoSide); + _mesa_LightModelf(GL_LIGHT_MODEL_COLOR_CONTROL, + (GLfloat) light->Model.ColorControl); + /* materials */ + MEMCPY(&ctx->Light.Material, &light->Material, + sizeof(struct gl_material)); + /* shade model */ + _mesa_ShadeModel(light->ShadeModel); + /* color material */ + _mesa_ColorMaterial(light->ColorMaterialFace, + light->ColorMaterialMode); + _mesa_set_enable(ctx, GL_COLOR_MATERIAL, + light->ColorMaterialEnabled); + } + break; + case GL_LINE_BIT: + { + const struct gl_line_attrib *line; + line = (const struct gl_line_attrib *) attr->data; + _mesa_set_enable(ctx, GL_LINE_SMOOTH, line->SmoothFlag); + _mesa_set_enable(ctx, GL_LINE_STIPPLE, line->StippleFlag); + _mesa_LineStipple(line->StippleFactor, line->StipplePattern); + _mesa_LineWidth(line->Width); + } + break; + case GL_LIST_BIT: + MEMCPY( &ctx->List, attr->data, sizeof(struct gl_list_attrib) ); + break; + case GL_PIXEL_MODE_BIT: + MEMCPY( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) ); + /* XXX what other pixel state needs to be set by function calls? */ + _mesa_ReadBuffer(ctx->Pixel.ReadBuffer); + ctx->NewState |= _NEW_PIXEL; + break; + case GL_POINT_BIT: + { + const struct gl_point_attrib *point; + point = (const struct gl_point_attrib *) attr->data; + _mesa_PointSize(point->Size); + _mesa_set_enable(ctx, GL_POINT_SMOOTH, point->SmoothFlag); + if (ctx->Extensions.EXT_point_parameters) { + _mesa_PointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, + point->Params); + _mesa_PointParameterfEXT(GL_POINT_SIZE_MIN_EXT, + point->MinSize); + _mesa_PointParameterfEXT(GL_POINT_SIZE_MAX_EXT, + point->MaxSize); + _mesa_PointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, + point->Threshold); + } + if (ctx->Extensions.NV_point_sprite + || ctx->Extensions.ARB_point_sprite) { + GLuint u; + for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { + _mesa_TexEnvi(GL_POINT_SPRITE_NV, GL_COORD_REPLACE_NV, + (GLint) point->CoordReplace[u]); + } + _mesa_set_enable(ctx, GL_POINT_SPRITE_NV,point->PointSprite); + _mesa_PointParameteriNV(GL_POINT_SPRITE_R_MODE_NV, + ctx->Point.SpriteRMode); + _mesa_PointParameterfEXT(GL_POINT_SPRITE_COORD_ORIGIN, + (GLfloat)ctx->Point.SpriteOrigin); + } + } + break; + case GL_POLYGON_BIT: + { + const struct gl_polygon_attrib *polygon; + polygon = (const struct gl_polygon_attrib *) attr->data; + _mesa_CullFace(polygon->CullFaceMode); + _mesa_FrontFace(polygon->FrontFace); + _mesa_PolygonMode(GL_FRONT, polygon->FrontMode); + _mesa_PolygonMode(GL_BACK, polygon->BackMode); + _mesa_PolygonOffset(polygon->OffsetFactor, + polygon->OffsetUnits); + _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, polygon->SmoothFlag); + _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, polygon->StippleFlag); + _mesa_set_enable(ctx, GL_CULL_FACE, polygon->CullFlag); + _mesa_set_enable(ctx, GL_POLYGON_OFFSET_POINT, + polygon->OffsetPoint); + _mesa_set_enable(ctx, GL_POLYGON_OFFSET_LINE, + polygon->OffsetLine); + _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, + polygon->OffsetFill); + } + break; + case GL_POLYGON_STIPPLE_BIT: + MEMCPY( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) ); + ctx->NewState |= _NEW_POLYGONSTIPPLE; + if (ctx->Driver.PolygonStipple) + ctx->Driver.PolygonStipple( ctx, (const GLubyte *) attr->data ); + break; + case GL_SCISSOR_BIT: + { + const struct gl_scissor_attrib *scissor; + scissor = (const struct gl_scissor_attrib *) attr->data; + _mesa_Scissor(scissor->X, scissor->Y, + scissor->Width, scissor->Height); + _mesa_set_enable(ctx, GL_SCISSOR_TEST, scissor->Enabled); + } + break; + case GL_STENCIL_BUFFER_BIT: + { + GLint face; + const struct gl_stencil_attrib *stencil; + stencil = (const struct gl_stencil_attrib *) attr->data; + _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); + _mesa_ClearStencil(stencil->Clear); + face = stencil->ActiveFace; + if (ctx->Extensions.EXT_stencil_two_side) { + _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, stencil->TestTwoSide); + face ^= 1; + } + do { + _mesa_ActiveStencilFaceEXT(face); + _mesa_StencilFunc(stencil->Function[face], stencil->Ref[face], + stencil->ValueMask[face]); + _mesa_StencilMask(stencil->WriteMask[face]); + _mesa_StencilOp(stencil->FailFunc[face], + stencil->ZFailFunc[face], + stencil->ZPassFunc[face]); + face ^= 1; + } while (face != (stencil->ActiveFace ^ 1)); + } + break; + case GL_TRANSFORM_BIT: + { + GLuint i; + const struct gl_transform_attrib *xform; + xform = (const struct gl_transform_attrib *) attr->data; + _mesa_MatrixMode(xform->MatrixMode); + if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top)) + _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); + + /* restore clip planes */ + for (i = 0; i < MAX_CLIP_PLANES; i++) { + const GLuint mask = 1 << 1; + const GLfloat *eyePlane = xform->EyeUserPlane[i]; + COPY_4V(ctx->Transform.EyeUserPlane[i], eyePlane); + if (xform->ClipPlanesEnabled & mask) { + _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE); + } + else { + _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE); + } + if (ctx->Driver.ClipPlane) + ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, eyePlane ); + } + + /* normalize/rescale */ + if (xform->Normalize != ctx->Transform.Normalize) + _mesa_set_enable(ctx, GL_NORMALIZE,ctx->Transform.Normalize); + if (xform->RescaleNormals != ctx->Transform.RescaleNormals) + _mesa_set_enable(ctx, GL_RESCALE_NORMAL_EXT, + ctx->Transform.RescaleNormals); + } + break; + case GL_TEXTURE_BIT: + /* Take care of texture object reference counters */ + { + const struct gl_texture_attrib *texture; + texture = (const struct gl_texture_attrib *) attr->data; + pop_texture_group(ctx, texture); + ctx->NewState |= _NEW_TEXTURE; + } + break; + case GL_VIEWPORT_BIT: + { + const struct gl_viewport_attrib *vp; + vp = (const struct gl_viewport_attrib *) attr->data; + _mesa_Viewport(vp->X, vp->Y, vp->Width, vp->Height); + _mesa_DepthRange(vp->Near, vp->Far); + } + break; + case GL_MULTISAMPLE_BIT_ARB: + { + const struct gl_multisample_attrib *ms; + ms = (const struct gl_multisample_attrib *) attr->data; + _mesa_SampleCoverageARB(ms->SampleCoverageValue, + ms->SampleCoverageInvert); + } + break; + + default: + _mesa_problem( ctx, "Bad attrib flag in PopAttrib"); + break; + } + + next = attr->next; + FREE( attr->data ); + FREE( attr ); + attr = next; + } +} + + +/** + * Helper for incrementing/decrementing vertex buffer object reference + * counts when pushing/popping the GL_CLIENT_VERTEX_ARRAY_BIT attribute group. + */ +static void +adjust_buffer_object_ref_counts(struct gl_array_attrib *array, GLint step) +{ + GLuint i; + array->Vertex.BufferObj->RefCount += step; + array->Normal.BufferObj->RefCount += step; + array->Color.BufferObj->RefCount += step; + array->SecondaryColor.BufferObj->RefCount += step; + array->FogCoord.BufferObj->RefCount += step; + array->Index.BufferObj->RefCount += step; + array->EdgeFlag.BufferObj->RefCount += step; + for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) + array->TexCoord[i].BufferObj->RefCount += step; + for (i = 0; i < VERT_ATTRIB_MAX; i++) + array->VertexAttrib[i].BufferObj->RefCount += step; + + array->ArrayBufferObj->RefCount += step; + array->ElementArrayBufferObj->RefCount += step; +} + + +#define GL_CLIENT_PACK_BIT (1<<20) +#define GL_CLIENT_UNPACK_BIT (1<<21) + + +void GLAPIENTRY +_mesa_PushClientAttrib(GLbitfield mask) +{ + struct gl_attrib_node *newnode; + struct gl_attrib_node *head; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->ClientAttribStackDepth >= MAX_CLIENT_ATTRIB_STACK_DEPTH) { + _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" ); + return; + } + + /* Build linked list of attribute nodes which save all attribute */ + /* groups specified by the mask. */ + head = NULL; + + if (mask & GL_CLIENT_PIXEL_STORE_BIT) { + struct gl_pixelstore_attrib *attr; +#if FEATURE_EXT_pixel_buffer_object + ctx->Pack.BufferObj->RefCount++; + ctx->Unpack.BufferObj->RefCount++; +#endif + /* packing attribs */ + attr = MALLOC_STRUCT( gl_pixelstore_attrib ); + MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) ); + newnode = new_attrib_node( GL_CLIENT_PACK_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + /* unpacking attribs */ + attr = MALLOC_STRUCT( gl_pixelstore_attrib ); + MEMCPY( attr, &ctx->Unpack, sizeof(struct gl_pixelstore_attrib) ); + newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + } + if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { + struct gl_array_attrib *attr; + attr = MALLOC_STRUCT( gl_array_attrib ); + MEMCPY( attr, &ctx->Array, sizeof(struct gl_array_attrib) ); + newnode = new_attrib_node( GL_CLIENT_VERTEX_ARRAY_BIT ); + newnode->data = attr; + newnode->next = head; + head = newnode; + /* bump reference counts on buffer objects */ + adjust_buffer_object_ref_counts(&ctx->Array, 1); + } + + ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head; + ctx->ClientAttribStackDepth++; +} + + + + +void GLAPIENTRY +_mesa_PopClientAttrib(void) +{ + struct gl_attrib_node *attr, *next; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->ClientAttribStackDepth == 0) { + _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" ); + return; + } + + ctx->ClientAttribStackDepth--; + attr = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; + + while (attr) { + switch (attr->kind) { + case GL_CLIENT_PACK_BIT: +#if FEATURE_EXT_pixel_buffer_object + ctx->Pack.BufferObj->RefCount--; + if (ctx->Pack.BufferObj->RefCount <= 0) { + _mesa_remove_buffer_object( ctx, ctx->Pack.BufferObj ); + (*ctx->Driver.DeleteBuffer)( ctx, ctx->Pack.BufferObj ); + } +#endif + MEMCPY( &ctx->Pack, attr->data, + sizeof(struct gl_pixelstore_attrib) ); + ctx->NewState |= _NEW_PACKUNPACK; + break; + case GL_CLIENT_UNPACK_BIT: +#if FEATURE_EXT_pixel_buffer_object + ctx->Unpack.BufferObj->RefCount--; + if (ctx->Unpack.BufferObj->RefCount <= 0) { + _mesa_remove_buffer_object( ctx, ctx->Unpack.BufferObj ); + (*ctx->Driver.DeleteBuffer)( ctx, ctx->Unpack.BufferObj ); + } +#endif + MEMCPY( &ctx->Unpack, attr->data, + sizeof(struct gl_pixelstore_attrib) ); + ctx->NewState |= _NEW_PACKUNPACK; + break; + case GL_CLIENT_VERTEX_ARRAY_BIT: + adjust_buffer_object_ref_counts(&ctx->Array, -1); + MEMCPY( &ctx->Array, attr->data, + sizeof(struct gl_array_attrib) ); + /* decrement reference counts on buffer objects */ + ctx->NewState |= _NEW_ARRAY; + break; + default: + _mesa_problem( ctx, "Bad attrib flag in PopClientAttrib"); + break; + } + + next = attr->next; + FREE( attr->data ); + FREE( attr ); + attr = next; + } +} + + +void _mesa_init_attrib( GLcontext *ctx ) +{ + /* Renderer and client attribute stacks */ + ctx->AttribStackDepth = 0; + ctx->ClientAttribStackDepth = 0; +} diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h new file mode 100644 index 00000000000..09d75196b23 --- /dev/null +++ b/src/mesa/main/attrib.h @@ -0,0 +1,68 @@ +/** + * \file attrib.h + * Attribute stacks. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef ATTRIB_H +#define ATTRIB_H + + +#include "mtypes.h" + + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_PushAttrib( GLbitfield mask ); + +extern void GLAPIENTRY +_mesa_PopAttrib( void ); + +extern void GLAPIENTRY +_mesa_PushClientAttrib( GLbitfield mask ); + +extern void GLAPIENTRY +_mesa_PopClientAttrib( void ); + +extern void +_mesa_init_attrib( GLcontext *ctx ); + +#else + +/** No-op */ +#define _mesa_init_attrib( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c new file mode 100644 index 00000000000..61b2b17c0c3 --- /dev/null +++ b/src/mesa/main/blend.c @@ -0,0 +1,579 @@ +/** + * \file blend.c + * Blending operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#include "glheader.h" +#include "blend.h" +#include "colormac.h" +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "mtypes.h" + + +/** + * Specify the blending operation. + * + * \param sfactor source factor operator. + * \param dfactor destination factor operator. + * + * \sa glBlendFunc, glBlendFuncSeparateEXT + * + * Swizzles the inputs and calls \c glBlendFuncSeparateEXT. This is done + * using the \c CurrentDispatch table in the context, so this same function + * can be used while compiling display lists. Therefore, there is no need + * for the display list code to save and restore this function. + */ +void GLAPIENTRY +_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) +{ + GET_CURRENT_CONTEXT(ctx); + + (*ctx->CurrentDispatch->BlendFuncSeparateEXT)( sfactor, dfactor, + sfactor, dfactor ); +} + + +/** + * Process GL_EXT_blend_func_separate(). + * + * \param sfactorRGB RGB source factor operator. + * \param dfactorRGB RGB destination factor operator. + * \param sfactorA alpha source factor operator. + * \param dfactorA alpha destination factor operator. + * + * Verifies the parameters and updates gl_colorbuffer_attrib. + * On a change, flush the vertices and notify the driver via + * dd_function_table::BlendFuncSeparate. + */ +void GLAPIENTRY +_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n", + _mesa_lookup_enum_by_nr(sfactorRGB), + _mesa_lookup_enum_by_nr(dfactorRGB), + _mesa_lookup_enum_by_nr(sfactorA), + _mesa_lookup_enum_by_nr(dfactorA)); + + switch (sfactorRGB) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + if (!ctx->Extensions.NV_blend_square) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)"); + return; + } + /* fall-through */ + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)"); + return; + } + + switch (dfactorRGB) { + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + if (!ctx->Extensions.NV_blend_square) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)"); + return; + } + /* fall-through */ + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)"); + return; + } + + switch (sfactorA) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + if (!ctx->Extensions.NV_blend_square) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)"); + return; + } + /* fall-through */ + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)"); + return; + } + + switch (dfactorA) { + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + if (!ctx->Extensions.NV_blend_square) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)"); + return; + } + /* fall-through */ + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)" ); + return; + } + + if (ctx->Color.BlendSrcRGB == sfactorRGB && + ctx->Color.BlendDstRGB == dfactorRGB && + ctx->Color.BlendSrcA == sfactorA && + ctx->Color.BlendDstA == dfactorA) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + + ctx->Color.BlendSrcRGB = sfactorRGB; + ctx->Color.BlendDstRGB = dfactorRGB; + ctx->Color.BlendSrcA = sfactorA; + ctx->Color.BlendDstA = dfactorA; + + if (ctx->Driver.BlendFuncSeparate) { + (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB, + sfactorA, dfactorA ); + } +} + + +#if _HAVE_FULL_GL + +static GLboolean +_mesa_validate_blend_equation( GLcontext *ctx, + GLenum mode, GLboolean is_separate ) +{ + switch (mode) { + case GL_FUNC_ADD: + break; + case GL_MIN: + case GL_MAX: + if (!ctx->Extensions.EXT_blend_minmax && + !ctx->Extensions.ARB_imaging) { + return GL_FALSE; + } + break; + /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter. + */ + case GL_LOGIC_OP: + if (!ctx->Extensions.EXT_blend_logic_op || is_separate) { + return GL_FALSE; + } + break; + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + if (!ctx->Extensions.EXT_blend_subtract && + !ctx->Extensions.ARB_imaging) { + return GL_FALSE; + } + break; + default: + return GL_FALSE; + } + + return GL_TRUE; +} + + +/* This is really an extension function! */ +void GLAPIENTRY +_mesa_BlendEquation( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glBlendEquation %s\n", + _mesa_lookup_enum_by_nr(mode)); + + if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); + return; + } + + if ( (ctx->Color.BlendEquationRGB == mode) && + (ctx->Color.BlendEquationA == mode) ) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.BlendEquationRGB = mode; + ctx->Color.BlendEquationA = mode; + + /* This is needed to support 1.1's RGB logic ops AND + * 1.0's blending logicops. + */ + ctx->Color._LogicOpEnabled = (ctx->Color.ColorLogicOpEnabled || + (ctx->Color.BlendEnabled && + mode == GL_LOGIC_OP)); + + if (ctx->Driver.BlendEquationSeparate) + (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode ); +} + + +void GLAPIENTRY +_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n", + _mesa_lookup_enum_by_nr(modeRGB), + _mesa_lookup_enum_by_nr(modeA)); + + if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlendEquationSeparateEXT not supported by driver"); + return; + } + + if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)"); + return; + } + + if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)"); + return; + } + + + if ( (ctx->Color.BlendEquationRGB == modeRGB) && + (ctx->Color.BlendEquationA == modeA) ) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.BlendEquationRGB = modeRGB; + ctx->Color.BlendEquationA = modeA; + + /* This is needed to support 1.1's RGB logic ops AND + * 1.0's blending logicops. This test is simplified over glBlendEquation + * because modeRGB cannot be GL_LOGIC_OP. + */ + ctx->Color._LogicOpEnabled = (ctx->Color.ColorLogicOpEnabled); + + if (ctx->Driver.BlendEquationSeparate) + (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA ); +} +#endif + + +/** + * Set the blending color. + * + * \param red red color component. + * \param green green color component. + * \param blue blue color component. + * \param alpha alpha color component. + * + * \sa glBlendColor(). + * + * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a + * change, flushes the vertices and notifies the driver via + * dd_function_table::BlendColor callback. + */ +void GLAPIENTRY +_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ + GLfloat tmp[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + tmp[0] = CLAMP( red, 0.0F, 1.0F ); + tmp[1] = CLAMP( green, 0.0F, 1.0F ); + tmp[2] = CLAMP( blue, 0.0F, 1.0F ); + tmp[3] = CLAMP( alpha, 0.0F, 1.0F ); + + if (TEST_EQ_4V(tmp, ctx->Color.BlendColor)) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4FV( ctx->Color.BlendColor, tmp ); + + if (ctx->Driver.BlendColor) + (*ctx->Driver.BlendColor)(ctx, tmp); +} + + +/** + * Specify the alpha test function. + * + * \param func alpha comparison function. + * \param ref reference value. + * + * Verifies the parameters and updates gl_colorbuffer_attrib. + * On a change, flushes the vertices and notifies the driver via + * dd_function_table::AlphaFunc callback. + */ +void GLAPIENTRY +_mesa_AlphaFunc( GLenum func, GLclampf ref ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_EQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + case GL_GEQUAL: + case GL_ALWAYS: + ref = CLAMP(ref, 0.0F, 1.0F); + + if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.AlphaFunc = func; + ctx->Color.AlphaRef = ref; + + if (ctx->Driver.AlphaFunc) + ctx->Driver.AlphaFunc(ctx, func, ref); + return; + + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" ); + return; + } +} + + +/** + * Specify a logic pixel operation for color index rendering. + * + * \param opcode operation. + * + * Verifies that \p opcode is a valid enum and updates +gl_colorbuffer_attrib::LogicOp. + * On a change, flushes the vertices and notifies the driver via the + * dd_function_table::LogicOpcode callback. + */ +void GLAPIENTRY +_mesa_LogicOp( GLenum opcode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (opcode) { + case GL_CLEAR: + case GL_SET: + case GL_COPY: + case GL_COPY_INVERTED: + case GL_NOOP: + case GL_INVERT: + case GL_AND: + case GL_NAND: + case GL_OR: + case GL_NOR: + case GL_XOR: + case GL_EQUIV: + case GL_AND_REVERSE: + case GL_AND_INVERTED: + case GL_OR_REVERSE: + case GL_OR_INVERTED: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" ); + return; + } + + if (ctx->Color.LogicOp == opcode) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.LogicOp = opcode; + + if (ctx->Driver.LogicOpcode) + ctx->Driver.LogicOpcode( ctx, opcode ); +} + +#if _HAVE_FULL_GL +void GLAPIENTRY +_mesa_IndexMask( GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->Color.IndexMask == mask) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.IndexMask = mask; + + if (ctx->Driver.IndexMask) + ctx->Driver.IndexMask( ctx, mask ); +} +#endif + + +/** + * Enable or disable writing of frame buffer color components. + * + * \param red whether to mask writing of the red color component. + * \param green whether to mask writing of the green color component. + * \param blue whether to mask writing of the blue color component. + * \param alpha whether to mask writing of the alpha color component. + * + * \sa glColorMask(). + * + * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a + * change, flushes the vertices and notifies the driver via the + * dd_function_table::ColorMask callback. + */ +void GLAPIENTRY +_mesa_ColorMask( GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ) +{ + GET_CURRENT_CONTEXT(ctx); + GLubyte tmp[4]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glColorMask %d %d %d %d\n", red, green, blue, alpha); + + /* Shouldn't have any information about channel depth in core mesa + * -- should probably store these as the native booleans: + */ + tmp[RCOMP] = red ? 0xff : 0x0; + tmp[GCOMP] = green ? 0xff : 0x0; + tmp[BCOMP] = blue ? 0xff : 0x0; + tmp[ACOMP] = alpha ? 0xff : 0x0; + + if (TEST_EQ_4UBV(tmp, ctx->Color.ColorMask)) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4UBV(ctx->Color.ColorMask, tmp); + + if (ctx->Driver.ColorMask) + ctx->Driver.ColorMask( ctx, red, green, blue, alpha ); +} + + +/**********************************************************************/ +/** \name Initialization */ +/*@{*/ + +/** + * Initialization of the context's Color attribute group. + * + * \param ctx GL context. + * + * Initializes the related fields in the context color attribute group, + * __GLcontextRec::Color. + */ +void _mesa_init_color( GLcontext * ctx ) +{ + /* Color buffer group */ + ctx->Color.IndexMask = ~0u; + ctx->Color.ColorMask[0] = 0xff; + ctx->Color.ColorMask[1] = 0xff; + ctx->Color.ColorMask[2] = 0xff; + ctx->Color.ColorMask[3] = 0xff; + ctx->Color.ClearIndex = 0; + ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 ); + ctx->Color.AlphaEnabled = GL_FALSE; + ctx->Color.AlphaFunc = GL_ALWAYS; + ctx->Color.AlphaRef = 0; + ctx->Color.BlendEnabled = GL_FALSE; + ctx->Color.BlendSrcRGB = GL_ONE; + ctx->Color.BlendDstRGB = GL_ZERO; + ctx->Color.BlendSrcA = GL_ONE; + ctx->Color.BlendDstA = GL_ZERO; + ctx->Color.BlendEquationRGB = GL_FUNC_ADD; + ctx->Color.BlendEquationA = GL_FUNC_ADD; + ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); + ctx->Color.IndexLogicOpEnabled = GL_FALSE; + ctx->Color.ColorLogicOpEnabled = GL_FALSE; + ctx->Color._LogicOpEnabled = GL_FALSE; + ctx->Color.LogicOp = GL_COPY; + ctx->Color.DitherFlag = GL_TRUE; + + if (ctx->Visual.doubleBufferMode) { + ctx->Color.DrawBuffer[0] = GL_BACK; + } + else { + ctx->Color.DrawBuffer[0] = GL_FRONT; + } +} + +/*@}*/ diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h new file mode 100644 index 00000000000..d6c03d903f4 --- /dev/null +++ b/src/mesa/main/blend.h @@ -0,0 +1,78 @@ +/** + * \file blend.h + * Blending functions operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef BLEND_H +#define BLEND_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ); + + +extern void GLAPIENTRY +_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ); + + +extern void GLAPIENTRY +_mesa_BlendEquation( GLenum mode ); + + +extern void GLAPIENTRY +_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ); + + +extern void GLAPIENTRY +_mesa_BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + + +extern void GLAPIENTRY +_mesa_AlphaFunc( GLenum func, GLclampf ref ); + + +extern void GLAPIENTRY +_mesa_LogicOp( GLenum opcode ); + + +extern void GLAPIENTRY +_mesa_IndexMask( GLuint mask ); + +extern void GLAPIENTRY +_mesa_ColorMask( GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ); + +extern void +_mesa_init_color( GLcontext * ctx ); + +#endif diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c new file mode 100644 index 00000000000..a1d4c0190a1 --- /dev/null +++ b/src/mesa/main/bufferobj.c @@ -0,0 +1,940 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file bufferobj.c + * \brief Functions for the GL_ARB_vertex_buffer_object extension. + * \author Brian Paul, Ian Romanick + */ + + +#include "glheader.h" +#include "hash.h" +#include "imports.h" +#include "image.h" +#include "context.h" +#include "bufferobj.h" + + +/** + * Get the buffer object bound to the specified target in a GL context. + * + * \param ctx GL context + * \param target Buffer object target to be retrieved. Currently this must + * be either \c GL_ARRAY_BUFFER or \c GL_ELEMENT_ARRAY_BUFFER. + * \param str Name of caller for logging errors. + * \return A pointer to the buffer object bound to \c target in the + * specified context or \c NULL if \c target is invalid or no + * buffer object is bound. + */ +static INLINE struct gl_buffer_object * +buffer_object_get_target( GLcontext *ctx, GLenum target, const char * str ) +{ + struct gl_buffer_object * bufObj = NULL; + + switch (target) { + case GL_ARRAY_BUFFER_ARB: + bufObj = ctx->Array.ArrayBufferObj; + break; + case GL_ELEMENT_ARRAY_BUFFER_ARB: + bufObj = ctx->Array.ElementArrayBufferObj; + break; + case GL_PIXEL_PACK_BUFFER_EXT: + bufObj = ctx->Pack.BufferObj; + break; + case GL_PIXEL_UNPACK_BUFFER_EXT: + bufObj = ctx->Unpack.BufferObj; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(target)", str); + return NULL; + } + + if (bufObj->Name == 0) + return NULL; + + return bufObj; +} + + +/** + * Tests the subdata range parameters and sets the GL error code for + * \c glBufferSubDataARB and \c glGetBufferSubDataARB. + * + * \param ctx GL context. + * \param target Buffer object target on which to operate. + * \param offset Offset of the first byte of the subdata range. + * \param size Size, in bytes, of the subdata range. + * \param str Name of caller for logging errors. + * \return A pointer to the buffer object bound to \c target in the + * specified context or \c NULL if any of the parameter or state + * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB + * are invalid. + * + * \sa glBufferSubDataARB, glGetBufferSubDataARB + */ +static struct gl_buffer_object * +buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, + GLintptrARB offset, GLsizeiptrARB size, + const char * str ) +{ + struct gl_buffer_object *bufObj; + + if (size < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", str); + return NULL; + } + + if (offset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", str); + return NULL; + } + + bufObj = buffer_object_get_target( ctx, target, str ); + if (!bufObj || bufObj->Name == 0) { + return NULL; + } + + if ((GLuint) (offset + size) > bufObj->Size) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(size + offset > buffer size)", str); + return NULL; + } + + if (bufObj->Pointer) { + /* Buffer is currently mapped */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", str); + return NULL; + } + + return bufObj; +} + + +/** + * Allocate and initialize a new buffer object. + * + * This function is intended to be called via + * \c dd_function_table::NewBufferObject. + */ +struct gl_buffer_object * +_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target ) +{ + struct gl_buffer_object *obj; + + (void) ctx; + + obj = MALLOC_STRUCT(gl_buffer_object); + _mesa_initialize_buffer_object(obj, name, target); + return obj; +} + + +/** + * Delete a buffer object. + * + * This function is intended to be called via + * \c dd_function_table::DeleteBuffer. + */ +void +_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) +{ + (void) ctx; + + if (bufObj->Data) + _mesa_free(bufObj->Data); + _mesa_free(bufObj); +} + + +/** + * Initialize a buffer object to default values. + */ +void +_mesa_initialize_buffer_object( struct gl_buffer_object *obj, + GLuint name, GLenum target ) +{ + (void) target; + + _mesa_bzero(obj, sizeof(struct gl_buffer_object)); + obj->RefCount = 1; + obj->Name = name; + obj->Usage = GL_STATIC_DRAW_ARB; + obj->Access = GL_READ_WRITE_ARB; +} + + +/** + * Add the given buffer object to the buffer object pool. + */ +void +_mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj ) +{ + if (obj->Name > 0) { + /* insert into hash table */ + _mesa_HashInsert(ctx->Shared->BufferObjects, obj->Name, obj); + } +} + + +/** + * Remove the given buffer object from the buffer object pool. + * Do not deallocate the buffer object though. + */ +void +_mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) +{ + if (bufObj->Name > 0) { + /* remove from hash table */ + _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name); + } +} + + +/** + * Allocate space for and store data in a buffer object. Any data that was + * previously stored in the buffer object is lost. If \c data is \c NULL, + * memory will be allocated, but no copy will occur. + * + * This function is intended to be called via + * \c dd_function_table::BufferData. This function need not set GL error + * codes. The input parameters will have been tested before calling. + * + * \param ctx GL context. + * \param target Buffer object target on which to operate. + * \param size Size, in bytes, of the new data store. + * \param data Pointer to the data to store in the buffer object. This + * pointer may be \c NULL. + * \param usage Hints about how the data will be used. + * \param bufObj Object to be used. + * + * \sa glBufferDataARB, dd_function_table::BufferData. + */ +void +_mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, + const GLvoid * data, GLenum usage, + struct gl_buffer_object * bufObj ) +{ + void * new_data; + + (void) ctx; (void) target; + + new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size ); + if (new_data) { + bufObj->Data = (GLubyte *) new_data; + bufObj->Size = size; + bufObj->Usage = usage; + + if (data) { + _mesa_memcpy( bufObj->Data, data, size ); + } + } +} + + +/** + * Replace data in a subrange of buffer object. If the data range + * specified by \c size + \c offset extends beyond the end of the buffer or + * if \c data is \c NULL, no copy is performed. + * + * This function is intended to be called by + * \c dd_function_table::BufferSubData. This function need not set GL error + * codes. The input parameters will have been tested before calling. + * + * \param ctx GL context. + * \param target Buffer object target on which to operate. + * \param offset Offset of the first byte to be modified. + * \param size Size, in bytes, of the data range. + * \param data Pointer to the data to store in the buffer object. + * \param bufObj Object to be used. + * + * \sa glBufferSubDataARB, dd_function_table::BufferSubData. + */ +void +_mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid * data, + struct gl_buffer_object * bufObj ) +{ + (void) ctx; (void) target; + + if (bufObj->Data && ((GLuint) (size + offset) <= bufObj->Size)) { + _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size ); + } +} + + +/** + * Retrieve data from a subrange of buffer object. If the data range + * specified by \c size + \c offset extends beyond the end of the buffer or + * if \c data is \c NULL, no copy is performed. + * + * This function is intended to be called by + * \c dd_function_table::BufferGetSubData. This function need not set GL error + * codes. The input parameters will have been tested before calling. + * + * \param ctx GL context. + * \param target Buffer object target on which to operate. + * \param offset Offset of the first byte to be modified. + * \param size Size, in bytes, of the data range. + * \param data Pointer to the data to store in the buffer object. + * \param bufObj Object to be used. + * + * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData. + */ +void +_mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, GLvoid * data, + struct gl_buffer_object * bufObj ) +{ + (void) ctx; (void) target; + + if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { + _mesa_memcpy( data, (GLubyte *) bufObj->Data + offset, size ); + } +} + + +/** + * Fallback function called via ctx->Driver.MapBuffer(). + * Hardware drivers that really implement buffer objects should never use + * function. + * + * The input parameters will have been already tested for errors. + * + * \param ctx GL context. + * \param target Buffer object target on which to operate. + * \param access Information about how the buffer will be accessed. + * \param bufObj Object to be mapped. + * \return A pointer to the object's internal data store that can be accessed + * by the processor + * + * \sa glMapBufferARB, dd_function_table::MapBuffer + */ +void * +_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, + struct gl_buffer_object *bufObj ) +{ + (void) ctx; + (void) target; + (void) access; + ASSERT(!bufObj->OnCard); + /* Just return a direct pointer to the data */ + if (bufObj->Pointer) { + /* already mapped! */ + return NULL; + } + bufObj->Pointer = bufObj->Data; + return bufObj->Pointer; +} + + +/** + * Fallback function called via ctx->Driver.MapBuffer(). + * Hardware drivers that really implement buffer objects should never use + * function. + * + * The input parameters will have been already tested for errors. + * + * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer + */ +GLboolean +_mesa_buffer_unmap( GLcontext *ctx, GLenum target, + struct gl_buffer_object *bufObj ) +{ + (void) ctx; + (void) target; + ASSERT(!bufObj->OnCard); + /* XXX we might assert here that bufObj->Pointer is non-null */ + bufObj->Pointer = NULL; + return GL_TRUE; +} + + +/** + * Initialize the state associated with buffer objects + */ +void +_mesa_init_buffer_objects( GLcontext *ctx ) +{ + GLuint i; + + /* Allocate the default buffer object and set refcount so high that + * it never gets deleted. + */ + ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0); + if (ctx->Array.NullBufferObj) + ctx->Array.NullBufferObj->RefCount = 1000; + + ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj; + ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj; + + /* Vertex array buffers */ + ctx->Array.Vertex.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.Normal.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.Color.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.SecondaryColor.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.FogCoord.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.Index.BufferObj = ctx->Array.NullBufferObj; + for (i = 0; i < MAX_TEXTURE_UNITS; i++) { + ctx->Array.TexCoord[i].BufferObj = ctx->Array.NullBufferObj; + } + ctx->Array.EdgeFlag.BufferObj = ctx->Array.NullBufferObj; + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + ctx->Array.VertexAttrib[i].BufferObj = ctx->Array.NullBufferObj; + } +} + + +/** + * When we're about to read pixel data out of a PBO (via glDrawPixels, + * glTexImage, etc) or write data into a PBO (via glReadPixels, + * glGetTexImage, etc) we call this function to check that we're not + * going to read out of bounds. + * + * XXX This would also be a convenient time to check that the PBO isn't + * currently mapped. Whoever calls this function should check for that. + * Remember, we can't use a PBO when it's mapped! + * + * \param width width of image to read/write + * \param height height of image to read/write + * \param depth depth of image to read/write + * \param format format of image to read/write + * \param type datatype of image to read/write + * \param ptr the user-provided pointer/offset + * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would + * go out of bounds. + */ +GLboolean +_mesa_validate_pbo_access(GLuint dimensions, + const struct gl_pixelstore_attrib *pack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *ptr) +{ + GLvoid *start, *end; + + ASSERT(pack->BufferObj->Name != 0); + + if (pack->BufferObj->Size == 0) + /* no buffer! */ + return GL_FALSE; + + /* get address of first pixel we'll read */ + start = _mesa_image_address(dimensions, pack, ptr, width, height, + format, type, 0, 0, 0); + + /* get address just past the last pixel we'll read */ + end = _mesa_image_address(dimensions, pack, ptr, width, height, + format, type, depth-1, height-1, width); + + + if ((const GLubyte *) start > (const GLubyte *)(uintptr_t) pack->BufferObj->Size) { + /* This will catch negative values / wrap-around */ + return GL_FALSE; + } + if ((const GLubyte *) end > (const GLubyte *)(uintptr_t) pack->BufferObj->Size) { + /* Image read goes beyond end of buffer */ + return GL_FALSE; + } + + /* OK! */ + return GL_TRUE; +} + + + + +/**********************************************************************/ +/* API Functions */ +/**********************************************************************/ + +void GLAPIENTRY +_mesa_BindBufferARB(GLenum target, GLuint buffer) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *oldBufObj; + struct gl_buffer_object *newBufObj = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + oldBufObj = buffer_object_get_target( ctx, target, "BindBufferARB" ); + if (oldBufObj && oldBufObj->Name == buffer) + return; /* rebinding the same buffer object- no change */ + + /* + * Get pointer to new buffer object (newBufObj) + */ + if (buffer == 0) { + /* The spec says there's not a buffer object named 0, but we use + * one internally because it simplifies things. + */ + newBufObj = ctx->Array.NullBufferObj; + } + else { + /* non-default buffer object */ + const struct _mesa_HashTable *hash = ctx->Shared->BufferObjects; + newBufObj = (struct gl_buffer_object *) _mesa_HashLookup(hash, buffer); + if (!newBufObj) { + /* if this is a new buffer object id, allocate a buffer object now */ + newBufObj = (*ctx->Driver.NewBufferObject)(ctx, buffer, target); + if (!newBufObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); + return; + } + _mesa_save_buffer_object(ctx, newBufObj); + } + newBufObj->RefCount++; + } + + switch (target) { + case GL_ARRAY_BUFFER_ARB: + ctx->Array.ArrayBufferObj = newBufObj; + break; + case GL_ELEMENT_ARRAY_BUFFER_ARB: + ctx->Array.ElementArrayBufferObj = newBufObj; + break; + case GL_PIXEL_PACK_BUFFER_EXT: + ctx->Pack.BufferObj = newBufObj; + break; + case GL_PIXEL_UNPACK_BUFFER_EXT: + ctx->Unpack.BufferObj = newBufObj; + break; + default: + _mesa_problem(ctx, "Bad target in _mesa_BindBufferARB"); + return; + } + + /* Pass BindBuffer call to device driver */ + if (ctx->Driver.BindBuffer && newBufObj) + (*ctx->Driver.BindBuffer)( ctx, target, newBufObj ); + + if (oldBufObj) { + oldBufObj->RefCount--; + assert(oldBufObj->RefCount >= 0); + if (oldBufObj->RefCount == 0) { + assert(oldBufObj->Name != 0); + ASSERT(ctx->Driver.DeleteBuffer); + ctx->Driver.DeleteBuffer( ctx, oldBufObj ); + } + } +} + + +/** + * Delete a set of buffer objects. + * + * \param n Number of buffer objects to delete. + * \param ids Array of \c n buffer object IDs. + */ +void GLAPIENTRY +_mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + GLsizei i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); + return; + } + + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + + for (i = 0; i < n; i++) { + if (ids[i] != 0) { + struct gl_buffer_object *bufObj = (struct gl_buffer_object *) + _mesa_HashLookup(ctx->Shared->BufferObjects, ids[i]); + if (bufObj) { + /* unbind any vertex pointers bound to this buffer */ + GLuint j; + + ASSERT(bufObj->Name == ids[i]); + + if (ctx->Array.Vertex.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Vertex.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.Normal.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Normal.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.Color.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Color.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.SecondaryColor.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.SecondaryColor.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.FogCoord.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.FogCoord.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.Index.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Index.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.EdgeFlag.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.EdgeFlag.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + for (j = 0; j < MAX_TEXTURE_UNITS; j++) { + if (ctx->Array.TexCoord[j].BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.TexCoord[j].BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + } + for (j = 0; j < VERT_ATTRIB_MAX; j++) { + if (ctx->Array.VertexAttrib[j].BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.VertexAttrib[j].BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + } + + if (ctx->Array.ArrayBufferObj == bufObj) { + _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); + } + if (ctx->Array.ElementArrayBufferObj == bufObj) { + _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); + } + + if (ctx->Pack.BufferObj == bufObj) { + _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 ); + } + if (ctx->Unpack.BufferObj == bufObj) { + _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); + } + + /* The ID is immediately freed for re-use */ + _mesa_remove_buffer_object(ctx, bufObj); + bufObj->RefCount--; + if (bufObj->RefCount <= 0) { + ASSERT(ctx->Array.ArrayBufferObj != bufObj); + ASSERT(ctx->Array.ElementArrayBufferObj != bufObj); + ASSERT(ctx->Array.Vertex.BufferObj != bufObj); + ASSERT(ctx->Driver.DeleteBuffer); + ctx->Driver.DeleteBuffer(ctx, bufObj); + } + } + } + } + + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); +} + + +/** + * Generate a set of unique buffer object IDs and store them in \c buffer. + * + * \param n Number of IDs to generate. + * \param buffer Array of \c n locations to store the IDs. + */ +void GLAPIENTRY +_mesa_GenBuffersARB(GLsizei n, GLuint *buffer) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + GLint i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); + return; + } + + if (!buffer) { + return; + } + + /* + * This must be atomic (generation and allocation of buffer object IDs) + */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); + + /* Allocate new, empty buffer objects and return identifiers */ + for (i = 0; i < n; i++) { + struct gl_buffer_object *bufObj; + GLuint name = first + i; + GLenum target = 0; + bufObj = (*ctx->Driver.NewBufferObject)( ctx, name, target ); + if (!bufObj) { + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB"); + return; + } + _mesa_save_buffer_object(ctx, bufObj); + buffer[i] = first + i; + } + + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); +} + + +/** + * Determine if ID is the name of a buffer object. + * + * \param id ID of the potential buffer object. + * \return \c GL_TRUE if \c id is the name of a buffer object, + * \c GL_FALSE otherwise. + */ +GLboolean GLAPIENTRY +_mesa_IsBufferARB(GLuint id) +{ + struct gl_buffer_object * bufObj; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (id == 0) + return GL_FALSE; + + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + bufObj = (struct gl_buffer_object *) _mesa_HashLookup(ctx->Shared->BufferObjects, id); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + return bufObj ? GL_TRUE : GL_FALSE; +} + + +void GLAPIENTRY +_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, + const GLvoid * data, GLenum usage) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (size < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); + return; + } + + switch (usage) { + case GL_STREAM_DRAW_ARB: + case GL_STREAM_READ_ARB: + case GL_STREAM_COPY_ARB: + case GL_STATIC_DRAW_ARB: + case GL_STATIC_READ_ARB: + case GL_STATIC_COPY_ARB: + case GL_DYNAMIC_DRAW_ARB: + case GL_DYNAMIC_READ_ARB: + case GL_DYNAMIC_COPY_ARB: + /* OK */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)"); + return; + } + + bufObj = buffer_object_get_target( ctx, target, "BufferDataARB" ); + if (!bufObj || bufObj->Name ==0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" ); + return; + } + + if (bufObj->Pointer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer is mapped)" ); + return; + } + + ASSERT(ctx->Driver.BufferData); + + /* Give the buffer object to the driver! <data> may be null! */ + (*ctx->Driver.BufferData)( ctx, target, size, data, usage, bufObj ); +} + + +void GLAPIENTRY +_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid * data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, + "BufferSubDataARB" ); + if (!bufObj) { + /* error already recorded */ + return; + } + + ASSERT(ctx->Driver.BufferSubData); + (*ctx->Driver.BufferSubData)( ctx, target, offset, size, data, bufObj ); +} + + +void GLAPIENTRY +_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, + GLsizeiptrARB size, void * data) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, + "GetBufferSubDataARB" ); + if (!bufObj) { + /* error already recorded */ + return; + } + + ASSERT(ctx->Driver.GetBufferSubData); + (*ctx->Driver.GetBufferSubData)( ctx, target, offset, size, data, bufObj ); +} + + +void * GLAPIENTRY +_mesa_MapBufferARB(GLenum target, GLenum access) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object * bufObj; + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); + + switch (access) { + case GL_READ_ONLY_ARB: + case GL_WRITE_ONLY_ARB: + case GL_READ_WRITE_ARB: + /* OK */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); + return NULL; + } + + bufObj = buffer_object_get_target( ctx, target, "MapBufferARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" ); + return NULL; + } + + if (bufObj->Pointer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); + return NULL; + } + + ASSERT(ctx->Driver.MapBuffer); + bufObj->Pointer = (*ctx->Driver.MapBuffer)( ctx, target, access, bufObj ); + if (!bufObj->Pointer) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)"); + } + + bufObj->Access = access; + + return bufObj->Pointer; +} + + +GLboolean GLAPIENTRY +_mesa_UnmapBufferARB(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + GLboolean status = GL_TRUE; + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + bufObj = buffer_object_get_target( ctx, target, "UnmapBufferARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" ); + return GL_FALSE; + } + + if (!bufObj->Pointer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); + return GL_FALSE; + } + + if (ctx->Driver.UnmapBuffer) { + status = (*ctx->Driver.UnmapBuffer)( ctx, target, bufObj ); + } + + bufObj->Access = GL_READ_WRITE_ARB; /* initial value, OK? */ + bufObj->Pointer = NULL; + + return status; +} + + +void GLAPIENTRY +_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + bufObj = buffer_object_get_target( ctx, target, "GetBufferParameterivARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" ); + return; + } + + switch (pname) { + case GL_BUFFER_SIZE_ARB: + *params = (GLint) bufObj->Size; + break; + case GL_BUFFER_USAGE_ARB: + *params = bufObj->Usage; + break; + case GL_BUFFER_ACCESS_ARB: + *params = bufObj->Access; + break; + case GL_BUFFER_MAPPED_ARB: + *params = (bufObj->Pointer != NULL); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object * bufObj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (pname != GL_BUFFER_MAP_POINTER_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); + return; + } + + bufObj = buffer_object_get_target( ctx, target, "GetBufferPointervARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" ); + return; + } + + *params = bufObj->Pointer; +} diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h new file mode 100644 index 00000000000..bc1005332ca --- /dev/null +++ b/src/mesa/main/bufferobj.h @@ -0,0 +1,124 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef BUFFEROBJ_H +#define BUFFEROBJ_H + + +#include "context.h" + + +/* + * Internal functions + */ + +extern void +_mesa_init_buffer_objects( GLcontext *ctx ); + +extern struct gl_buffer_object * +_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target ); + +extern void +_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ); + +extern void +_mesa_initialize_buffer_object( struct gl_buffer_object *obj, + GLuint name, GLenum target ); + +extern void +_mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj ); + +extern void +_mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ); + +extern void +_mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, + const GLvoid * data, GLenum usage, + struct gl_buffer_object * bufObj ); + +extern void +_mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid * data, + struct gl_buffer_object * bufObj ); + +extern void +_mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, GLvoid * data, + struct gl_buffer_object * bufObj ); + +extern void * +_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, + struct gl_buffer_object * bufObj ); + +extern GLboolean +_mesa_buffer_unmap( GLcontext *ctx, GLenum target, + struct gl_buffer_object * bufObj ); + +extern GLboolean +_mesa_validate_pbo_access(GLuint dimensions, + const struct gl_pixelstore_attrib *pack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *ptr); + + +/* + * API functions + */ + +extern void GLAPIENTRY +_mesa_BindBufferARB(GLenum target, GLuint buffer); + +extern void GLAPIENTRY +_mesa_DeleteBuffersARB(GLsizei n, const GLuint * buffer); + +extern void GLAPIENTRY +_mesa_GenBuffersARB(GLsizei n, GLuint * buffer); + +extern GLboolean GLAPIENTRY +_mesa_IsBufferARB(GLuint buffer); + +extern void GLAPIENTRY +_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); + +extern void GLAPIENTRY +_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data); + +extern void GLAPIENTRY +_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data); + +extern void * GLAPIENTRY +_mesa_MapBufferARB(GLenum target, GLenum access); + +extern GLboolean GLAPIENTRY +_mesa_UnmapBufferARB(GLenum target); + +extern void GLAPIENTRY +_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params); + +#endif diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c new file mode 100644 index 00000000000..58435e0edef --- /dev/null +++ b/src/mesa/main/buffers.c @@ -0,0 +1,723 @@ +/** + * \file buffers.c + * Frame buffer management. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "buffers.h" +#include "colormac.h" +#include "context.h" +#include "enums.h" +#include "fbobject.h" +#include "state.h" + + +#define BAD_MASK ~0u + + +#if _HAVE_FULL_GL +void GLAPIENTRY +_mesa_ClearIndex( GLfloat c ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->Color.ClearIndex == (GLuint) c) + return; + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.ClearIndex = (GLuint) c; + + if (!ctx->Visual.rgbMode && ctx->Driver.ClearIndex) { + /* it's OK to call glClearIndex in RGBA mode but it should be a NOP */ + (*ctx->Driver.ClearIndex)( ctx, ctx->Color.ClearIndex ); + } +} +#endif + + +/** + * Specify the clear values for the color buffers. + * + * \param red red color component. + * \param green green color component. + * \param blue blue color component. + * \param alpha alpha component. + * + * \sa glClearColor(). + * + * Clamps the parameters and updates gl_colorbuffer_attrib::ClearColor. On a + * change, flushes the vertices and notifies the driver via the + * dd_function_table::ClearColor callback. + */ +void GLAPIENTRY +_mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) +{ + GLfloat tmp[4]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + tmp[0] = CLAMP(red, 0.0F, 1.0F); + tmp[1] = CLAMP(green, 0.0F, 1.0F); + tmp[2] = CLAMP(blue, 0.0F, 1.0F); + tmp[3] = CLAMP(alpha, 0.0F, 1.0F); + + if (TEST_EQ_4V(tmp, ctx->Color.ClearColor)) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + COPY_4V(ctx->Color.ClearColor, tmp); + + if (ctx->Visual.rgbMode && ctx->Driver.ClearColor) { + /* it's OK to call glClearColor in CI mode but it should be a NOP */ + (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor); + } +} + + +/** + * Clear buffers. + * + * \param mask bit-mask indicating the buffers to be cleared. + * + * Flushes the vertices and verifies the parameter. If __GLcontextRec::NewState + * is set then calls _mesa_update_state() to update gl_frame_buffer::_Xmin, + * etc. If the rasterization mode is set to GL_RENDER then requests the driver + * to clear the buffers, via the dd_function_table::Clear callback. + */ +void GLAPIENTRY +_mesa_Clear( GLbitfield mask ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glClear 0x%x\n", mask); + + if (mask & ~(GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_ACCUM_BUFFER_BIT)) { + /* invalid bit set */ + _mesa_error( ctx, GL_INVALID_VALUE, "glClear(0x%x)", mask); + return; + } + + if (ctx->NewState) { + _mesa_update_state( ctx ); /* update _Xmin, etc */ + } + + if (ctx->RenderMode == GL_RENDER) { + const GLint x = ctx->DrawBuffer->_Xmin; + const GLint y = ctx->DrawBuffer->_Ymin; + const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + GLbitfield bufferMask; + + /* don't clear depth buffer if depth writing disabled */ + if (!ctx->Depth.Mask) + mask &= ~GL_DEPTH_BUFFER_BIT; + + /* Build the bitmask to send to device driver's Clear function. + * Note that the GL_COLOR_BUFFER_BIT flag will expand to 0, 1, 2 or 4 + * of the BUFFER_BIT_FRONT/BACK_LEFT/RIGHT flags, or one of the + * BUFFER_BIT_COLORn flags. + */ + bufferMask = 0; + if (mask & GL_COLOR_BUFFER_BIT) { + bufferMask |= ctx->DrawBuffer->_ColorDrawBufferMask[0]; + } + + if ((mask & GL_DEPTH_BUFFER_BIT) + && ctx->DrawBuffer->Visual.haveDepthBuffer) { + bufferMask |= BUFFER_BIT_DEPTH; + } + + if ((mask & GL_STENCIL_BUFFER_BIT) + && ctx->DrawBuffer->Visual.haveStencilBuffer) { + bufferMask |= BUFFER_BIT_STENCIL; + } + + if ((mask & GL_ACCUM_BUFFER_BIT) + && ctx->DrawBuffer->Visual.haveAccumBuffer) { + bufferMask |= BUFFER_BIT_ACCUM; + } + + ASSERT(ctx->Driver.Clear); + ctx->Driver.Clear( ctx, bufferMask, (GLboolean) !ctx->Scissor.Enabled, + x, y, width, height ); + } +} + + + +/** + * Return bitmask of BUFFER_BIT_* flags indicating which color buffers are + * available to the rendering context. + * This depends on the framebuffer we're writing to. For window system + * framebuffers we look at the framebuffer's visual. But for user- + * create framebuffers we look at the number of supported color attachments. + */ +static GLuint +supported_buffer_bitmask(const GLcontext *ctx, GLuint framebufferID) +{ + GLuint mask = 0x0; + GLint i; + + if (framebufferID > 0) { + /* A user-created renderbuffer */ + ASSERT(ctx->Extensions.EXT_framebuffer_object); + for (i = 0; i < ctx->Const.MaxColorAttachments; i++) { + mask |= (BUFFER_BIT_COLOR0 << i); + } + } + else { + /* A window system renderbuffer */ + mask = BUFFER_BIT_FRONT_LEFT; /* always have this */ + if (ctx->Visual.stereoMode) { + mask |= BUFFER_BIT_FRONT_RIGHT; + if (ctx->Visual.doubleBufferMode) { + mask |= BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; + } + } + else if (ctx->Visual.doubleBufferMode) { + mask |= BUFFER_BIT_BACK_LEFT; + } + + for (i = 0; i < ctx->Visual.numAuxBuffers; i++) { + mask |= (BUFFER_BIT_AUX0 << i); + } + } + + return mask; +} + + +/** + * Helper routine used by glDrawBuffer and glDrawBuffersARB. + * Given a GLenum naming one or more color buffers (such as + * GL_FRONT_AND_BACK), return the corresponding bitmask of BUFFER_BIT_* flags. + */ +static GLuint +draw_buffer_enum_to_bitmask(GLenum buffer) +{ + switch (buffer) { + case GL_NONE: + return 0; + case GL_FRONT: + return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT; + case GL_BACK: + return BUFFER_BIT_BACK_LEFT | BUFFER_BIT_BACK_RIGHT; + case GL_RIGHT: + return BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; + case GL_FRONT_RIGHT: + return BUFFER_BIT_FRONT_RIGHT; + case GL_BACK_RIGHT: + return BUFFER_BIT_BACK_RIGHT; + case GL_BACK_LEFT: + return BUFFER_BIT_BACK_LEFT; + case GL_FRONT_AND_BACK: + return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT + | BUFFER_BIT_FRONT_RIGHT | BUFFER_BIT_BACK_RIGHT; + case GL_LEFT: + return BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT; + case GL_FRONT_LEFT: + return BUFFER_BIT_FRONT_LEFT; + case GL_AUX0: + return BUFFER_BIT_AUX0; + case GL_AUX1: + return BUFFER_BIT_AUX1; + case GL_AUX2: + return BUFFER_BIT_AUX2; + case GL_AUX3: + return BUFFER_BIT_AUX3; + case GL_COLOR_ATTACHMENT0_EXT: + return BUFFER_BIT_COLOR0; + case GL_COLOR_ATTACHMENT1_EXT: + return BUFFER_BIT_COLOR1; + case GL_COLOR_ATTACHMENT2_EXT: + return BUFFER_BIT_COLOR2; + case GL_COLOR_ATTACHMENT3_EXT: + return BUFFER_BIT_COLOR3; + default: + /* error */ + return BAD_MASK; + } +} + + +/** + * Helper routine used by glReadBuffer. + * Given a GLenum naming (a) color buffer(s), return the corresponding + * bitmask of DD_* flags. + */ +static GLuint +read_buffer_enum_to_bitmask(GLenum buffer) +{ + switch (buffer) { + case GL_FRONT: + return BUFFER_BIT_FRONT_LEFT; + case GL_BACK: + return BUFFER_BIT_BACK_LEFT; + case GL_RIGHT: + return BUFFER_BIT_FRONT_RIGHT; + case GL_FRONT_RIGHT: + return BUFFER_BIT_FRONT_RIGHT; + case GL_BACK_RIGHT: + return BUFFER_BIT_BACK_RIGHT; + case GL_BACK_LEFT: + return BUFFER_BIT_BACK_LEFT; + case GL_LEFT: + return BUFFER_BIT_FRONT_LEFT; + case GL_FRONT_LEFT: + return BUFFER_BIT_FRONT_LEFT; + case GL_AUX0: + return BUFFER_BIT_AUX0; + case GL_AUX1: + return BUFFER_BIT_AUX1; + case GL_AUX2: + return BUFFER_BIT_AUX2; + case GL_AUX3: + return BUFFER_BIT_AUX3; + case GL_COLOR_ATTACHMENT0_EXT: + return BUFFER_BIT_COLOR0; + case GL_COLOR_ATTACHMENT1_EXT: + return BUFFER_BIT_COLOR1; + case GL_COLOR_ATTACHMENT2_EXT: + return BUFFER_BIT_COLOR2; + case GL_COLOR_ATTACHMENT3_EXT: + return BUFFER_BIT_COLOR3; + default: + /* error */ + return BAD_MASK; + } +} + + +/** + * Specify which color buffers to draw into. + * + * \param buffer color buffer, such as GL_LEFT or GL_FRONT_AND_BACK. + * + * Flushes the vertices and verifies the parameter and updates the + * gl_colorbuffer_attrib::_DrawDestMask bitfield. Marks new color state in + * __GLcontextRec::NewState and notifies the driver via the + * dd_function_table::DrawBuffer callback. + */ +void GLAPIENTRY +_mesa_DrawBuffer(GLenum buffer) +{ + GLuint bufferID; + GLuint destMask; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex... */ + + if (MESA_VERBOSE & VERBOSE_API) { + _mesa_debug(ctx, "glDrawBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + } + + bufferID = ctx->DrawBuffer->Name; + + if (buffer == GL_NONE) { + destMask = 0x0; + } + else { + const GLuint supportedMask = supported_buffer_bitmask(ctx, bufferID); + destMask = draw_buffer_enum_to_bitmask(buffer); + if (destMask == BAD_MASK) { + /* totally bogus buffer */ + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffer(buffer)"); + return; + } + destMask &= supportedMask; + if (destMask == 0x0) { + /* none of the named color buffers exist! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffer(buffer)"); + return; + } + } + + /* if we get here, there's no error so set new state */ + _mesa_drawbuffers(ctx, 1, &buffer, &destMask); +} + + +/** + * Called by glDrawBuffersARB; specifies the destination color buffers + * for N fragment program color outputs. + * + * XXX This function is called by _mesa_PopAttrib() and we need to do + * some more work to deal with the current framebuffer binding state! + */ +void GLAPIENTRY +_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers) +{ + GLint output; + GLuint usedBufferMask, supportedMask; + GLuint bufferID; + GLuint destMask[MAX_DRAW_BUFFERS]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (!ctx->Extensions.ARB_draw_buffers) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB"); + return; + } + if (n < 1 || n > (GLsizei) ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)"); + return; + } + + bufferID = ctx->DrawBuffer->Name; + + supportedMask = supported_buffer_bitmask(ctx, bufferID); + usedBufferMask = 0x0; + + /* complicated error checking... */ + for (output = 0; output < n; output++) { + if (buffers[output] == GL_NONE) { + destMask[output] = 0x0; + } + else { + destMask[output] = draw_buffer_enum_to_bitmask(buffers[output]); + if (destMask[output] == BAD_MASK + || _mesa_bitcount(destMask[output]) > 1) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)"); + return; + } + destMask[output] &= supportedMask; + if (destMask[output] == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawBuffersARB(unsupported buffer)"); + return; + } + if (destMask[output] & usedBufferMask) { + /* can't specify a dest buffer more than once! */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawBuffersARB(duplicated buffer)"); + return; + } + + /* update bitmask */ + usedBufferMask |= destMask[output]; + } + } + + /* OK, if we get here, there were no errors so set the new state */ + _mesa_drawbuffers(ctx, n, buffers, destMask); +} + + +/** + * Set color output state. Traditionally, there was only one color + * output, but fragment programs can now have several distinct color + * outputs (see GL_ARB_draw_buffers). This function sets the state + * for one such color output. + */ +static void +set_color_output(GLcontext *ctx, GLuint output, GLenum buffer, GLuint destMask) +{ + struct gl_framebuffer *fb = ctx->DrawBuffer; + + ASSERT(output < ctx->Const.MaxDrawBuffers); + + fb->ColorDrawBuffer[output] = buffer; + fb->_ColorDrawBufferMask[output] = destMask; + + if (fb->Name == 0) { + /* Set traditional state var */ + ctx->Color.DrawBuffer[output] = buffer; + } + + /* not really needed, will be set later */ + fb->_NumColorDrawBuffers[output] = 0; +} + + +/** + * Helper routine used by _mesa_DrawBuffer, _mesa_DrawBuffersARB and + * _mesa_PopAttrib to set drawbuffer state. + */ +void +_mesa_drawbuffers(GLcontext *ctx, GLsizei n, const GLenum *buffers, + const GLuint *destMask) +{ + GLuint mask[MAX_DRAW_BUFFERS]; + GLint output; + + if (!destMask) { + /* compute destMask values now */ + const GLuint bufferID = ctx->DrawBuffer->Name; + const GLuint supportedMask = supported_buffer_bitmask(ctx, bufferID); + for (output = 0; output < n; output++) { + mask[output] = draw_buffer_enum_to_bitmask(buffers[output]); + ASSERT(mask[output] != BAD_MASK); + mask[output] &= supportedMask; + } + destMask = mask; + } + + for (output = 0; output < n; output++) { + set_color_output(ctx, output, buffers[output], destMask[output]); + } + + /* set remaining color outputs to NONE */ + for (output = n; output < ctx->Const.MaxDrawBuffers; output++) { + set_color_output(ctx, output, GL_NONE, 0x0); + } + + ctx->NewState |= _NEW_COLOR; + + /* + * Call device driver function. + */ + if (ctx->Driver.DrawBuffers) + ctx->Driver.DrawBuffers(ctx, n, buffers); + else if (ctx->Driver.DrawBuffer) + ctx->Driver.DrawBuffer(ctx, buffers[0]); +} + + + +/** + * Set the color buffer source for reading pixels. + * + * \param mode color buffer. + * + * \sa glReadBuffer(). + * + */ +void GLAPIENTRY +_mesa_ReadBuffer(GLenum buffer) +{ + struct gl_framebuffer *fb; + GLuint srcMask, supportedMask; + GLuint bufferID; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + fb = ctx->ReadBuffer; + bufferID = fb->Name; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); + + if (bufferID > 0 && buffer == GL_NONE) { + /* legal! */ + srcMask = 0x0; + } + else { + /* general case */ + srcMask = read_buffer_enum_to_bitmask(buffer); + if (srcMask == BAD_MASK) { + _mesa_error(ctx, GL_INVALID_ENUM, "glReadBuffer(buffer)"); + return; + } + supportedMask = supported_buffer_bitmask(ctx, bufferID); + if ((srcMask & supportedMask) == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glReadBuffer(buffer)"); + return; + } + } + + if (bufferID == 0) { + ctx->Pixel.ReadBuffer = buffer; + } + fb->ColorReadBuffer = buffer; + fb->_ColorReadBufferMask = srcMask; + + ctx->NewState |= _NEW_PIXEL; + + /* + * Call device driver function. + */ + if (ctx->Driver.ReadBuffer) + (*ctx->Driver.ReadBuffer)(ctx, buffer); +} + + +#if _HAVE_FULL_GL + +/** + * GL_MESA_resize_buffers extension. + * + * When this function is called, we'll ask the window system how large + * the current window is. If it's a new size, we'll call the driver's + * ResizeBuffers function. The driver will then resize its color buffers + * as needed, and maybe call the swrast's routine for reallocating + * swrast-managed depth/stencil/accum/etc buffers. + * \note This function may be called from within Mesa or called by the + * user directly (see the GL_MESA_resize_buffers extension). + */ +void GLAPIENTRY +_mesa_ResizeBuffersMESA( void ) +{ + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glResizeBuffersMESA\n"); + + if (ctx->DrawBuffer && ctx->DrawBuffer->Name == 0) { + GLuint newWidth, newHeight; + GLframebuffer *buffer = ctx->DrawBuffer; + + /* ask device driver for size of output buffer */ + ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); + + /* see if size of device driver's color buffer (window) has changed */ + if (buffer->Width != newWidth || buffer->Height != newHeight) { + if (ctx->Driver.ResizeBuffers) + ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); + } + } + + if (ctx->ReadBuffer && ctx->ReadBuffer != ctx->DrawBuffer + && ctx->ReadBuffer->Name == 0) { + GLuint newWidth, newHeight; + GLframebuffer *buffer = ctx->ReadBuffer; + + /* ask device driver for size of read buffer */ + ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); + + /* see if size of device driver's color buffer (window) has changed */ + if (buffer->Width != newWidth || buffer->Height != newHeight) { + if (ctx->Driver.ResizeBuffers) + ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); + } + } + + ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ +} + + +/* + * XXX move somewhere else someday? + */ +void GLAPIENTRY +_mesa_SampleCoverageARB(GLclampf value, GLboolean invert) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_multisample) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleCoverageARB"); + return; + } + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); + ctx->Multisample.SampleCoverageValue = (GLfloat) CLAMP(value, 0.0, 1.0); + ctx->Multisample.SampleCoverageInvert = invert; + ctx->NewState |= _NEW_MULTISAMPLE; +} + +#endif /* _HAVE_FULL_GL */ + + + +/** + * Define the scissor box. + * + * \param x, y coordinates of the scissor box lower-left corner. + * \param width width of the scissor box. + * \param height height of the scissor box. + * + * \sa glScissor(). + * + * Verifies the parameters and updates __GLcontextRec::Scissor. On a + * change flushes the vertices and notifies the driver via + * the dd_function_table::Scissor callback. + */ +void GLAPIENTRY +_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" ); + return; + } + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height); + + if (x == ctx->Scissor.X && + y == ctx->Scissor.Y && + width == ctx->Scissor.Width && + height == ctx->Scissor.Height) + return; + + FLUSH_VERTICES(ctx, _NEW_SCISSOR); + ctx->Scissor.X = x; + ctx->Scissor.Y = y; + ctx->Scissor.Width = width; + ctx->Scissor.Height = height; + + if (ctx->Driver.Scissor) + ctx->Driver.Scissor( ctx, x, y, width, height ); +} + + + +/**********************************************************************/ +/** \name Initialization */ +/*@{*/ + +/** + * Initialize the context's scissor state. + * \param ctx the GL context. + */ +void +_mesa_init_scissor(GLcontext *ctx) +{ + /* Scissor group */ + ctx->Scissor.Enabled = GL_FALSE; + ctx->Scissor.X = 0; + ctx->Scissor.Y = 0; + ctx->Scissor.Width = 0; + ctx->Scissor.Height = 0; +} + + +/** + * Initialize the context's multisample state. + * \param ctx the GL context. + */ +void +_mesa_init_multisample(GLcontext *ctx) +{ + ctx->Multisample.Enabled = GL_FALSE; + ctx->Multisample.SampleAlphaToCoverage = GL_FALSE; + ctx->Multisample.SampleAlphaToOne = GL_FALSE; + ctx->Multisample.SampleCoverage = GL_FALSE; + ctx->Multisample.SampleCoverageValue = 1.0; + ctx->Multisample.SampleCoverageInvert = GL_FALSE; +} + +/*@}*/ diff --git a/src/mesa/main/buffers.h b/src/mesa/main/buffers.h new file mode 100644 index 00000000000..0c7f68ee79e --- /dev/null +++ b/src/mesa/main/buffers.h @@ -0,0 +1,78 @@ +/** + * \file buffers.h + * Frame buffer management functions declarations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef BUFFERS_H +#define BUFFERS_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_ClearIndex( GLfloat c ); + +extern void GLAPIENTRY +_mesa_ClearColor( GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ); + +extern void GLAPIENTRY +_mesa_Clear( GLbitfield mask ); + +extern void GLAPIENTRY +_mesa_DrawBuffer( GLenum mode ); + +extern void GLAPIENTRY +_mesa_DrawBuffersARB(GLsizei n, const GLenum *buffers); + +extern void +_mesa_drawbuffers(GLcontext *ctx, GLsizei n, const GLenum *buffers, + const GLuint *destMask); + +extern void GLAPIENTRY +_mesa_ReadBuffer( GLenum mode ); + +extern void GLAPIENTRY +_mesa_ResizeBuffersMESA( void ); + +extern void GLAPIENTRY +_mesa_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ); + +extern void GLAPIENTRY +_mesa_SampleCoverageARB(GLclampf value, GLboolean invert); + +extern void +_mesa_init_scissor(GLcontext *ctx); + +extern void +_mesa_init_multisample(GLcontext *ctx); + + +#endif diff --git a/src/mesa/main/clip.c b/src/mesa/main/clip.c new file mode 100644 index 00000000000..43ef55ee3b5 --- /dev/null +++ b/src/mesa/main/clip.c @@ -0,0 +1,160 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "clip.h" +#include "context.h" +#include "macros.h" +#include "mtypes.h" + +#include "math/m_xform.h" +#include "math/m_matrix.h" + + + +/**********************************************************************/ +/* Get/Set User clip-planes. */ +/**********************************************************************/ + + + +void GLAPIENTRY +_mesa_ClipPlane( GLenum plane, const GLdouble *eq ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint p; + GLfloat equation[4]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + p = (GLint) plane - (GLint) GL_CLIP_PLANE0; + if (p < 0 || p >= (GLint) ctx->Const.MaxClipPlanes) { + _mesa_error( ctx, GL_INVALID_ENUM, "glClipPlane" ); + return; + } + + equation[0] = (GLfloat) eq[0]; + equation[1] = (GLfloat) eq[1]; + equation[2] = (GLfloat) eq[2]; + equation[3] = (GLfloat) eq[3]; + + /* + * The equation is transformed by the transpose of the inverse of the + * current modelview matrix and stored in the resulting eye coordinates. + * + * KW: Eqn is then transformed to the current clip space, where user + * clipping now takes place. The clip-space equations are recalculated + * whenever the projection matrix changes. + */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + + _mesa_transform_vector( equation, equation, + ctx->ModelviewMatrixStack.Top->inv ); + + if (TEST_EQ_4V(ctx->Transform.EyeUserPlane[p], equation)) + return; + + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + COPY_4FV(ctx->Transform.EyeUserPlane[p], equation); + + /* Update derived state. This state also depends on the projection + * matrix, and is recalculated on changes to the projection matrix by + * code in _mesa_update_state(). + */ + if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { + if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top)) + _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); + + _mesa_transform_vector( ctx->Transform._ClipUserPlane[p], + ctx->Transform.EyeUserPlane[p], + ctx->ProjectionMatrixStack.Top->inv ); + } + + if (ctx->Driver.ClipPlane) + ctx->Driver.ClipPlane( ctx, plane, equation ); +} + + +void GLAPIENTRY +_mesa_GetClipPlane( GLenum plane, GLdouble *equation ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint p; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + p = (GLint) (plane - GL_CLIP_PLANE0); + if (p < 0 || p >= (GLint) ctx->Const.MaxClipPlanes) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" ); + return; + } + + equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0]; + equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1]; + equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2]; + equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3]; +} + +void GLAPIENTRY +_mesa_CullParameterfvEXT (GLenum cap, GLfloat *v) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (cap) { + case GL_CULL_VERTEX_EYE_POSITION_EXT: + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + COPY_4FV(ctx->Transform.CullEyePos, v); + + _mesa_transform_vector( ctx->Transform.CullObjPos, + ctx->Transform.CullEyePos, + ctx->ModelviewMatrixStack.Top->inv ); + break; + + case GL_CULL_VERTEX_OBJECT_POSITION_EXT: + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + COPY_4FV(ctx->Transform.CullObjPos, v); + + _mesa_transform_vector( ctx->Transform.CullEyePos, + ctx->Transform.CullObjPos, + ctx->ModelviewMatrixStack.Top->m ); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glCullParameterfvEXT" ); + } +} + +void GLAPIENTRY +_mesa_CullParameterdvEXT (GLenum cap, GLdouble *v) +{ + GLfloat f[4]; + + f[0] = (GLfloat)v[0]; + f[1] = (GLfloat)v[1]; + f[2] = (GLfloat)v[2]; + f[3] = (GLfloat)v[3]; + + _mesa_CullParameterfvEXT(cap, f); +} + diff --git a/src/mesa/main/clip.h b/src/mesa/main/clip.h new file mode 100644 index 00000000000..d53afb45bdf --- /dev/null +++ b/src/mesa/main/clip.h @@ -0,0 +1,49 @@ +/** + * \file clip.h + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef CLIP_H +#define CLIP_H + +#include "mtypes.h" + +extern void GLAPIENTRY +_mesa_ClipPlane( GLenum plane, const GLdouble *equation ); + +extern void GLAPIENTRY +_mesa_GetClipPlane( GLenum plane, GLdouble *equation ); + +extern void GLAPIENTRY +_mesa_CullParameterfvEXT (GLenum cap, GLfloat *v); + +extern void GLAPIENTRY +_mesa_CullParameterdvEXT (GLenum cap, GLdouble *v); + + +#endif diff --git a/src/mesa/main/colormac.h b/src/mesa/main/colormac.h new file mode 100644 index 00000000000..a19521fc85b --- /dev/null +++ b/src/mesa/main/colormac.h @@ -0,0 +1,227 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file colormac.h + * Color-related macros + */ + + +#ifndef COLORMAC_H +#define COLORMAC_H + + +#include "imports.h" +#include "config.h" +#include "macros.h" + + +/** \def BYTE_TO_CHAN + * Convert from GLbyte to GLchan */ + +/** \def UBYTE_TO_CHAN + * Convert from GLubyte to GLchan */ + +/** \def SHORT_TO_CHAN + * Convert from GLshort to GLchan */ + +/** \def USHORT_TO_CHAN + * Convert from GLushort to GLchan */ + +/** \def INT_TO_CHAN + * Convert from GLint to GLchan */ + +/** \def UINT_TO_CHAN + * Convert from GLuint to GLchan */ + +/** \def CHAN_TO_UBYTE + * Convert from GLchan to GLubyte */ + +/** \def CHAN_TO_FLOAT + * Convert from GLchan to GLfloat */ + +/** \def CLAMPED_FLOAT_TO_CHAN + * Convert from GLclampf to GLchan */ + +/** \def UNCLAMPED_FLOAT_TO_CHAN + * Convert from GLfloat to GLchan */ + +/** \def COPY_CHAN4 + * Copy a GLchan[4] array */ + +/** \def CHAN_PRODUCT + * Scaled product (usually approximated) between two GLchan arguments */ + +#if CHAN_BITS == 8 + +#define BYTE_TO_CHAN(b) ((b) < 0 ? 0 : (GLchan) (b)) +#define UBYTE_TO_CHAN(b) (b) +#define SHORT_TO_CHAN(s) ((s) < 0 ? 0 : (GLchan) ((s) >> 7)) +#define USHORT_TO_CHAN(s) ((GLchan) ((s) >> 8)) +#define INT_TO_CHAN(i) ((i) < 0 ? 0 : (GLchan) ((i) >> 23)) +#define UINT_TO_CHAN(i) ((GLchan) ((i) >> 24)) + +#define CHAN_TO_UBYTE(c) (c) +#define CHAN_TO_FLOAT(c) UBYTE_TO_FLOAT(c) + +#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_UBYTE(c, f) +#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_UBYTE(c, f) + +#define COPY_CHAN4(DST, SRC) COPY_4UBV(DST, SRC) + +#define CHAN_PRODUCT(a, b) ((GLubyte) (((GLint)(a) * ((GLint)(b) + 1)) >> 8)) + +#elif CHAN_BITS == 16 + +#define BYTE_TO_CHAN(b) ((b) < 0 ? 0 : (((GLchan) (b)) * 516)) +#define UBYTE_TO_CHAN(b) ((((GLchan) (b)) << 8) | ((GLchan) (b))) +#define SHORT_TO_CHAN(s) ((s) < 0 ? 0 : (GLchan) (s)) +#define USHORT_TO_CHAN(s) (s) +#define INT_TO_CHAN(i) ((i) < 0 ? 0 : (GLchan) ((i) >> 15)) +#define UINT_TO_CHAN(i) ((GLchan) ((i) >> 16)) + +#define CHAN_TO_UBYTE(c) ((c) >> 8) +#define CHAN_TO_FLOAT(c) ((GLfloat) ((c) * (1.0 / CHAN_MAXF))) + +#define CLAMPED_FLOAT_TO_CHAN(c, f) CLAMPED_FLOAT_TO_USHORT(c, f) +#define UNCLAMPED_FLOAT_TO_CHAN(c, f) UNCLAMPED_FLOAT_TO_USHORT(c, f) + +#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC) + +#define CHAN_PRODUCT(a, b) ((GLchan) ((((GLuint) (a)) * ((GLuint) (b))) / 65535)) + +#elif CHAN_BITS == 32 + +/* XXX floating-point color channels not fully thought-out */ +#define BYTE_TO_CHAN(b) ((GLfloat) ((b) * (1.0F / 127.0F))) +#define UBYTE_TO_CHAN(b) ((GLfloat) ((b) * (1.0F / 255.0F))) +#define SHORT_TO_CHAN(s) ((GLfloat) ((s) * (1.0F / 32767.0F))) +#define USHORT_TO_CHAN(s) ((GLfloat) ((s) * (1.0F / 65535.0F))) +#define INT_TO_CHAN(i) ((GLfloat) ((i) * (1.0F / 2147483647.0F))) +#define UINT_TO_CHAN(i) ((GLfloat) ((i) * (1.0F / 4294967295.0F))) + +#define CHAN_TO_UBYTE(c) FLOAT_TO_UBYTE(c) +#define CHAN_TO_FLOAT(c) (c) + +#define CLAMPED_FLOAT_TO_CHAN(c, f) c = (f) +#define UNCLAMPED_FLOAT_TO_CHAN(c, f) c = (f) + +#define COPY_CHAN4(DST, SRC) COPY_4V(DST, SRC) + +#define CHAN_PRODUCT(a, b) ((a) * (b)) + +#else + +#error unexpected CHAN_BITS size + +#endif + + +/** + * Convert 3 channels at once. + * + * \param dst pointer to destination GLchan[3] array. + * \param f pointer to source GLfloat[3] array. + * + * \sa #UNCLAMPED_FLOAT_TO_CHAN. + */ +#define UNCLAMPED_FLOAT_TO_RGB_CHAN(dst, f) \ +do { \ + UNCLAMPED_FLOAT_TO_CHAN(dst[0], f[0]); \ + UNCLAMPED_FLOAT_TO_CHAN(dst[1], f[1]); \ + UNCLAMPED_FLOAT_TO_CHAN(dst[2], f[2]); \ +} while (0) + + +/** + * Convert 4 channels at once. + * + * \param dst pointer to destination GLchan[4] array. + * \param f pointer to source GLfloat[4] array. + * + * \sa #UNCLAMPED_FLOAT_TO_CHAN. + */ +#define UNCLAMPED_FLOAT_TO_RGBA_CHAN(dst, f) \ +do { \ + UNCLAMPED_FLOAT_TO_CHAN(dst[0], f[0]); \ + UNCLAMPED_FLOAT_TO_CHAN(dst[1], f[1]); \ + UNCLAMPED_FLOAT_TO_CHAN(dst[2], f[2]); \ + UNCLAMPED_FLOAT_TO_CHAN(dst[3], f[3]); \ +} while (0) + + + +/** + * \name Generic color packing macros. All inputs should be GLubytes. + * + * \todo We may move these into texstore.h at some point. + */ +/*@{*/ + +#define PACK_COLOR_8888( R, G, B, A ) \ + (((R) << 24) | ((G) << 16) | ((B) << 8) | (A)) + +#define PACK_COLOR_8888_REV( R, G, B, A ) \ + (((A) << 24) | ((B) << 16) | ((G) << 8) | (R)) + +#define PACK_COLOR_888( R, G, B ) \ + (((R) << 16) | ((G) << 8) | (B)) + +#define PACK_COLOR_565( R, G, B ) \ + ((((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | (((B) & 0xf8) >> 3)) + +#define PACK_COLOR_565_REV( R, G, B ) \ + (((R) & 0xf8) | ((G) & 0xe0) >> 5 | (((G) & 0x1c) << 11) | (((B) & 0xf8) << 5)) + +#define PACK_COLOR_1555( A, B, G, R ) \ + ((((B) & 0xf8) << 7) | (((G) & 0xf8) << 2) | (((R) & 0xf8) >> 3) | \ + ((A) ? 0x8000 : 0)) + +#define PACK_COLOR_1555_REV( A, B, G, R ) \ + ((((B) & 0xf8) >> 1) | (((G) & 0xc0) >> 6) | (((G) & 0x38) << 10) | (((R) & 0xf8) << 5) | \ + ((A) ? 0x80 : 0)) + +#define PACK_COLOR_4444( R, G, B, A ) \ + ((((R) & 0xf0) << 8) | (((G) & 0xf0) << 4) | ((B) & 0xf0) | ((A) >> 4)) + +#define PACK_COLOR_4444_REV( R, G, B, A ) \ + ((((B) & 0xf0) << 8) | (((A) & 0xf0) << 4) | ((R) & 0xf0) | ((G) >> 4)) + +#define PACK_COLOR_88( L, A ) \ + (((L) << 8) | (A)) + +#define PACK_COLOR_88_REV( L, A ) \ + (((A) << 8) | (L)) + +#define PACK_COLOR_332( R, G, B ) \ + (((R) & 0xe0) | (((G) & 0xe0) >> 3) | (((B) & 0xc0) >> 6)) + +#define PACK_COLOR_233( B, G, R ) \ + (((B) & 0xc0) | (((G) & 0xe0) >> 2) | (((R) & 0xe0) >> 5)) + +/*@}*/ + + +#endif /* COLORMAC_H */ diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c new file mode 100644 index 00000000000..4f0801578ce --- /dev/null +++ b/src/mesa/main/colortab.c @@ -0,0 +1,1445 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "bufferobj.h" +#include "colortab.h" +#include "context.h" +#include "image.h" +#include "macros.h" +#include "state.h" + + +/* + * Given an internalFormat token passed to glColorTable, + * return the corresponding base format. + * Return -1 if invalid token. + */ +static GLint +base_colortab_format( GLenum format ) +{ + switch (format) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return GL_ALPHA; + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return GL_INTENSITY; + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + default: + return -1; /* error */ + } +} + + + +/* + * Examine table's format and set the component sizes accordingly. + */ +static void +set_component_sizes( struct gl_color_table *table ) +{ + GLubyte sz; + + switch (table->Type) { + case GL_UNSIGNED_BYTE: + sz = 8 * sizeof(GLubyte); + break; + case GL_UNSIGNED_SHORT: + sz = 8 * sizeof(GLushort); + break; + case GL_FLOAT: + /* Don't actually return 32 here since that causes the conformance + * tests to blow up. Conform thinks the component is an integer, + * not a float. + */ + sz = 8; /** 8 * sizeof(GLfloat); **/ + break; + default: + _mesa_problem(NULL, "bad color table type in set_component_sizes 0x%x", table->Type); + return; + } + + switch (table->Format) { + case GL_ALPHA: + table->RedSize = 0; + table->GreenSize = 0; + table->BlueSize = 0; + table->AlphaSize = sz; + table->IntensitySize = 0; + table->LuminanceSize = 0; + break; + case GL_LUMINANCE: + table->RedSize = 0; + table->GreenSize = 0; + table->BlueSize = 0; + table->AlphaSize = 0; + table->IntensitySize = 0; + table->LuminanceSize = sz; + break; + case GL_LUMINANCE_ALPHA: + table->RedSize = 0; + table->GreenSize = 0; + table->BlueSize = 0; + table->AlphaSize = sz; + table->IntensitySize = 0; + table->LuminanceSize = sz; + break; + case GL_INTENSITY: + table->RedSize = 0; + table->GreenSize = 0; + table->BlueSize = 0; + table->AlphaSize = 0; + table->IntensitySize = sz; + table->LuminanceSize = 0; + break; + case GL_RGB: + table->RedSize = sz; + table->GreenSize = sz; + table->BlueSize = sz; + table->AlphaSize = 0; + table->IntensitySize = 0; + table->LuminanceSize = 0; + break; + case GL_RGBA: + table->RedSize = sz; + table->GreenSize = sz; + table->BlueSize = sz; + table->AlphaSize = sz; + table->IntensitySize = 0; + table->LuminanceSize = 0; + break; + default: + _mesa_problem(NULL, "unexpected format in set_component_sizes"); + } +} + + + +/** + * Update/replace all or part of a color table. Helper function + * used by _mesa_ColorTable() and _mesa_ColorSubTable(). + * The table->Table buffer should already be allocated. + * \param start first entry to update + * \param count number of entries to update + * \param format format of user-provided table data + * \param type datatype of user-provided table data + * \param data user-provided table data + * \param [rgba]Scale - RGBA scale factors + * \param [rgba]Bias - RGBA bias factors + */ +static void +store_colortable_entries(GLcontext *ctx, struct gl_color_table *table, + GLsizei start, GLsizei count, + GLenum format, GLenum type, const GLvoid *data, + GLfloat rScale, GLfloat rBias, + GLfloat gScale, GLfloat gBias, + GLfloat bScale, GLfloat bBias, + GLfloat aScale, GLfloat aBias) +{ + if (ctx->Unpack.BufferObj->Name) { + /* Get/unpack the color table data from a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Unpack, count, 1, 1, + format, type, data)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glColor[Sub]Table(bad PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glColor[Sub]Table(PBO mapped)"); + return; + } + data = ADD_POINTERS(buf, data); + } + + + if (table->Type == GL_FLOAT) { + /* convert user-provided data to GLfloat values */ + GLfloat tempTab[MAX_COLOR_TABLE_SIZE * 4]; + GLfloat *tableF; + GLint i; + + _mesa_unpack_color_span_float(ctx, + count, /* number of pixels */ + table->Format, /* dest format */ + tempTab, /* dest address */ + format, type, /* src format/type */ + data, /* src data */ + &ctx->Unpack, + IMAGE_CLAMP_BIT); /* transfer ops */ + + /* the destination */ + tableF = (GLfloat *) table->Table; + + /* Apply scale & bias & clamp now */ + switch (table->Format) { + case GL_INTENSITY: + for (i = 0; i < count; i++) { + GLuint j = start + i; + tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); + } + break; + case GL_LUMINANCE: + for (i = 0; i < count; i++) { + GLuint j = start + i; + tableF[j] = CLAMP(tempTab[i] * rScale + rBias, 0.0F, 1.0F); + } + break; + case GL_ALPHA: + for (i = 0; i < count; i++) { + GLuint j = start + i; + tableF[j] = CLAMP(tempTab[i] * aScale + aBias, 0.0F, 1.0F); + } + break; + case GL_LUMINANCE_ALPHA: + for (i = 0; i < count; i++) { + GLuint j = start + i; + tableF[j*2+0] = CLAMP(tempTab[i*2+0] * rScale + rBias, 0.0F, 1.0F); + tableF[j*2+1] = CLAMP(tempTab[i*2+1] * aScale + aBias, 0.0F, 1.0F); + } + break; + case GL_RGB: + for (i = 0; i < count; i++) { + GLuint j = start + i; + tableF[j*3+0] = CLAMP(tempTab[i*3+0] * rScale + rBias, 0.0F, 1.0F); + tableF[j*3+1] = CLAMP(tempTab[i*3+1] * gScale + gBias, 0.0F, 1.0F); + tableF[j*3+2] = CLAMP(tempTab[i*3+2] * bScale + bBias, 0.0F, 1.0F); + } + break; + case GL_RGBA: + for (i = 0; i < count; i++) { + GLuint j = start + i; + tableF[j*4+0] = CLAMP(tempTab[i*4+0] * rScale + rBias, 0.0F, 1.0F); + tableF[j*4+1] = CLAMP(tempTab[i*4+1] * gScale + gBias, 0.0F, 1.0F); + tableF[j*4+2] = CLAMP(tempTab[i*4+2] * bScale + bBias, 0.0F, 1.0F); + tableF[j*4+3] = CLAMP(tempTab[i*4+3] * aScale + aBias, 0.0F, 1.0F); + } + break; + default: + _mesa_problem(ctx, "Bad format in store_colortable_entries"); + return; + } + } + else { + /* non-float (GLchan) */ + const GLint comps = _mesa_components_in_format(table->Format); + GLchan *dest = (GLchan *) table->Table + start * comps; + _mesa_unpack_color_span_chan(ctx, count, /* number of entries */ + table->Format, /* dest format */ + dest, /* dest address */ + format, type, data, /* src data */ + &ctx->Unpack, + 0); /* transfer ops */ + } + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } +} + + + +void GLAPIENTRY +_mesa_ColorTable( GLenum target, GLenum internalFormat, + GLsizei width, GLenum format, GLenum type, + const GLvoid *data ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj = NULL; + struct gl_color_table *table = NULL; + GLboolean proxy = GL_FALSE; + GLint baseFormat; + GLfloat rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0; + GLfloat rBias = 0.0, gBias = 0.0, bBias = 0.0, aBias = 0.0; + GLenum tableType = CHAN_TYPE; + GLint comps; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ + + switch (target) { + case GL_TEXTURE_1D: + texObj = texUnit->Current1D; + table = &texObj->Palette; + break; + case GL_TEXTURE_2D: + texObj = texUnit->Current2D; + table = &texObj->Palette; + break; + case GL_TEXTURE_3D: + texObj = texUnit->Current3D; + table = &texObj->Palette; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); + return; + } + texObj = texUnit->CurrentCubeMap; + table = &texObj->Palette; + break; + case GL_PROXY_TEXTURE_1D: + texObj = ctx->Texture.Proxy1D; + table = &texObj->Palette; + proxy = GL_TRUE; + break; + case GL_PROXY_TEXTURE_2D: + texObj = ctx->Texture.Proxy2D; + table = &texObj->Palette; + proxy = GL_TRUE; + break; + case GL_PROXY_TEXTURE_3D: + texObj = ctx->Texture.Proxy3D; + table = &texObj->Palette; + proxy = GL_TRUE; + break; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); + return; + } + texObj = ctx->Texture.ProxyCubeMap; + table = &texObj->Palette; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + table = &ctx->Texture.Palette; + tableType = GL_FLOAT; + break; + case GL_COLOR_TABLE: + table = &ctx->ColorTable; + tableType = GL_FLOAT; + rScale = ctx->Pixel.ColorTableScale[0]; + gScale = ctx->Pixel.ColorTableScale[1]; + bScale = ctx->Pixel.ColorTableScale[2]; + aScale = ctx->Pixel.ColorTableScale[3]; + rBias = ctx->Pixel.ColorTableBias[0]; + gBias = ctx->Pixel.ColorTableBias[1]; + bBias = ctx->Pixel.ColorTableBias[2]; + aBias = ctx->Pixel.ColorTableBias[3]; + break; + case GL_PROXY_COLOR_TABLE: + table = &ctx->ProxyColorTable; + proxy = GL_TRUE; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); + return; + } + table = &(texUnit->ColorTable); + tableType = GL_FLOAT; + rScale = ctx->Pixel.TextureColorTableScale[0]; + gScale = ctx->Pixel.TextureColorTableScale[1]; + bScale = ctx->Pixel.TextureColorTableScale[2]; + aScale = ctx->Pixel.TextureColorTableScale[3]; + rBias = ctx->Pixel.TextureColorTableBias[0]; + gBias = ctx->Pixel.TextureColorTableBias[1]; + bBias = ctx->Pixel.TextureColorTableBias[2]; + aBias = ctx->Pixel.TextureColorTableBias[3]; + break; + case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); + return; + } + table = &(texUnit->ProxyColorTable); + tableType = GL_FLOAT; + proxy = GL_TRUE; + break; + case GL_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->PostConvolutionColorTable; + tableType = GL_FLOAT; + rScale = ctx->Pixel.PCCTscale[0]; + gScale = ctx->Pixel.PCCTscale[1]; + bScale = ctx->Pixel.PCCTscale[2]; + aScale = ctx->Pixel.PCCTscale[3]; + rBias = ctx->Pixel.PCCTbias[0]; + gBias = ctx->Pixel.PCCTbias[1]; + bBias = ctx->Pixel.PCCTbias[2]; + aBias = ctx->Pixel.PCCTbias[3]; + break; + case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->ProxyPostConvolutionColorTable; + tableType = GL_FLOAT; + proxy = GL_TRUE; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->PostColorMatrixColorTable; + tableType = GL_FLOAT; + rScale = ctx->Pixel.PCMCTscale[0]; + gScale = ctx->Pixel.PCMCTscale[1]; + bScale = ctx->Pixel.PCMCTscale[2]; + aScale = ctx->Pixel.PCMCTscale[3]; + rBias = ctx->Pixel.PCMCTbias[0]; + gBias = ctx->Pixel.PCMCTbias[1]; + bBias = ctx->Pixel.PCMCTbias[2]; + aBias = ctx->Pixel.PCMCTbias[3]; + break; + case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->ProxyPostColorMatrixColorTable; + tableType = GL_FLOAT; + proxy = GL_TRUE; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(target)"); + return; + } + + assert(table); + + if (!_mesa_is_legal_format_and_type(ctx, format, type) || + format == GL_INTENSITY) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glColorTable(format or type)"); + return; + } + + baseFormat = base_colortab_format(internalFormat); + if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)"); + return; + } + + if (width < 0 || (width != 0 && _mesa_bitcount(width) != 1)) { + /* error */ + if (proxy) { + table->Size = 0; + table->IntFormat = (GLenum) 0; + table->Format = (GLenum) 0; + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, "glColorTable(width=%d)", width); + } + return; + } + + if (width > (GLsizei) ctx->Const.MaxColorTableSize) { + if (proxy) { + table->Size = 0; + table->IntFormat = (GLenum) 0; + table->Format = (GLenum) 0; + } + else { + _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glColorTable(width)"); + } + return; + } + + table->Size = width; + table->IntFormat = internalFormat; + table->Format = (GLenum) baseFormat; + table->Type = (tableType == GL_FLOAT) ? GL_FLOAT : CHAN_TYPE; + + comps = _mesa_components_in_format(table->Format); + assert(comps > 0); /* error should have been caught sooner */ + + if (!proxy) { + /* free old table, if any */ + if (table->Table) { + FREE(table->Table); + table->Table = NULL; + } + + if (width > 0) { + if (table->Type == GL_FLOAT) { + table->Table = MALLOC(comps * width * sizeof(GLfloat)); + } + else { + table->Table = MALLOC(comps * width * sizeof(GLchan)); + } + + if (!table->Table) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorTable"); + return; + } + + store_colortable_entries(ctx, table, + 0, width, /* start, count */ + format, type, data, + rScale, rBias, + gScale, gBias, + bScale, bBias, + aScale, aBias); + } + } /* proxy */ + + /* do this after the table's Type and Format are set */ + set_component_sizes(table); + + if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { + /* texture object palette, texObj==NULL means the shared palette */ + if (ctx->Driver.UpdateTexturePalette) { + (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); + } + } + + ctx->NewState |= _NEW_PIXEL; +} + + + +void GLAPIENTRY +_mesa_ColorSubTable( GLenum target, GLsizei start, + GLsizei count, GLenum format, GLenum type, + const GLvoid *data ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj = NULL; + struct gl_color_table *table = NULL; + GLfloat rScale = 1.0, gScale = 1.0, bScale = 1.0, aScale = 1.0; + GLfloat rBias = 0.0, gBias = 0.0, bBias = 0.0, aBias = 0.0; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (target) { + case GL_TEXTURE_1D: + texObj = texUnit->Current1D; + table = &texObj->Palette; + break; + case GL_TEXTURE_2D: + texObj = texUnit->Current2D; + table = &texObj->Palette; + break; + case GL_TEXTURE_3D: + texObj = texUnit->Current3D; + table = &texObj->Palette; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); + return; + } + texObj = texUnit->CurrentCubeMap; + table = &texObj->Palette; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + table = &ctx->Texture.Palette; + break; + case GL_COLOR_TABLE: + table = &ctx->ColorTable; + rScale = ctx->Pixel.ColorTableScale[0]; + gScale = ctx->Pixel.ColorTableScale[1]; + bScale = ctx->Pixel.ColorTableScale[2]; + aScale = ctx->Pixel.ColorTableScale[3]; + rBias = ctx->Pixel.ColorTableBias[0]; + gBias = ctx->Pixel.ColorTableBias[1]; + bBias = ctx->Pixel.ColorTableBias[2]; + aBias = ctx->Pixel.ColorTableBias[3]; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); + return; + } + table = &(texUnit->ColorTable); + rScale = ctx->Pixel.TextureColorTableScale[0]; + gScale = ctx->Pixel.TextureColorTableScale[1]; + bScale = ctx->Pixel.TextureColorTableScale[2]; + aScale = ctx->Pixel.TextureColorTableScale[3]; + rBias = ctx->Pixel.TextureColorTableBias[0]; + gBias = ctx->Pixel.TextureColorTableBias[1]; + bBias = ctx->Pixel.TextureColorTableBias[2]; + aBias = ctx->Pixel.TextureColorTableBias[3]; + break; + case GL_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->PostConvolutionColorTable; + rScale = ctx->Pixel.PCCTscale[0]; + gScale = ctx->Pixel.PCCTscale[1]; + bScale = ctx->Pixel.PCCTscale[2]; + aScale = ctx->Pixel.PCCTscale[3]; + rBias = ctx->Pixel.PCCTbias[0]; + gBias = ctx->Pixel.PCCTbias[1]; + bBias = ctx->Pixel.PCCTbias[2]; + aBias = ctx->Pixel.PCCTbias[3]; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->PostColorMatrixColorTable; + rScale = ctx->Pixel.PCMCTscale[0]; + gScale = ctx->Pixel.PCMCTscale[1]; + bScale = ctx->Pixel.PCMCTscale[2]; + aScale = ctx->Pixel.PCMCTscale[3]; + rBias = ctx->Pixel.PCMCTbias[0]; + gBias = ctx->Pixel.PCMCTbias[1]; + bBias = ctx->Pixel.PCMCTbias[2]; + aBias = ctx->Pixel.PCMCTbias[3]; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glColorSubTable(target)"); + return; + } + + assert(table); + + if (!_mesa_is_legal_format_and_type(ctx, format, type) || + format == GL_INTENSITY) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glColorSubTable(format or type)"); + return; + } + + if (count < 1) { + _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)"); + return; + } + + /* error should have been caught sooner */ + assert(_mesa_components_in_format(table->Format) > 0); + + if (start + count > (GLint) table->Size) { + _mesa_error(ctx, GL_INVALID_VALUE, "glColorSubTable(count)"); + return; + } + + if (!table->Table) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glColorSubTable"); + return; + } + + store_colortable_entries(ctx, table, start, count, + format, type, data, + rScale, rBias, + gScale, gBias, + bScale, bBias, + aScale, aBias); + + if (texObj || target == GL_SHARED_TEXTURE_PALETTE_EXT) { + /* per-texture object palette */ + if (ctx->Driver.UpdateTexturePalette) { + (*ctx->Driver.UpdateTexturePalette)( ctx, texObj ); + } + } + + ctx->NewState |= _NEW_PIXEL; +} + + + +void GLAPIENTRY +_mesa_CopyColorTable(GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + /* Select buffer to read from */ + ctx->Driver.CopyColorTable( ctx, target, internalformat, x, y, width ); +} + + + +void GLAPIENTRY +_mesa_CopyColorSubTable(GLenum target, GLsizei start, + GLint x, GLint y, GLsizei width) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + ctx->Driver.CopyColorSubTable( ctx, target, start, x, y, width ); +} + + + +void GLAPIENTRY +_mesa_GetColorTable( GLenum target, GLenum format, + GLenum type, GLvoid *data ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_color_table *table = NULL; + GLchan rgba[MAX_COLOR_TABLE_SIZE][4]; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + switch (target) { + case GL_TEXTURE_1D: + table = &texUnit->Current1D->Palette; + break; + case GL_TEXTURE_2D: + table = &texUnit->Current2D->Palette; + break; + case GL_TEXTURE_3D: + table = &texUnit->Current3D->Palette; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); + return; + } + table = &texUnit->CurrentCubeMap->Palette; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + table = &ctx->Texture.Palette; + break; + case GL_COLOR_TABLE: + table = &ctx->ColorTable; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); + return; + } + table = &(texUnit->ColorTable); + break; + case GL_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->PostConvolutionColorTable; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->PostColorMatrixColorTable; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTable(target)"); + return; + } + + ASSERT(table); + + switch (table->Format) { + case GL_ALPHA: + if (table->Type == GL_FLOAT) { + const GLfloat *tableF = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = 0; + rgba[i][GCOMP] = 0; + rgba[i][BCOMP] = 0; + rgba[i][ACOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + } + } + else { + const GLchan *tableUB = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = 0; + rgba[i][GCOMP] = 0; + rgba[i][BCOMP] = 0; + rgba[i][ACOMP] = tableUB[i]; + } + } + break; + case GL_LUMINANCE: + if (table->Type == GL_FLOAT) { + const GLfloat *tableF = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + rgba[i][GCOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + rgba[i][BCOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + rgba[i][ACOMP] = CHAN_MAX; + } + } + else { + const GLchan *tableUB = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = tableUB[i]; + rgba[i][GCOMP] = tableUB[i]; + rgba[i][BCOMP] = tableUB[i]; + rgba[i][ACOMP] = CHAN_MAX; + } + } + break; + case GL_LUMINANCE_ALPHA: + if (table->Type == GL_FLOAT) { + const GLfloat *tableF = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = IROUND_POS(tableF[i*2+0] * CHAN_MAXF); + rgba[i][GCOMP] = IROUND_POS(tableF[i*2+0] * CHAN_MAXF); + rgba[i][BCOMP] = IROUND_POS(tableF[i*2+0] * CHAN_MAXF); + rgba[i][ACOMP] = IROUND_POS(tableF[i*2+1] * CHAN_MAXF); + } + } + else { + const GLchan *tableUB = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = tableUB[i*2+0]; + rgba[i][GCOMP] = tableUB[i*2+0]; + rgba[i][BCOMP] = tableUB[i*2+0]; + rgba[i][ACOMP] = tableUB[i*2+1]; + } + } + break; + case GL_INTENSITY: + if (table->Type == GL_FLOAT) { + const GLfloat *tableF = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + rgba[i][GCOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + rgba[i][BCOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + rgba[i][ACOMP] = IROUND_POS(tableF[i] * CHAN_MAXF); + } + } + else { + const GLchan *tableUB = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = tableUB[i]; + rgba[i][GCOMP] = tableUB[i]; + rgba[i][BCOMP] = tableUB[i]; + rgba[i][ACOMP] = tableUB[i]; + } + } + break; + case GL_RGB: + if (table->Type == GL_FLOAT) { + const GLfloat *tableF = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = IROUND_POS(tableF[i*3+0] * CHAN_MAXF); + rgba[i][GCOMP] = IROUND_POS(tableF[i*3+1] * CHAN_MAXF); + rgba[i][BCOMP] = IROUND_POS(tableF[i*3+2] * CHAN_MAXF); + rgba[i][ACOMP] = CHAN_MAX; + } + } + else { + const GLchan *tableUB = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = tableUB[i*3+0]; + rgba[i][GCOMP] = tableUB[i*3+1]; + rgba[i][BCOMP] = tableUB[i*3+2]; + rgba[i][ACOMP] = CHAN_MAX; + } + } + break; + case GL_RGBA: + if (table->Type == GL_FLOAT) { + const GLfloat *tableF = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = IROUND_POS(tableF[i*4+0] * CHAN_MAXF); + rgba[i][GCOMP] = IROUND_POS(tableF[i*4+1] * CHAN_MAXF); + rgba[i][BCOMP] = IROUND_POS(tableF[i*4+2] * CHAN_MAXF); + rgba[i][ACOMP] = IROUND_POS(tableF[i*4+3] * CHAN_MAXF); + } + } + else { + const GLchan *tableUB = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < table->Size; i++) { + rgba[i][RCOMP] = tableUB[i*4+0]; + rgba[i][GCOMP] = tableUB[i*4+1]; + rgba[i][BCOMP] = tableUB[i*4+2]; + rgba[i][ACOMP] = tableUB[i*4+3]; + } + } + break; + default: + _mesa_problem(ctx, "bad table format in glGetColorTable"); + return; + } + + if (ctx->Pack.BufferObj->Name) { + /* pack color table into PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Pack, table->Size, 1, 1, + format, type, data)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetColorTable(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetColorTable(PBO is mapped)"); + return; + } + data = ADD_POINTERS(buf, data); + } + + _mesa_pack_rgba_span_chan(ctx, table->Size, (const GLchan (*)[4]) rgba, + format, type, data, &ctx->Pack, GL_FALSE); + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + + +void GLAPIENTRY +_mesa_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (target) { + case GL_COLOR_TABLE_SGI: + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + ctx->Pixel.ColorTableScale[0] = params[0]; + ctx->Pixel.ColorTableScale[1] = params[1]; + ctx->Pixel.ColorTableScale[2] = params[2]; + ctx->Pixel.ColorTableScale[3] = params[3]; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + ctx->Pixel.ColorTableBias[0] = params[0]; + ctx->Pixel.ColorTableBias[1] = params[1]; + ctx->Pixel.ColorTableBias[2] = params[2]; + ctx->Pixel.ColorTableBias[3] = params[3]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)"); + return; + } + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameter(target)"); + return; + } + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + ctx->Pixel.TextureColorTableScale[0] = params[0]; + ctx->Pixel.TextureColorTableScale[1] = params[1]; + ctx->Pixel.TextureColorTableScale[2] = params[2]; + ctx->Pixel.TextureColorTableScale[3] = params[3]; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + ctx->Pixel.TextureColorTableBias[0] = params[0]; + ctx->Pixel.TextureColorTableBias[1] = params[1]; + ctx->Pixel.TextureColorTableBias[2] = params[2]; + ctx->Pixel.TextureColorTableBias[3] = params[3]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)"); + return; + } + break; + case GL_POST_CONVOLUTION_COLOR_TABLE_SGI: + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + ctx->Pixel.PCCTscale[0] = params[0]; + ctx->Pixel.PCCTscale[1] = params[1]; + ctx->Pixel.PCCTscale[2] = params[2]; + ctx->Pixel.PCCTscale[3] = params[3]; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + ctx->Pixel.PCCTbias[0] = params[0]; + ctx->Pixel.PCCTbias[1] = params[1]; + ctx->Pixel.PCCTbias[2] = params[2]; + ctx->Pixel.PCCTbias[3] = params[3]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)"); + return; + } + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI: + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + ctx->Pixel.PCMCTscale[0] = params[0]; + ctx->Pixel.PCMCTscale[1] = params[1]; + ctx->Pixel.PCMCTscale[2] = params[2]; + ctx->Pixel.PCMCTscale[3] = params[3]; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + ctx->Pixel.PCMCTbias[0] = params[0]; + ctx->Pixel.PCMCTbias[1] = params[1]; + ctx->Pixel.PCMCTbias[2] = params[2]; + ctx->Pixel.PCMCTbias[3] = params[3]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameterfv(pname)"); + return; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glColorTableParameter(target)"); + return; + } + + ctx->NewState |= _NEW_PIXEL; +} + + + +void GLAPIENTRY +_mesa_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + GLfloat fparams[4]; + if (pname == GL_COLOR_TABLE_SGI || + pname == GL_TEXTURE_COLOR_TABLE_SGI || + pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI || + pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI) { + /* four values */ + fparams[0] = (GLfloat) params[0]; + fparams[1] = (GLfloat) params[1]; + fparams[2] = (GLfloat) params[2]; + fparams[3] = (GLfloat) params[3]; + } + else { + /* one values */ + fparams[0] = (GLfloat) params[0]; + } + _mesa_ColorTableParameterfv(target, pname, fparams); +} + + + +void GLAPIENTRY +_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_color_table *table = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (target) { + case GL_TEXTURE_1D: + table = &texUnit->Current1D->Palette; + break; + case GL_TEXTURE_2D: + table = &texUnit->Current2D->Palette; + break; + case GL_TEXTURE_3D: + table = &texUnit->Current3D->Palette; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetColorTableParameterfv(target)"); + return; + } + table = &texUnit->CurrentCubeMap->Palette; + break; + case GL_PROXY_TEXTURE_1D: + table = &ctx->Texture.Proxy1D->Palette; + break; + case GL_PROXY_TEXTURE_2D: + table = &ctx->Texture.Proxy2D->Palette; + break; + case GL_PROXY_TEXTURE_3D: + table = &ctx->Texture.Proxy3D->Palette; + break; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetColorTableParameterfv(target)"); + return; + } + table = &ctx->Texture.ProxyCubeMap->Palette; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + table = &ctx->Texture.Palette; + break; + case GL_COLOR_TABLE: + table = &ctx->ColorTable; + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = ctx->Pixel.ColorTableScale[0]; + params[1] = ctx->Pixel.ColorTableScale[1]; + params[2] = ctx->Pixel.ColorTableScale[2]; + params[3] = ctx->Pixel.ColorTableScale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = ctx->Pixel.ColorTableBias[0]; + params[1] = ctx->Pixel.ColorTableBias[1]; + params[2] = ctx->Pixel.ColorTableBias[2]; + params[3] = ctx->Pixel.ColorTableBias[3]; + return; + } + break; + case GL_PROXY_COLOR_TABLE: + table = &ctx->ProxyColorTable; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)"); + return; + } + table = &(texUnit->ColorTable); + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = ctx->Pixel.TextureColorTableScale[0]; + params[1] = ctx->Pixel.TextureColorTableScale[1]; + params[2] = ctx->Pixel.TextureColorTableScale[2]; + params[3] = ctx->Pixel.TextureColorTableScale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = ctx->Pixel.TextureColorTableBias[0]; + params[1] = ctx->Pixel.TextureColorTableBias[1]; + params[2] = ctx->Pixel.TextureColorTableBias[2]; + params[3] = ctx->Pixel.TextureColorTableBias[3]; + return; + } + break; + case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)"); + return; + } + table = &(texUnit->ProxyColorTable); + break; + case GL_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->PostConvolutionColorTable; + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = ctx->Pixel.PCCTscale[0]; + params[1] = ctx->Pixel.PCCTscale[1]; + params[2] = ctx->Pixel.PCCTscale[2]; + params[3] = ctx->Pixel.PCCTscale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = ctx->Pixel.PCCTbias[0]; + params[1] = ctx->Pixel.PCCTbias[1]; + params[2] = ctx->Pixel.PCCTbias[2]; + params[3] = ctx->Pixel.PCCTbias[3]; + return; + } + break; + case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->ProxyPostConvolutionColorTable; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->PostColorMatrixColorTable; + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = ctx->Pixel.PCMCTscale[0]; + params[1] = ctx->Pixel.PCMCTscale[1]; + params[2] = ctx->Pixel.PCMCTscale[2]; + params[3] = ctx->Pixel.PCMCTscale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = ctx->Pixel.PCMCTbias[0]; + params[1] = ctx->Pixel.PCMCTbias[1]; + params[2] = ctx->Pixel.PCMCTbias[2]; + params[3] = ctx->Pixel.PCMCTbias[3]; + return; + } + break; + case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->ProxyPostColorMatrixColorTable; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(target)"); + return; + } + + assert(table); + + switch (pname) { + case GL_COLOR_TABLE_FORMAT: + *params = (GLfloat) table->IntFormat; + break; + case GL_COLOR_TABLE_WIDTH: + *params = (GLfloat) table->Size; + break; + case GL_COLOR_TABLE_RED_SIZE: + *params = (GLfloat) table->RedSize; + break; + case GL_COLOR_TABLE_GREEN_SIZE: + *params = (GLfloat) table->GreenSize; + break; + case GL_COLOR_TABLE_BLUE_SIZE: + *params = (GLfloat) table->BlueSize; + break; + case GL_COLOR_TABLE_ALPHA_SIZE: + *params = (GLfloat) table->AlphaSize; + break; + case GL_COLOR_TABLE_LUMINANCE_SIZE: + *params = (GLfloat) table->LuminanceSize; + break; + case GL_COLOR_TABLE_INTENSITY_SIZE: + *params = (GLfloat) table->IntensitySize; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameterfv(pname)" ); + return; + } +} + + + +void GLAPIENTRY +_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_color_table *table = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (target) { + case GL_TEXTURE_1D: + table = &texUnit->Current1D->Palette; + break; + case GL_TEXTURE_2D: + table = &texUnit->Current2D->Palette; + break; + case GL_TEXTURE_3D: + table = &texUnit->Current3D->Palette; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetColorTableParameteriv(target)"); + return; + } + table = &texUnit->CurrentCubeMap->Palette; + break; + case GL_PROXY_TEXTURE_1D: + table = &ctx->Texture.Proxy1D->Palette; + break; + case GL_PROXY_TEXTURE_2D: + table = &ctx->Texture.Proxy2D->Palette; + break; + case GL_PROXY_TEXTURE_3D: + table = &ctx->Texture.Proxy3D->Palette; + break; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetColorTableParameteriv(target)"); + return; + } + table = &ctx->Texture.ProxyCubeMap->Palette; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + table = &ctx->Texture.Palette; + break; + case GL_COLOR_TABLE: + table = &ctx->ColorTable; + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = (GLint) ctx->Pixel.ColorTableScale[0]; + params[1] = (GLint) ctx->Pixel.ColorTableScale[1]; + params[2] = (GLint) ctx->Pixel.ColorTableScale[2]; + params[3] = (GLint) ctx->Pixel.ColorTableScale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = (GLint) ctx->Pixel.ColorTableBias[0]; + params[1] = (GLint) ctx->Pixel.ColorTableBias[1]; + params[2] = (GLint) ctx->Pixel.ColorTableBias[2]; + params[3] = (GLint) ctx->Pixel.ColorTableBias[3]; + return; + } + break; + case GL_PROXY_COLOR_TABLE: + table = &ctx->ProxyColorTable; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)"); + return; + } + table = &(texUnit->ColorTable); + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = (GLint) ctx->Pixel.TextureColorTableScale[0]; + params[1] = (GLint) ctx->Pixel.TextureColorTableScale[1]; + params[2] = (GLint) ctx->Pixel.TextureColorTableScale[2]; + params[3] = (GLint) ctx->Pixel.TextureColorTableScale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = (GLint) ctx->Pixel.TextureColorTableBias[0]; + params[1] = (GLint) ctx->Pixel.TextureColorTableBias[1]; + params[2] = (GLint) ctx->Pixel.TextureColorTableBias[2]; + params[3] = (GLint) ctx->Pixel.TextureColorTableBias[3]; + return; + } + break; + case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: + if (!ctx->Extensions.SGI_texture_color_table) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)"); + return; + } + table = &(texUnit->ProxyColorTable); + break; + case GL_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->PostConvolutionColorTable; + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = (GLint) ctx->Pixel.PCCTscale[0]; + params[1] = (GLint) ctx->Pixel.PCCTscale[1]; + params[2] = (GLint) ctx->Pixel.PCCTscale[2]; + params[3] = (GLint) ctx->Pixel.PCCTscale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = (GLint) ctx->Pixel.PCCTbias[0]; + params[1] = (GLint) ctx->Pixel.PCCTbias[1]; + params[2] = (GLint) ctx->Pixel.PCCTbias[2]; + params[3] = (GLint) ctx->Pixel.PCCTbias[3]; + return; + } + break; + case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: + table = &ctx->ProxyPostConvolutionColorTable; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->PostColorMatrixColorTable; + if (pname == GL_COLOR_TABLE_SCALE_SGI) { + params[0] = (GLint) ctx->Pixel.PCMCTscale[0]; + params[1] = (GLint) ctx->Pixel.PCMCTscale[1]; + params[2] = (GLint) ctx->Pixel.PCMCTscale[2]; + params[3] = (GLint) ctx->Pixel.PCMCTscale[3]; + return; + } + else if (pname == GL_COLOR_TABLE_BIAS_SGI) { + params[0] = (GLint) ctx->Pixel.PCMCTbias[0]; + params[1] = (GLint) ctx->Pixel.PCMCTbias[1]; + params[2] = (GLint) ctx->Pixel.PCMCTbias[2]; + params[3] = (GLint) ctx->Pixel.PCMCTbias[3]; + return; + } + break; + case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: + table = &ctx->ProxyPostColorMatrixColorTable; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(target)"); + return; + } + + assert(table); + + switch (pname) { + case GL_COLOR_TABLE_FORMAT: + *params = table->IntFormat; + break; + case GL_COLOR_TABLE_WIDTH: + *params = table->Size; + break; + case GL_COLOR_TABLE_RED_SIZE: + *params = table->RedSize; + break; + case GL_COLOR_TABLE_GREEN_SIZE: + *params = table->GreenSize; + break; + case GL_COLOR_TABLE_BLUE_SIZE: + *params = table->BlueSize; + break; + case GL_COLOR_TABLE_ALPHA_SIZE: + *params = table->AlphaSize; + break; + case GL_COLOR_TABLE_LUMINANCE_SIZE: + *params = table->LuminanceSize; + break; + case GL_COLOR_TABLE_INTENSITY_SIZE: + *params = table->IntensitySize; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameteriv(pname)" ); + return; + } +} + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + + +void +_mesa_init_colortable( struct gl_color_table *p ) +{ + p->Type = CHAN_TYPE; + p->Table = NULL; + p->Size = 0; + p->IntFormat = GL_RGBA; +} + + + +void +_mesa_free_colortable_data( struct gl_color_table *p ) +{ + if (p->Table) { + FREE(p->Table); + p->Table = NULL; + } +} + + +/* + * Initialize all colortables for a context. + */ +void _mesa_init_colortables( GLcontext * ctx ) +{ + /* Color tables */ + _mesa_init_colortable(&ctx->ColorTable); + _mesa_init_colortable(&ctx->ProxyColorTable); + _mesa_init_colortable(&ctx->PostConvolutionColorTable); + _mesa_init_colortable(&ctx->ProxyPostConvolutionColorTable); + _mesa_init_colortable(&ctx->PostColorMatrixColorTable); + _mesa_init_colortable(&ctx->ProxyPostColorMatrixColorTable); +} + + +/* + * Free all colortable data for a context + */ +void _mesa_free_colortables_data( GLcontext *ctx ) +{ + _mesa_free_colortable_data(&ctx->ColorTable); + _mesa_free_colortable_data(&ctx->ProxyColorTable); + _mesa_free_colortable_data(&ctx->PostConvolutionColorTable); + _mesa_free_colortable_data(&ctx->ProxyPostConvolutionColorTable); + _mesa_free_colortable_data(&ctx->PostColorMatrixColorTable); + _mesa_free_colortable_data(&ctx->ProxyPostColorMatrixColorTable); +} diff --git a/src/mesa/main/colortab.h b/src/mesa/main/colortab.h new file mode 100644 index 00000000000..4bd16210a0b --- /dev/null +++ b/src/mesa/main/colortab.h @@ -0,0 +1,110 @@ +/** + * \file colortab.h + * Color tables. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef COLORTAB_H +#define COLORTAB_H + + +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_ColorTable( GLenum target, GLenum internalformat, + GLsizei width, GLenum format, GLenum type, + const GLvoid *table ); + +extern void GLAPIENTRY +_mesa_ColorSubTable( GLenum target, GLsizei start, + GLsizei count, GLenum format, GLenum type, + const GLvoid *table ); + +extern void GLAPIENTRY +_mesa_CopyColorSubTable(GLenum target, GLsizei start, + GLint x, GLint y, GLsizei width); + +extern void GLAPIENTRY +_mesa_CopyColorTable(GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width); + +extern void GLAPIENTRY +_mesa_GetColorTable( GLenum target, GLenum format, + GLenum type, GLvoid *table ); + +extern void GLAPIENTRY +_mesa_ColorTableParameterfv(GLenum target, GLenum pname, + const GLfloat *params); + +extern void GLAPIENTRY +_mesa_ColorTableParameteriv(GLenum target, GLenum pname, + const GLint *params); + +extern void GLAPIENTRY +_mesa_GetColorTableParameterfv( GLenum target, GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetColorTableParameteriv( GLenum target, GLenum pname, GLint *params ); + + + +extern void +_mesa_init_colortable( struct gl_color_table *table ); + +extern void +_mesa_free_colortable_data( struct gl_color_table *table ); + +extern void +_mesa_init_colortables( GLcontext *ctx ); + +extern void +_mesa_free_colortables_data( GLcontext *ctx ); + +#else + +/** No-op */ +#define _mesa_init_colortable( p ) ((void) 0) + +/** No-op */ +#define _mesa_free_colortable_data( p ) ((void) 0) + +/** No-op */ +#define _mesa_init_colortables( p ) ((void)0) + +/** No-op */ +#define _mesa_free_colortables_data( p ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h new file mode 100644 index 00000000000..de2bae9cb0d --- /dev/null +++ b/src/mesa/main/config.h @@ -0,0 +1,324 @@ +/** + * \file config.h + * Tunable configuration parameters. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef CONFIG_H +#define CONFIG_H + +/** + * \name OpenGL implementation limits + */ +/*@{*/ + +/** Maximum modelview matrix stack depth */ +#define MAX_MODELVIEW_STACK_DEPTH 32 + +/** Maximum projection matrix stack depth */ +#define MAX_PROJECTION_STACK_DEPTH 32 + +/** Maximum texture matrix stack depth */ +#define MAX_TEXTURE_STACK_DEPTH 10 + +/** Maximum color matrix stack depth */ +#define MAX_COLOR_STACK_DEPTH 4 + +/** Maximum attribute stack depth */ +#define MAX_ATTRIB_STACK_DEPTH 16 + +/** Maximum client attribute stack depth */ +#define MAX_CLIENT_ATTRIB_STACK_DEPTH 16 + +/** Maximum recursion depth of display list calls */ +#define MAX_LIST_NESTING 64 + +/** Maximum number of lights */ +#define MAX_LIGHTS 8 + +/** Maximum user-defined clipping planes */ +#define MAX_CLIP_PLANES 6 + +/** Maximum pixel map lookup table size */ +#define MAX_PIXEL_MAP_TABLE 256 + +/** Maximum number of auxillary color buffers */ +#define MAX_AUX_BUFFERS 4 + +/** Maximum order (degree) of curves */ +#ifdef AMIGA +# define MAX_EVAL_ORDER 12 +#else +# define MAX_EVAL_ORDER 30 +#endif + +/** Maximum Name stack depth */ +#define MAX_NAME_STACK_DEPTH 64 + +/** Minimum point size */ +#define MIN_POINT_SIZE 1.0 +/** Maximum point size */ +#define MAX_POINT_SIZE 20.0 +/** Point size granularity */ +#define POINT_SIZE_GRANULARITY 0.1 + +/** Minimum line width */ +#define MIN_LINE_WIDTH 1.0 +/** Maximum line width */ +#define MAX_LINE_WIDTH 10.0 +/** Line width granularity */ +#define LINE_WIDTH_GRANULARITY 0.1 + +/** Max texture palette / color table size */ +#define MAX_COLOR_TABLE_SIZE 256 + +/** Number of 1D/2D texture mipmap levels */ +#define MAX_TEXTURE_LEVELS 12 + +/** Number of 3D texture mipmap levels */ +#define MAX_3D_TEXTURE_LEVELS 9 + +/** Number of cube texture mipmap levels - GL_ARB_texture_cube_map */ +#define MAX_CUBE_TEXTURE_LEVELS 12 + +/** Maximum rectangular texture size - GL_NV_texture_rectangle */ +#define MAX_TEXTURE_RECT_SIZE 2048 + +/** Number of texture units - GL_ARB_multitexture */ +#define MAX_TEXTURE_UNITS 8 + +/*@}*/ + + +/** + * \name Separate numbers of texture coordinates and texture image units. + * + * These values will eventually replace most instances of MAX_TEXTURE_UNITS. + * We should always have MAX_TEXTURE_COORD_UNITS <= MAX_TEXTURE_IMAGE_UNITS. + * And, GL_MAX_TEXTURE_UNITS <= MAX_TEXTURE_COORD_UNITS. + */ +/*@{*/ +#define MAX_TEXTURE_COORD_UNITS 8 +#define MAX_TEXTURE_IMAGE_UNITS 8 +/*@}*/ + +/** + * Maximum viewport/image width. Must accomodate all texture sizes too. + */ +#define MAX_WIDTH 4096 +/** Maximum viewport/image height */ +#define MAX_HEIGHT 4096 + +/** Maxmimum size for CVA. May be overridden by the drivers. */ +#define MAX_ARRAY_LOCK_SIZE 3000 + +/** Subpixel precision for antialiasing, window coordinate snapping */ +#define SUB_PIXEL_BITS 4 + +/** Size of histogram tables */ +#define HISTOGRAM_TABLE_SIZE 256 + +/** Max convolution filter width */ +#define MAX_CONVOLUTION_WIDTH 9 +/** Max convolution filter height */ +#define MAX_CONVOLUTION_HEIGHT 9 + +/** For GL_ARB_texture_compression */ +#define MAX_COMPRESSED_TEXTURE_FORMATS 25 + +/** For GL_EXT_texture_filter_anisotropic */ +#define MAX_TEXTURE_MAX_ANISOTROPY 16.0 + +/** For GL_EXT_texture_lod_bias (typically MAX_TEXTURE_LEVELS - 1) */ +#define MAX_TEXTURE_LOD_BIAS 11.0 + +/** For GL_NV_vertex_program */ +/*@{*/ +#define MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS 128 +#define MAX_NV_VERTEX_PROGRAM_TEMPS 12 +#define MAX_NV_VERTEX_PROGRAM_PARAMS 128 /* KW: power of two */ +#define MAX_NV_VERTEX_PROGRAM_INPUTS 16 +#define MAX_NV_VERTEX_PROGRAM_OUTPUTS 15 +/*@}*/ + +/** For GL_NV_fragment_program */ +/*@{*/ +#define MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS 128 +#define MAX_NV_FRAGMENT_PROGRAM_TEMPS 96 +#define MAX_NV_FRAGMENT_PROGRAM_PARAMS 64 +#define MAX_NV_FRAGMENT_PROGRAM_INPUTS 12 +#define MAX_NV_FRAGMENT_PROGRAM_OUTPUTS 3 +#define MAX_NV_FRAGMENT_PROGRAM_WRITE_ONLYS 2 +/*@}*/ + +/** For GL_ARB_vertex_program */ +/*@{*/ +#define MAX_VERTEX_PROGRAM_ADDRESS_REGS 1 +#define MAX_VERTEX_PROGRAM_ATTRIBS 16 +/*@}*/ + +/** For GL_ARB_fragment_program */ +/*@{*/ +#define MAX_FRAGMENT_PROGRAM_ADDRESS_REGS 1 +#define MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS 48 +#define MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS 24 +#define MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS 4 +/*@}*/ + +/** For any program target/extension */ +/*@{*/ +#define MAX_PROGRAM_LOCAL_PARAMS 128 /* KW: power of two */ +#define MAX_PROGRAM_MATRICES 8 +#define MAX_PROGRAM_MATRIX_STACK_DEPTH 4 +/*@}*/ + +/** For GL_ARB_fragment_shader */ +/*@{*/ +#define MAX_FRAGMENT_UNIFORM_COMPONENTS 64 +/*@}*/ + +/** For GL_ARB_vertex_shader */ +/*@{*/ +#define MAX_VERTEX_UNIFORM_COMPONENTS 512 +#define MAX_VARYING_FLOATS 32 +#define MAX_VERTEX_TEXTURE_IMAGE_UNITS 0 +#define MAX_COMBINED_TEXTURE_IMAGE_UNITS (MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS) +/*@}*/ + + +/** For GL_ARB_draw_buffers */ +/*@{*/ +#define MAX_DRAW_BUFFERS 1 +/*@}*/ + + +/** For GL_EXT_framebuffer_object */ +/*@{*/ +#define MAX_COLOR_ATTACHMENTS 8 +/*@}*/ + + + +/** + * \name Mesa-specific parameters + */ +/*@{*/ + + +/** + * If non-zero use GLdouble for walking triangle edges, for better accuracy. + */ +#define TRIANGLE_WALK_DOUBLE 0 + +/** + * Bits per accumulation buffer color component: 8, 16 or 32 + */ +#define ACCUM_BITS 16 + +/** + * Bits per depth buffer value. + * + * Any reasonable value up to 31 will work. 32 doesn't work because of integer + * overflow problems in the rasterizer code. + */ +#ifndef DEFAULT_SOFTWARE_DEPTH_BITS +#define DEFAULT_SOFTWARE_DEPTH_BITS 16 +#endif +/** Depth buffer data type */ +#if DEFAULT_SOFTWARE_DEPTH_BITS <= 16 +#define DEFAULT_SOFTWARE_DEPTH_TYPE GLushort +#else +#define DEFAULT_SOFTWARE_DEPTH_TYPE GLuint +#endif + + +/** + * Bits per stencil value: 8 + */ +#define STENCIL_BITS 8 + + +/** + * Bits per color channel: 8, 16 or 32 + */ +#ifndef CHAN_BITS +#define CHAN_BITS 8 +#endif + + +/* + * Color channel component order + * + * \note Changes will almost certainly cause problems at this time. + */ +#define RCOMP 0 +#define GCOMP 1 +#define BCOMP 2 +#define ACOMP 3 + + +/* + * Enable/disable features (blocks of code) by setting FEATURE_xyz to 0 or 1. + */ +#ifndef _HAVE_FULL_GL +#define _HAVE_FULL_GL 1 +#endif + +#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL +#define FEATURE_ARB_vertex_program _HAVE_FULL_GL +#define FEATURE_ARB_fragment_program _HAVE_FULL_GL +#define FEATURE_ARB_occlusion_query _HAVE_FULL_GL +#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL +#define FEATURE_MESA_program_debug _HAVE_FULL_GL +#define FEATURE_NV_fence _HAVE_FULL_GL +#define FEATURE_NV_fragment_program _HAVE_FULL_GL +#define FEATURE_NV_vertex_program _HAVE_FULL_GL +#define FEATURE_userclip _HAVE_FULL_GL +#define FEATURE_texgen _HAVE_FULL_GL +#define FEATURE_windowpos _HAVE_FULL_GL +#define FEATURE_ARB_vertex_shader _HAVE_FULL_GL +#define FEATURE_ARB_fragment_shader _HAVE_FULL_GL +#define FEATURE_ARB_shader_objects (FEATURE_ARB_vertex_shader || FEATURE_ARB_fragment_shader) +#define FEATURE_ARB_shading_language_100 FEATURE_ARB_shader_objects +#define FEATURE_ATI_fragment_shader _HAVE_FULL_GL +#define FEATURE_EXT_framebuffer_object _HAVE_FULL_GL +/*@}*/ + + +/** + * Maximum number of temporary vertices required for clipping. + * + * Used in array_cache and tnl modules. + */ +#define MAX_CLIPPED_VERTICES ((2 * (6 + MAX_CLIP_PLANES))+1) + + +/* XXX everything marked with OLD_RENDERBUFFER will be going away... */ +#define OLD_RENDERBUFFER 1 + + +#endif /* CONFIG_H */ diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c new file mode 100644 index 00000000000..25a3f6a37d4 --- /dev/null +++ b/src/mesa/main/context.c @@ -0,0 +1,1750 @@ +/** + * \file context.c + * Mesa context/visual/framebuffer management functions. + * \author Brian Paul + */ + +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \mainpage Mesa Main Module + * + * \section MainIntroduction Introduction + * + * The Mesa Main module consists of all the files in the main/ directory. + * Among the features of this module are: + * <UL> + * <LI> Structures to represent most GL state </LI> + * <LI> State set/get functions </LI> + * <LI> Display lists </LI> + * <LI> Texture unit, object and image handling </LI> + * <LI> Matrix and attribute stacks </LI> + * </UL> + * + * Other modules are responsible for API dispatch, vertex transformation, + * point/line/triangle setup, rasterization, vertex array caching, + * vertex/fragment programs/shaders, etc. + * + * + * \section AboutDoxygen About Doxygen + * + * If you're viewing this information as Doxygen-generated HTML you'll + * see the documentation index at the top of this page. + * + * The first line lists the Mesa source code modules. + * The second line lists the indexes available for viewing the documentation + * for each module. + * + * Selecting the <b>Main page</b> link will display a summary of the module + * (this page). + * + * Selecting <b>Data Structures</b> will list all C structures. + * + * Selecting the <b>File List</b> link will list all the source files in + * the module. + * Selecting a filename will show a list of all functions defined in that file. + * + * Selecting the <b>Data Fields</b> link will display a list of all + * documented structure members. + * + * Selecting the <b>Globals</b> link will display a list + * of all functions, structures, global variables and macros in the module. + * + */ + + +#include "glheader.h" +#include "imports.h" +#include "accum.h" +#include "attrib.h" +#include "blend.h" +#include "buffers.h" +#include "bufferobj.h" +#include "colortab.h" +#include "context.h" +#include "debug.h" +#include "depth.h" +#include "dlist.h" +#include "eval.h" +#include "enums.h" +#include "extensions.h" +#include "fbobject.h" +#include "feedback.h" +#include "fog.h" +#include "get.h" +#include "glthread.h" +#include "glapioffsets.h" +#include "histogram.h" +#include "hint.h" +#include "hash.h" +#include "light.h" +#include "lines.h" +#include "macros.h" +#include "matrix.h" +#include "occlude.h" +#include "pixel.h" +#include "points.h" +#include "polygon.h" +#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program +#include "program.h" +#endif +#include "rastpos.h" +#include "simple_list.h" +#include "state.h" +#include "stencil.h" +#include "texcompress.h" +#include "teximage.h" +#include "texobj.h" +#include "texstate.h" +#include "mtypes.h" +#include "varray.h" +#include "version.h" +#include "vtxfmt.h" +#if _HAVE_FULL_GL +#include "math/m_translate.h" +#include "math/m_matrix.h" +#include "math/m_xform.h" +#include "math/mathmod.h" +#endif +#include "shaderobjects.h" + +#ifdef USE_SPARC_ASM +#include "sparc/sparc.h" +#endif + +#ifndef MESA_VERBOSE +int MESA_VERBOSE = 0; +#endif + +#ifndef MESA_DEBUG_FLAGS +int MESA_DEBUG_FLAGS = 0; +#endif + + +/* ubyte -> float conversion */ +GLfloat _mesa_ubyte_to_float_color_tab[256]; + +static void +free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ); + + +/**********************************************************************/ +/** \name OpenGL SI-style interface (new in Mesa 3.5) + * + * \if subset + * \note Most of these functions are never called in the Mesa subset. + * \endif + */ +/*@{*/ + +/** + * Destroy context callback. + * + * \param gc context. + * \return GL_TRUE on success, or GL_FALSE on failure. + * + * \ifnot subset + * Called by window system/device driver (via __GLexports::destroyCurrent) when + * the rendering context is to be destroyed. + * \endif + * + * Frees the context data and the context structure. + */ +GLboolean +_mesa_destroyContext(__GLcontext *gc) +{ + if (gc) { + _mesa_free_context_data(gc); + _mesa_free(gc); + } + return GL_TRUE; +} + +/** + * Unbind context callback. + * + * \param gc context. + * \return GL_TRUE on success, or GL_FALSE on failure. + * + * \ifnot subset + * Called by window system/device driver (via __GLexports::loseCurrent) + * when the rendering context is made non-current. + * \endif + * + * No-op + */ +GLboolean +_mesa_loseCurrent(__GLcontext *gc) +{ + /* XXX unbind context from thread */ + (void) gc; + return GL_TRUE; +} + +/** + * Bind context callback. + * + * \param gc context. + * \return GL_TRUE on success, or GL_FALSE on failure. + * + * \ifnot subset + * Called by window system/device driver (via __GLexports::makeCurrent) + * when the rendering context is made current. + * \endif + * + * No-op + */ +GLboolean +_mesa_makeCurrent(__GLcontext *gc) +{ + /* XXX bind context to thread */ + (void) gc; + return GL_TRUE; +} + +/** + * Share context callback. + * + * \param gc context. + * \param gcShare shared context. + * \return GL_TRUE on success, or GL_FALSE on failure. + * + * \ifnot subset + * Called by window system/device driver (via __GLexports::shareContext) + * \endif + * + * Update the shared context reference count, gl_shared_state::RefCount. + */ +GLboolean +_mesa_shareContext(__GLcontext *gc, __GLcontext *gcShare) +{ + if (gc && gcShare && gc->Shared && gcShare->Shared) { + gc->Shared->RefCount--; + if (gc->Shared->RefCount == 0) { + free_shared_state(gc, gc->Shared); + } + gc->Shared = gcShare->Shared; + gc->Shared->RefCount++; + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + +#if _HAVE_FULL_GL +/** + * Copy context callback. + */ +GLboolean +_mesa_copyContext(__GLcontext *dst, const __GLcontext *src, GLuint mask) +{ + if (dst && src) { + _mesa_copy_context( src, dst, mask ); + return GL_TRUE; + } + else { + return GL_FALSE; + } +} +#endif + +/** No-op */ +GLboolean +_mesa_forceCurrent(__GLcontext *gc) +{ + (void) gc; + return GL_TRUE; +} + +/** + * Windows/buffer resizing notification callback. + * + * \param gc GL context. + * \return GL_TRUE on success, or GL_FALSE on failure. + */ +GLboolean +_mesa_notifyResize(__GLcontext *gc) +{ + GLint x, y; + GLuint width, height; + __GLdrawablePrivate *d = gc->imports.getDrawablePrivate(gc); + if (!d || !d->getDrawableSize) + return GL_FALSE; + d->getDrawableSize( d, &x, &y, &width, &height ); + /* update viewport, resize software buffers, etc. */ + return GL_TRUE; +} + +/** + * Window/buffer destruction notification callback. + * + * \param gc GL context. + * + * Called when the context's window/buffer is going to be destroyed. + * + * No-op + */ +void +_mesa_notifyDestroy(__GLcontext *gc) +{ + /* Unbind from it. */ + (void) gc; +} + +/** + * Swap buffers notification callback. + * + * \param gc GL context. + * + * Called by window system just before swapping buffers. + * We have to finish any pending rendering. + */ +void +_mesa_notifySwapBuffers(__GLcontext *gc) +{ + FLUSH_VERTICES( gc, 0 ); +} + +/** No-op */ +struct __GLdispatchStateRec * +_mesa_dispatchExec(__GLcontext *gc) +{ + (void) gc; + return NULL; +} + +/** No-op */ +void +_mesa_beginDispatchOverride(__GLcontext *gc) +{ + (void) gc; +} + +/** No-op */ +void +_mesa_endDispatchOverride(__GLcontext *gc) +{ + (void) gc; +} + +/** + * \ifnot subset + * Setup the exports. + * + * The window system will call these functions when it needs Mesa to do + * something. + * + * \note Device drivers should override these functions! For example, + * the Xlib driver should plug in the XMesa*-style functions into this + * structure. The XMesa-style functions should then call the _mesa_* + * version of these functions. This is an approximation to OO design + * (inheritance and virtual functions). + * \endif + * + * \if subset + * No-op. + * + * \endif + */ +static void +_mesa_init_default_exports(__GLexports *exports) +{ +#if _HAVE_FULL_GL + exports->destroyContext = _mesa_destroyContext; + exports->loseCurrent = _mesa_loseCurrent; + exports->makeCurrent = _mesa_makeCurrent; + exports->shareContext = _mesa_shareContext; + exports->copyContext = _mesa_copyContext; + exports->forceCurrent = _mesa_forceCurrent; + exports->notifyResize = _mesa_notifyResize; + exports->notifyDestroy = _mesa_notifyDestroy; + exports->notifySwapBuffers = _mesa_notifySwapBuffers; + exports->dispatchExec = _mesa_dispatchExec; + exports->beginDispatchOverride = _mesa_beginDispatchOverride; + exports->endDispatchOverride = _mesa_endDispatchOverride; +#else + (void) exports; +#endif +} + +/** + * Exported OpenGL SI interface. + */ +__GLcontext * +__glCoreCreateContext(__GLimports *imports, __GLcontextModes *modes) +{ + GLcontext *ctx; + + ctx = (GLcontext *) (*imports->calloc)(NULL, 1, sizeof(GLcontext)); + if (ctx == NULL) { + return NULL; + } + + /* XXX doesn't work at this time */ + _mesa_initialize_context(ctx, modes, NULL, NULL, NULL); + ctx->imports = *imports; + + return ctx; +} + +/** + * Exported OpenGL SI interface. + */ +void +__glCoreNopDispatch(void) +{ +#if 0 + /* SI */ + __gl_dispatch = __glNopDispatchState; +#else + /* Mesa */ + _glapi_set_dispatch(NULL); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name GL Visual allocation/destruction */ +/**********************************************************************/ +/*@{*/ + +/** + * Allocates a GLvisual structure and initializes it via + * _mesa_initialize_visual(). + * + * \param rgbFlag GL_TRUE for RGB(A) mode, GL_FALSE for Color Index mode. + * \param dbFlag double buffering + * \param stereoFlag stereo buffer + * \param depthBits requested bits per depth buffer value. Any value in [0, 32] + * is acceptable but the actual depth type will be GLushort or GLuint as + * needed. + * \param stencilBits requested minimum bits per stencil buffer value + * \param accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits number of bits per color component in accum buffer. + * \param indexBits number of bits per pixel if \p rgbFlag is GL_FALSE + * \param redBits number of bits per color component in frame buffer for RGB(A) + * mode. We always use 8 in core Mesa though. + * \param greenBits same as above. + * \param blueBits same as above. + * \param alphaBits same as above. + * \param numSamples not really used. + * + * \return pointer to new GLvisual or NULL if requested parameters can't be + * met. + * + * \note Need to add params for level and numAuxBuffers (at least) + */ +GLvisual * +_mesa_create_visual( GLboolean rgbFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits, + GLint indexBits, + GLint depthBits, + GLint stencilBits, + GLint accumRedBits, + GLint accumGreenBits, + GLint accumBlueBits, + GLint accumAlphaBits, + GLint numSamples ) +{ + GLvisual *vis = (GLvisual *) CALLOC( sizeof(GLvisual) ); + if (vis) { + if (!_mesa_initialize_visual(vis, rgbFlag, dbFlag, stereoFlag, + redBits, greenBits, blueBits, alphaBits, + indexBits, depthBits, stencilBits, + accumRedBits, accumGreenBits, + accumBlueBits, accumAlphaBits, + numSamples)) { + FREE(vis); + return NULL; + } + } + return vis; +} + +/** + * Makes some sanity checks and fills in the fields of the + * GLvisual object with the given parameters. If the caller needs + * to set additional fields, he should just probably init the whole GLvisual + * object himself. + * \return GL_TRUE on success, or GL_FALSE on failure. + * + * \sa _mesa_create_visual() above for the parameter description. + */ +GLboolean +_mesa_initialize_visual( GLvisual *vis, + GLboolean rgbFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits, + GLint indexBits, + GLint depthBits, + GLint stencilBits, + GLint accumRedBits, + GLint accumGreenBits, + GLint accumBlueBits, + GLint accumAlphaBits, + GLint numSamples ) +{ + assert(vis); + + if (depthBits < 0 || depthBits > 32) { + return GL_FALSE; + } + if (stencilBits < 0 || stencilBits > STENCIL_BITS) { + return GL_FALSE; + } + if (accumRedBits < 0 || accumRedBits > ACCUM_BITS) { + return GL_FALSE; + } + if (accumGreenBits < 0 || accumGreenBits > ACCUM_BITS) { + return GL_FALSE; + } + if (accumBlueBits < 0 || accumBlueBits > ACCUM_BITS) { + return GL_FALSE; + } + if (accumAlphaBits < 0 || accumAlphaBits > ACCUM_BITS) { + return GL_FALSE; + } + + vis->rgbMode = rgbFlag; + vis->doubleBufferMode = dbFlag; + vis->stereoMode = stereoFlag; + + vis->redBits = redBits; + vis->greenBits = greenBits; + vis->blueBits = blueBits; + vis->alphaBits = alphaBits; + vis->rgbBits = redBits + greenBits + blueBits; + + vis->indexBits = indexBits; + vis->depthBits = depthBits; + vis->stencilBits = stencilBits; + + vis->accumRedBits = accumRedBits; + vis->accumGreenBits = accumGreenBits; + vis->accumBlueBits = accumBlueBits; + vis->accumAlphaBits = accumAlphaBits; + + vis->haveAccumBuffer = accumRedBits > 0; + vis->haveDepthBuffer = depthBits > 0; + vis->haveStencilBuffer = stencilBits > 0; + + vis->numAuxBuffers = 0; + vis->level = 0; + vis->pixmapMode = 0; + vis->sampleBuffers = numSamples > 0 ? 1 : 0; + vis->samples = numSamples; + + return GL_TRUE; +} + + +/** + * Destroy a visual and free its memory. + * + * \param vis visual. + * + * Frees the visual structure. + */ +void +_mesa_destroy_visual( GLvisual *vis ) +{ + FREE(vis); +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Context allocation, initialization, destroying + * + * The purpose of the most initialization functions here is to provide the + * default state values according to the OpenGL specification. + */ +/**********************************************************************/ +/*@{*/ + +/** + * One-time initialization mutex lock. + * + * \sa Used by one_time_init(). + */ +_glthread_DECLARE_STATIC_MUTEX(OneTimeLock); + +/** + * Calls all the various one-time-init functions in Mesa. + * + * While holding a global mutex lock, calls several initialization functions, + * and sets the glapi callbacks if the \c MESA_DEBUG environment variable is + * defined. + * + * \sa _mesa_init_lists(), _math_init(). + */ +static void +one_time_init( GLcontext *ctx ) +{ + static GLboolean alreadyCalled = GL_FALSE; + (void) ctx; + _glthread_LOCK_MUTEX(OneTimeLock); + if (!alreadyCalled) { + GLuint i; + + /* do some implementation tests */ + assert( sizeof(GLbyte) == 1 ); + assert( sizeof(GLubyte) == 1 ); + assert( sizeof(GLshort) == 2 ); + assert( sizeof(GLushort) == 2 ); + assert( sizeof(GLint) == 4 ); + assert( sizeof(GLuint) == 4 ); + + _mesa_init_lists(); + +#if _HAVE_FULL_GL + _math_init(); + + for (i = 0; i < 256; i++) { + _mesa_ubyte_to_float_color_tab[i] = (float) i / 255.0F; + } +#endif + +#ifdef USE_SPARC_ASM + _mesa_init_sparc_glapi_relocs(); +#endif + if (_mesa_getenv("MESA_DEBUG")) { + _glapi_noop_enable_warnings(GL_TRUE); + _glapi_set_warning_func( (_glapi_warning_func) _mesa_warning ); + } + else { + _glapi_noop_enable_warnings(GL_FALSE); + } + +#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__) + _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n", + MESA_VERSION_STRING, __DATE__, __TIME__); +#endif + + alreadyCalled = GL_TRUE; + } + _glthread_UNLOCK_MUTEX(OneTimeLock); +} + + +/** + * Allocate and initialize a shared context state structure. + * Initializes the display list, texture objects and vertex programs hash + * tables, allocates the texture objects. If it runs out of memory, frees + * everything already allocated before returning NULL. + * + * \return pointer to a gl_shared_state structure on success, or NULL on + * failure. + */ +static GLboolean +alloc_shared_state( GLcontext *ctx ) +{ + struct gl_shared_state *ss = CALLOC_STRUCT(gl_shared_state); + if (!ss) + return GL_FALSE; + + ctx->Shared = ss; + + _glthread_INIT_MUTEX(ss->Mutex); + + ss->DisplayList = _mesa_NewHashTable(); + ss->TexObjects = _mesa_NewHashTable(); +#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program + ss->Programs = _mesa_NewHashTable(); +#endif + +#if FEATURE_ARB_vertex_program + ss->DefaultVertexProgram = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); + if (!ss->DefaultVertexProgram) + goto cleanup; +#endif +#if FEATURE_ARB_fragment_program + ss->DefaultFragmentProgram = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); + if (!ss->DefaultFragmentProgram) + goto cleanup; +#endif +#if FEATURE_ATI_fragment_shader + ss->DefaultFragmentShader = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_SHADER_ATI, 0); + if (!ss->DefaultFragmentShader) + goto cleanup; +#endif + + ss->BufferObjects = _mesa_NewHashTable(); + + ss->GL2Objects = _mesa_NewHashTable (); + + ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D); + if (!ss->Default1D) + goto cleanup; + + ss->Default2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D); + if (!ss->Default2D) + goto cleanup; + + ss->Default3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D); + if (!ss->Default3D) + goto cleanup; + + ss->DefaultCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB); + if (!ss->DefaultCubeMap) + goto cleanup; + + ss->DefaultRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV); + if (!ss->DefaultRect) + goto cleanup; + + /* Effectively bind the default textures to all texture units */ + ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS; + ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS; + ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS; + ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS; + ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS; + +#if FEATURE_EXT_framebuffer_object + ss->FrameBuffers = _mesa_NewHashTable(); + if (!ss->FrameBuffers) + goto cleanup; + ss->RenderBuffers = _mesa_NewHashTable(); + if (!ss->RenderBuffers) + goto cleanup; +#endif + + + return GL_TRUE; + + cleanup: + /* Ran out of memory at some point. Free everything and return NULL */ + if (ss->DisplayList) + _mesa_DeleteHashTable(ss->DisplayList); + if (ss->TexObjects) + _mesa_DeleteHashTable(ss->TexObjects); +#if FEATURE_NV_vertex_program + if (ss->Programs) + _mesa_DeleteHashTable(ss->Programs); +#endif +#if FEATURE_ARB_vertex_program + if (ss->DefaultVertexProgram) + ctx->Driver.DeleteProgram(ctx, ss->DefaultVertexProgram); +#endif +#if FEATURE_ARB_fragment_program + if (ss->DefaultFragmentProgram) + ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentProgram); +#endif +#if FEATURE_ATI_fragment_shader + if (ss->DefaultFragmentShader) + ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentShader); +#endif +#if FEATURE_ARB_vertex_buffer_object + if (ss->BufferObjects) + _mesa_DeleteHashTable(ss->BufferObjects); +#endif + + if (ss->GL2Objects) + _mesa_DeleteHashTable (ss->GL2Objects); + +#if FEATURE_EXT_framebuffer_object + if (ss->FrameBuffers) + _mesa_DeleteHashTable(ss->FrameBuffers); + if (ss->RenderBuffers) + _mesa_DeleteHashTable(ss->RenderBuffers); +#endif + + if (ss->Default1D) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default1D); + if (ss->Default2D) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default2D); + if (ss->Default3D) + (*ctx->Driver.DeleteTexture)(ctx, ss->Default3D); + if (ss->DefaultCubeMap) + (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap); + if (ss->DefaultRect) + (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect); + if (ss) + _mesa_free(ss); + return GL_FALSE; +} + +/** + * Deallocate a shared state context and all children structures. + * + * \param ctx GL context. + * \param ss shared state pointer. + * + * Frees the display lists, the texture objects (calling the driver texture + * deletion callback to free its private data) and the vertex programs, as well + * as their hash tables. + * + * \sa alloc_shared_state(). + */ +static void +free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) +{ + /* Free display lists */ + while (1) { + GLuint list = _mesa_HashFirstEntry(ss->DisplayList); + if (list) { + _mesa_destroy_list(ctx, list); + } + else { + break; + } + } + _mesa_DeleteHashTable(ss->DisplayList); + + /* Free texture objects */ + ASSERT(ctx->Driver.DeleteTexture); + /* the default textures */ + (*ctx->Driver.DeleteTexture)(ctx, ss->Default1D); + (*ctx->Driver.DeleteTexture)(ctx, ss->Default2D); + (*ctx->Driver.DeleteTexture)(ctx, ss->Default3D); + (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap); + (*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect); + /* all other textures */ + while (1) { + GLuint texName = _mesa_HashFirstEntry(ss->TexObjects); + if (texName) { + struct gl_texture_object *texObj = (struct gl_texture_object *) + _mesa_HashLookup(ss->TexObjects, texName); + ASSERT(texObj); + (*ctx->Driver.DeleteTexture)(ctx, texObj); + _mesa_HashRemove(ss->TexObjects, texName); + } + else { + break; + } + } + _mesa_DeleteHashTable(ss->TexObjects); + +#if FEATURE_NV_vertex_program + /* Free vertex programs */ + while (1) { + GLuint prog = _mesa_HashFirstEntry(ss->Programs); + if (prog) { + struct program *p = (struct program *) _mesa_HashLookup(ss->Programs, + prog); + ASSERT(p); + ctx->Driver.DeleteProgram(ctx, p); + _mesa_HashRemove(ss->Programs, prog); + } + else { + break; + } + } + _mesa_DeleteHashTable(ss->Programs); +#endif +#if FEATURE_ARB_vertex_program + _mesa_delete_program(ctx, ss->DefaultVertexProgram); +#endif +#if FEATURE_ARB_fragment_program + _mesa_delete_program(ctx, ss->DefaultFragmentProgram); +#endif +#if FEATURE_ATI_fragment_shader + _mesa_delete_program(ctx, ss->DefaultFragmentShader); +#endif + +#if FEATURE_ARB_vertex_buffer_object + _mesa_DeleteHashTable(ss->BufferObjects); +#endif + + _mesa_DeleteHashTable (ss->GL2Objects); + +#if FEATURE_EXT_framebuffer_object + _mesa_DeleteHashTable(ss->FrameBuffers); + _mesa_DeleteHashTable(ss->RenderBuffers); +#endif + + _glthread_DESTROY_MUTEX(ss->Mutex); + + FREE(ss); +} + + +/** + * Initialize fields of gl_current_attrib (aka ctx->Current.*) + */ +static void +_mesa_init_current( GLcontext *ctx ) +{ + GLuint i; + + /* Current group */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + ASSIGN_4V( ctx->Current.Attrib[i], 0.0, 0.0, 0.0, 1.0 ); + } + /* special cases: */ + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], 0.0, 0.0, 1.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_FOG], 0.0, 0.0, 0.0, 0.0 ); + + ctx->Current.Index = 1; + ctx->Current.EdgeFlag = GL_TRUE; +} + + +/** + * Initialize fields of gl_constants (aka ctx->Const.*). + * Use defaults from config.h. The device drivers will often override + * some of these values (such as number of texture units). + */ +static void +_mesa_init_constants( GLcontext *ctx ) +{ + assert(ctx); + + assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS); + assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS); + + /* Constants, may be overriden (usually only reduced) by device drivers */ + ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS; + ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS; + ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS; + ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE; + ctx->Const.MaxTextureUnits = MAX_TEXTURE_UNITS; + ctx->Const.MaxTextureCoordUnits = MAX_TEXTURE_COORD_UNITS; + ctx->Const.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; + ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY; + ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS; + ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE; + ctx->Const.SubPixelBits = SUB_PIXEL_BITS; + ctx->Const.MinPointSize = MIN_POINT_SIZE; + ctx->Const.MaxPointSize = MAX_POINT_SIZE; + ctx->Const.MinPointSizeAA = MIN_POINT_SIZE; + ctx->Const.MaxPointSizeAA = MAX_POINT_SIZE; + ctx->Const.PointSizeGranularity = (GLfloat) POINT_SIZE_GRANULARITY; + ctx->Const.MinLineWidth = MIN_LINE_WIDTH; + ctx->Const.MaxLineWidth = MAX_LINE_WIDTH; + ctx->Const.MinLineWidthAA = MIN_LINE_WIDTH; + ctx->Const.MaxLineWidthAA = MAX_LINE_WIDTH; + ctx->Const.LineWidthGranularity = (GLfloat) LINE_WIDTH_GRANULARITY; + ctx->Const.MaxColorTableSize = MAX_COLOR_TABLE_SIZE; + ctx->Const.MaxConvolutionWidth = MAX_CONVOLUTION_WIDTH; + ctx->Const.MaxConvolutionHeight = MAX_CONVOLUTION_HEIGHT; + ctx->Const.MaxClipPlanes = MAX_CLIP_PLANES; + ctx->Const.MaxLights = MAX_LIGHTS; + ctx->Const.MaxShininess = 128.0; + ctx->Const.MaxSpotExponent = 128.0; + ctx->Const.MaxViewportWidth = MAX_WIDTH; + ctx->Const.MaxViewportHeight = MAX_HEIGHT; +#if FEATURE_ARB_vertex_program + ctx->Const.MaxVertexProgramInstructions = MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS; + ctx->Const.MaxVertexProgramAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS; + ctx->Const.MaxVertexProgramTemps = MAX_NV_VERTEX_PROGRAM_TEMPS; + ctx->Const.MaxVertexProgramLocalParams = MAX_NV_VERTEX_PROGRAM_PARAMS; + ctx->Const.MaxVertexProgramEnvParams = MAX_NV_VERTEX_PROGRAM_PARAMS;/*XXX*/ + ctx->Const.MaxVertexProgramAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS; +#endif +#if FEATURE_ARB_fragment_program + ctx->Const.MaxFragmentProgramInstructions = MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS; + ctx->Const.MaxFragmentProgramAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS; + ctx->Const.MaxFragmentProgramTemps = MAX_NV_FRAGMENT_PROGRAM_TEMPS; + ctx->Const.MaxFragmentProgramLocalParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS; + ctx->Const.MaxFragmentProgramEnvParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;/*XXX*/ + ctx->Const.MaxFragmentProgramAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS; + ctx->Const.MaxFragmentProgramAluInstructions = MAX_FRAGMENT_PROGRAM_ALU_INSTRUCTIONS; + ctx->Const.MaxFragmentProgramTexInstructions = MAX_FRAGMENT_PROGRAM_TEX_INSTRUCTIONS; + ctx->Const.MaxFragmentProgramTexIndirections = MAX_FRAGMENT_PROGRAM_TEX_INDIRECTIONS; +#endif + + ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES; + ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH; + + /* If we're running in the X server, do bounds checking to prevent + * segfaults and server crashes! + */ +#if defined(XFree86LOADER) && defined(IN_MODULE) + ctx->Const.CheckArrayBounds = GL_TRUE; +#else + ctx->Const.CheckArrayBounds = GL_FALSE; +#endif + + ctx->Const.MaxDrawBuffers = MAX_DRAW_BUFFERS; + + /* GL_OES_read_format */ + ctx->Const.ColorReadFormat = GL_RGBA; + ctx->Const.ColorReadType = GL_UNSIGNED_BYTE; + +#if FEATURE_EXT_framebuffer_object + ctx->Const.MaxColorAttachments = MAX_COLOR_ATTACHMENTS; + ctx->Const.MaxRenderbufferSize = MAX_WIDTH; +#endif + + /* sanity checks */ + ASSERT(ctx->Const.MaxTextureUnits == MAX2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits)); +} + + +/** + * Initialize the attribute groups in a GL context. + * + * \param ctx GL context. + * + * Initializes all the attributes, calling the respective <tt>init*</tt> + * functions for the more complex data structures. + */ +static GLboolean +init_attrib_groups( GLcontext *ctx ) +{ + assert(ctx); + + /* Constants */ + _mesa_init_constants( ctx ); + + /* Extensions */ + _mesa_init_extensions( ctx ); + + /* Attribute Groups */ + _mesa_init_accum( ctx ); + _mesa_init_attrib( ctx ); + _mesa_init_buffer_objects( ctx ); + _mesa_init_color( ctx ); + _mesa_init_colortables( ctx ); + _mesa_init_current( ctx ); + _mesa_init_depth( ctx ); + _mesa_init_debug( ctx ); + _mesa_init_display_list( ctx ); + _mesa_init_eval( ctx ); + _mesa_init_feedback( ctx ); + _mesa_init_fog( ctx ); + _mesa_init_histogram( ctx ); + _mesa_init_hint( ctx ); + _mesa_init_line( ctx ); + _mesa_init_lighting( ctx ); + _mesa_init_matrix( ctx ); + _mesa_init_multisample( ctx ); + _mesa_init_occlude( ctx ); + _mesa_init_pixel( ctx ); + _mesa_init_point( ctx ); + _mesa_init_polygon( ctx ); + _mesa_init_program( ctx ); + _mesa_init_rastpos( ctx ); + _mesa_init_scissor( ctx ); + _mesa_init_shaderobjects (ctx); + _mesa_init_stencil( ctx ); + _mesa_init_transform( ctx ); + _mesa_init_varray( ctx ); + _mesa_init_viewport( ctx ); + + if (!_mesa_init_texture( ctx )) + return GL_FALSE; + + _mesa_init_texture_s3tc( ctx ); + _mesa_init_texture_fxt1( ctx ); + + /* Miscellaneous */ + ctx->NewState = _NEW_ALL; + ctx->ErrorValue = (GLenum) GL_NO_ERROR; + ctx->_Facing = 0; +#if CHAN_TYPE == GL_FLOAT + ctx->ClampFragmentColors = GL_FALSE; /* XXX temporary */ +#else + ctx->ClampFragmentColors = GL_TRUE; +#endif + ctx->ClampVertexColors = GL_TRUE; + + return GL_TRUE; +} + + +/** + * This is the default function we plug into all dispatch table slots + * This helps prevents a segfault when someone calls a GL function without + * first checking if the extension's supported. + */ +static int +generic_nop(void) +{ + _mesa_problem(NULL, "User called no-op dispatch function (an unsupported extension function?)"); + return 0; +} + + +/** + * Allocate and initialize a new dispatch table. + */ +static struct _glapi_table * +alloc_dispatch_table(void) +{ + /* Find the larger of Mesa's dispatch table and libGL's dispatch table. + * In practice, this'll be the same for stand-alone Mesa. But for DRI + * Mesa we do this to accomodate different versions of libGL and various + * DRI drivers. + */ + GLint numEntries = MAX2(_glapi_get_dispatch_table_size(), + sizeof(struct _glapi_table) / sizeof(_glapi_proc)); + struct _glapi_table *table = + (struct _glapi_table *) _mesa_malloc(numEntries * sizeof(_glapi_proc)); + if (table) { + _glapi_proc *entry = (_glapi_proc *) table; + GLint i; + for (i = 0; i < numEntries; i++) { + entry[i] = (_glapi_proc) generic_nop; + } + } + return table; +} + + +/** + * Initialize a GLcontext struct (rendering context). + * + * This includes allocating all the other structs and arrays which hang off of + * the context by pointers. + * Note that the driver needs to pass in its dd_function_table here since + * we need to at least call driverFunctions->NewTextureObject to create the + * default texture objects. + * + * Called by _mesa_create_context(). + * + * Performs the imports and exports callback tables initialization, and + * miscellaneous one-time initializations. If no shared context is supplied one + * is allocated, and increase its reference count. Setups the GL API dispatch + * tables. Initialize the TNL module. Sets the maximum Z buffer depth. + * Finally queries the \c MESA_DEBUG and \c MESA_VERBOSE environment variables + * for debug flags. + * + * \param ctx the context to initialize + * \param visual describes the visual attributes for this context + * \param share_list points to context to share textures, display lists, + * etc with, or NULL + * \param driverFunctions table of device driver functions for this context + * to use + * \param driverContext pointer to driver-specific context data + */ +GLboolean +_mesa_initialize_context( GLcontext *ctx, + const GLvisual *visual, + GLcontext *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext ) +{ + ASSERT(driverContext); + assert(driverFunctions->NewTextureObject); + assert(driverFunctions->FreeTexImageData); + + /* If the driver wants core Mesa to use special imports, it'll have to + * override these defaults. + */ + _mesa_init_default_imports( &(ctx->imports), driverContext ); + + /* initialize the exports (Mesa functions called by the window system) */ + _mesa_init_default_exports( &(ctx->exports) ); + + /* misc one-time initializations */ + one_time_init(ctx); + + ctx->Visual = *visual; + ctx->DrawBuffer = NULL; + ctx->ReadBuffer = NULL; + ctx->WinSysDrawBuffer = NULL; + ctx->WinSysReadBuffer = NULL; + + /* Plug in driver functions and context pointer here. + * This is important because when we call alloc_shared_state() below + * we'll call ctx->Driver.NewTextureObject() to create the default + * textures. + */ + ctx->Driver = *driverFunctions; + ctx->DriverCtx = driverContext; + + if (share_list) { + /* share state with another context */ + ctx->Shared = share_list->Shared; + } + else { + /* allocate new, unshared state */ + if (!alloc_shared_state( ctx )) { + return GL_FALSE; + } + } + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + ctx->Shared->RefCount++; + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + if (!init_attrib_groups( ctx )) { + free_shared_state(ctx, ctx->Shared); + return GL_FALSE; + } + + /* setup the API dispatch tables */ + ctx->Exec = alloc_dispatch_table(); + ctx->Save = alloc_dispatch_table(); + if (!ctx->Exec || !ctx->Save) { + free_shared_state(ctx, ctx->Shared); + if (ctx->Exec) + _mesa_free(ctx->Exec); + } + _mesa_init_exec_table(ctx->Exec); + ctx->CurrentDispatch = ctx->Exec; +#if _HAVE_FULL_GL + _mesa_init_dlist_table(ctx->Save); + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); + /* Neutral tnl module stuff */ + _mesa_init_exec_vtxfmt( ctx ); + ctx->TnlModule.Current = NULL; + ctx->TnlModule.SwapCount = 0; +#endif + + ctx->_MaintainTexEnvProgram = (_mesa_getenv("MESA_TEX_PROG") != NULL); + ctx->_MaintainTnlProgram = (_mesa_getenv("MESA_TNL_PROG") != NULL); + + return GL_TRUE; +} + + +/** + * Allocate and initialize a GLcontext structure. + * Note that the driver needs to pass in its dd_function_table here since + * we need to at least call driverFunctions->NewTextureObject to initialize + * the rendering context. + * + * \param visual a GLvisual pointer (we copy the struct contents) + * \param share_list another context to share display lists with or NULL + * \param driverFunctions points to the dd_function_table into which the + * driver has plugged in all its special functions. + * \param driverCtx points to the device driver's private context state + * + * \return pointer to a new __GLcontextRec or NULL if error. + */ +GLcontext * +_mesa_create_context( const GLvisual *visual, + GLcontext *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext ) + +{ + GLcontext *ctx; + + ASSERT(visual); + ASSERT(driverContext); + + ctx = (GLcontext *) _mesa_calloc(sizeof(GLcontext)); + if (!ctx) + return NULL; + + if (_mesa_initialize_context(ctx, visual, share_list, + driverFunctions, driverContext)) { + return ctx; + } + else { + _mesa_free(ctx); + return NULL; + } +} + + +/** + * Free the data associated with the given context. + * + * But doesn't free the GLcontext struct itself. + * + * \sa _mesa_initialize_context() and init_attrib_groups(). + */ +void +_mesa_free_context_data( GLcontext *ctx ) +{ + /* if we're destroying the current context, unbind it first */ + if (ctx == _mesa_get_current_context()) { + _mesa_make_current(NULL, NULL, NULL); + } + + _mesa_free_lighting_data( ctx ); + _mesa_free_eval_data( ctx ); + _mesa_free_texture_data( ctx ); + _mesa_free_matrix_data( ctx ); + _mesa_free_viewport_data( ctx ); + _mesa_free_colortables_data( ctx ); + _mesa_free_program_data(ctx); + _mesa_free_occlude_data(ctx); + +#if FEATURE_ARB_vertex_buffer_object + _mesa_delete_buffer_object(ctx, ctx->Array.NullBufferObj); +#endif + + /* free dispatch tables */ + _mesa_free(ctx->Exec); + _mesa_free(ctx->Save); + + /* Shared context state (display lists, textures, etc) */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + ctx->Shared->RefCount--; + assert(ctx->Shared->RefCount >= 0); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + if (ctx->Shared->RefCount == 0) { + /* free shared state */ + free_shared_state( ctx, ctx->Shared ); + } + + if (ctx->Extensions.String) + FREE((void *) ctx->Extensions.String); +} + + +/** + * Destroy a GLcontext structure. + * + * \param ctx GL context. + * + * Calls _mesa_free_context_data() and frees the GLcontext structure itself. + */ +void +_mesa_destroy_context( GLcontext *ctx ) +{ + if (ctx) { + _mesa_free_context_data(ctx); + FREE( (void *) ctx ); + } +} + + +#if _HAVE_FULL_GL +/** + * Copy attribute groups from one context to another. + * + * \param src source context + * \param dst destination context + * \param mask bitwise OR of GL_*_BIT flags + * + * According to the bits specified in \p mask, copies the corresponding + * attributes from \p src into \p dst. For many of the attributes a simple \c + * memcpy is not enough due to the existence of internal pointers in their data + * structures. + */ +void +_mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask ) +{ + if (mask & GL_ACCUM_BUFFER_BIT) { + /* OK to memcpy */ + dst->Accum = src->Accum; + } + if (mask & GL_COLOR_BUFFER_BIT) { + /* OK to memcpy */ + dst->Color = src->Color; + } + if (mask & GL_CURRENT_BIT) { + /* OK to memcpy */ + dst->Current = src->Current; + } + if (mask & GL_DEPTH_BUFFER_BIT) { + /* OK to memcpy */ + dst->Depth = src->Depth; + } + if (mask & GL_ENABLE_BIT) { + /* no op */ + } + if (mask & GL_EVAL_BIT) { + /* OK to memcpy */ + dst->Eval = src->Eval; + } + if (mask & GL_FOG_BIT) { + /* OK to memcpy */ + dst->Fog = src->Fog; + } + if (mask & GL_HINT_BIT) { + /* OK to memcpy */ + dst->Hint = src->Hint; + } + if (mask & GL_LIGHTING_BIT) { + GLuint i; + /* begin with memcpy */ + MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_light) ); + /* fixup linked lists to prevent pointer insanity */ + make_empty_list( &(dst->Light.EnabledList) ); + for (i = 0; i < MAX_LIGHTS; i++) { + if (dst->Light.Light[i].Enabled) { + insert_at_tail(&(dst->Light.EnabledList), &(dst->Light.Light[i])); + } + } + } + if (mask & GL_LINE_BIT) { + /* OK to memcpy */ + dst->Line = src->Line; + } + if (mask & GL_LIST_BIT) { + /* OK to memcpy */ + dst->List = src->List; + } + if (mask & GL_PIXEL_MODE_BIT) { + /* OK to memcpy */ + dst->Pixel = src->Pixel; + } + if (mask & GL_POINT_BIT) { + /* OK to memcpy */ + dst->Point = src->Point; + } + if (mask & GL_POLYGON_BIT) { + /* OK to memcpy */ + dst->Polygon = src->Polygon; + } + if (mask & GL_POLYGON_STIPPLE_BIT) { + /* Use loop instead of MEMCPY due to problem with Portland Group's + * C compiler. Reported by John Stone. + */ + GLuint i; + for (i = 0; i < 32; i++) { + dst->PolygonStipple[i] = src->PolygonStipple[i]; + } + } + if (mask & GL_SCISSOR_BIT) { + /* OK to memcpy */ + dst->Scissor = src->Scissor; + } + if (mask & GL_STENCIL_BUFFER_BIT) { + /* OK to memcpy */ + dst->Stencil = src->Stencil; + } + if (mask & GL_TEXTURE_BIT) { + /* Cannot memcpy because of pointers */ + _mesa_copy_texture_state(src, dst); + } + if (mask & GL_TRANSFORM_BIT) { + /* OK to memcpy */ + dst->Transform = src->Transform; + } + if (mask & GL_VIEWPORT_BIT) { + /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */ + dst->Viewport.X = src->Viewport.X; + dst->Viewport.Y = src->Viewport.Y; + dst->Viewport.Width = src->Viewport.Width; + dst->Viewport.Height = src->Viewport.Height; + dst->Viewport.Near = src->Viewport.Near; + dst->Viewport.Far = src->Viewport.Far; + _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._WindowMap); + } + + /* XXX FIXME: Call callbacks? + */ + dst->NewState = _NEW_ALL; +} +#endif + + +/** + * Check if the given context can render into the given framebuffer + * by checking visual attributes. + * \return GL_TRUE if compatible, GL_FALSE otherwise. + */ +static GLboolean +check_compatible(const GLcontext *ctx, const GLframebuffer *buffer) +{ + const GLvisual *ctxvis = &ctx->Visual; + const GLvisual *bufvis = &buffer->Visual; + + if (ctxvis == bufvis) + return GL_TRUE; + + if (ctxvis->rgbMode != bufvis->rgbMode) + return GL_FALSE; + if (ctxvis->doubleBufferMode && !bufvis->doubleBufferMode) + return GL_FALSE; + if (ctxvis->stereoMode && !bufvis->stereoMode) + return GL_FALSE; + if (ctxvis->haveAccumBuffer && !bufvis->haveAccumBuffer) + return GL_FALSE; + if (ctxvis->haveDepthBuffer && !bufvis->haveDepthBuffer) + return GL_FALSE; + if (ctxvis->haveStencilBuffer && !bufvis->haveStencilBuffer) + return GL_FALSE; + if (ctxvis->redMask && ctxvis->redMask != bufvis->redMask) + return GL_FALSE; + if (ctxvis->greenMask && ctxvis->greenMask != bufvis->greenMask) + return GL_FALSE; + if (ctxvis->blueMask && ctxvis->blueMask != bufvis->blueMask) + return GL_FALSE; + if (ctxvis->depthBits && ctxvis->depthBits != bufvis->depthBits) + return GL_FALSE; + if (ctxvis->stencilBits && ctxvis->stencilBits != bufvis->stencilBits) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Bind the given context to the given draw-buffer and read-buffer and + * make it the current context for this thread. + * + * \param newCtx new GL context. If NULL then there will be no current GL + * context. + * \param drawBuffer draw framebuffer. + * \param readBuffer read framebuffer. + * + * Check that the context's and framebuffer's visuals are compatible, returning + * immediately otherwise. Sets the glapi current context via + * _glapi_set_context(). If \p newCtx is not NULL, associates \p drawBuffer and + * \p readBuffer with it and calls dd_function_table::ResizeBuffers if the buffers size has changed. + * Calls dd_function_table::MakeCurrent callback if defined. + * + * When a context is bound by the first time and the \c MESA_INFO environment + * variable is set it calls print_info() as an aid for remote user + * troubleshooting. + */ +void +_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, + GLframebuffer *readBuffer ) +{ + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(newCtx, "_mesa_make_current()\n"); + + /* Check that the context's and framebuffer's visuals are compatible. + */ + if (newCtx && drawBuffer && newCtx->DrawBuffer != drawBuffer) { + if (!check_compatible(newCtx, drawBuffer)) + return; + } + if (newCtx && readBuffer && newCtx->ReadBuffer != readBuffer) { + if (!check_compatible(newCtx, readBuffer)) + return; + } + +#if !defined(IN_DRI_DRIVER) + /* We call this function periodically (just here for now) in + * order to detect when multithreading has begun. In a DRI driver, this + * step is done by the driver loader (e.g., libGL). + */ + _glapi_check_multithread(); +#endif /* !defined(IN_DRI_DRIVER) */ + + _glapi_set_context((void *) newCtx); + ASSERT(_mesa_get_current_context() == newCtx); + + if (!newCtx) { + _glapi_set_dispatch(NULL); /* none current */ + } + else { + _glapi_set_dispatch(newCtx->CurrentDispatch); + + if (drawBuffer && readBuffer) { + /* TODO: check if newCtx and buffer's visual match??? */ + + ASSERT(drawBuffer->Name == 0); + ASSERT(readBuffer->Name == 0); + newCtx->WinSysDrawBuffer = drawBuffer; + newCtx->WinSysReadBuffer = readBuffer; + /* don't replace user-buffer bindings with window system buffer */ + if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) { + newCtx->DrawBuffer = drawBuffer; + newCtx->ReadBuffer = readBuffer; + } + + newCtx->NewState |= _NEW_BUFFERS; + +#if _HAVE_FULL_GL + if (!drawBuffer->Initialized) { + /* get initial window size */ + GLuint bufWidth, bufHeight; + /* ask device driver for size of the buffer */ + (*newCtx->Driver.GetBufferSize)(drawBuffer, &bufWidth, &bufHeight); + /* set initial buffer size */ + if (newCtx->Driver.ResizeBuffers) + newCtx->Driver.ResizeBuffers(newCtx, drawBuffer, + bufWidth, bufHeight); + drawBuffer->Initialized = GL_TRUE; + } + + if (readBuffer != drawBuffer && !readBuffer->Initialized) { + /* get initial window size */ + GLuint bufWidth, bufHeight; + /* ask device driver for size of the buffer */ + (*newCtx->Driver.GetBufferSize)(readBuffer, &bufWidth, &bufHeight); + /* set initial buffer size */ + if (newCtx->Driver.ResizeBuffers) + newCtx->Driver.ResizeBuffers(newCtx, readBuffer, + bufWidth, bufHeight); + readBuffer->Initialized = GL_TRUE; + } +#endif + if (newCtx->FirstTimeCurrent) { + /* set initial viewport and scissor size now */ + _mesa_set_viewport(newCtx, 0, 0, drawBuffer->Width, drawBuffer->Height); + newCtx->Scissor.Width = drawBuffer->Width; + newCtx->Scissor.Height = drawBuffer->Height; + } + } + + /* Alert the driver - usually passed on to the sw t&l module, + * but also used to detect threaded cases in the radeon codegen + * hw t&l module. + */ + if (newCtx->Driver.MakeCurrent) + newCtx->Driver.MakeCurrent( newCtx, drawBuffer, readBuffer ); + + /* We can use this to help debug user's problems. Tell them to set + * the MESA_INFO env variable before running their app. Then the + * first time each context is made current we'll print some useful + * information. + */ + if (newCtx->FirstTimeCurrent) { + if (_mesa_getenv("MESA_INFO")) { + _mesa_print_info(); + } + newCtx->FirstTimeCurrent = GL_FALSE; + } + } +} + + +/** + * Make context 'ctx' share the display lists, textures and programs + * that are associated with 'ctxToShare'. + * Any display lists, textures or programs associated with 'ctx' will + * be deleted if nobody else is sharing them. + */ +GLboolean +_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare) +{ + if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) { + ctx->Shared->RefCount--; + if (ctx->Shared->RefCount == 0) { + free_shared_state(ctx, ctx->Shared); + } + ctx->Shared = ctxToShare->Shared; + ctx->Shared->RefCount++; + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/** + * Get current context for the calling thread. + * + * \return pointer to the current GL context. + * + * Calls _glapi_get_context(). This isn't the fastest way to get the current + * context. If you need speed, see the #GET_CURRENT_CONTEXT macro in context.h. + */ +GLcontext * +_mesa_get_current_context( void ) +{ + return (GLcontext *) _glapi_get_context(); +} + +/** + * Get context's current API dispatch table. + * + * It'll either be the immediate-mode execute dispatcher or the display list + * compile dispatcher. + * + * \param ctx GL context. + * + * \return pointer to dispatch_table. + * + * Simply returns __GLcontextRec::CurrentDispatch. + */ +struct _glapi_table * +_mesa_get_dispatch(GLcontext *ctx) +{ + return ctx->CurrentDispatch; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Miscellaneous functions */ +/**********************************************************************/ +/*@{*/ + +/** + * Record an error. + * + * \param ctx GL context. + * \param error error code. + * + * Records the given error code and call the driver's dd_function_table::Error + * function if defined. + * + * \sa + * This is called via _mesa_error(). + */ +void +_mesa_record_error( GLcontext *ctx, GLenum error ) +{ + if (!ctx) + return; + + if (ctx->ErrorValue == GL_NO_ERROR) { + ctx->ErrorValue = error; + } + + /* Call device driver's error handler, if any. This is used on the Mac. */ + if (ctx->Driver.Error) { + (*ctx->Driver.Error)( ctx ); + } +} + +/** + * Execute glFinish(). + * + * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the + * dd_function_table::Finish driver callback, if not NULL. + */ +void GLAPIENTRY +_mesa_Finish( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (ctx->Driver.Finish) { + (*ctx->Driver.Finish)( ctx ); + } +} + +/** + * Execute glFlush(). + * + * Calls the #ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH macro and the + * dd_function_table::Flush driver callback, if not NULL. + */ +void GLAPIENTRY +_mesa_Flush( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (ctx->Driver.Flush) { + (*ctx->Driver.Flush)( ctx ); + } +} + + +/*@}*/ diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h new file mode 100644 index 00000000000..8b7e7c9952b --- /dev/null +++ b/src/mesa/main/context.h @@ -0,0 +1,340 @@ +/** + * \file context.h + * Mesa context/visual/framebuffer management functions. + * + * There are three Mesa data types which are meant to be used by device + * drivers: + * - GLcontext: this contains the Mesa rendering state + * - GLvisual: this describes the color buffer (RGB vs. ci), whether or not + * there's a depth buffer, stencil buffer, etc. + * - GLframebuffer: contains pointers to the depth buffer, stencil buffer, + * accum buffer and alpha buffers. + * + * These types should be encapsulated by corresponding device driver + * data types. See xmesa.h and xmesaP.h for an example. + * + * In OOP terms, GLcontext, GLvisual, and GLframebuffer are base classes + * which the device driver must derive from. + * + * The following functions create and destroy these data types. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef CONTEXT_H +#define CONTEXT_H + + +#include "glapi.h" +#include "imports.h" +#include "mtypes.h" + + +/**********************************************************************/ +/** \name Create/destroy a GLvisual. */ +/*@{*/ + +extern GLvisual * +_mesa_create_visual( GLboolean rgbFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits, + GLint indexBits, + GLint depthBits, + GLint stencilBits, + GLint accumRedBits, + GLint accumGreenBits, + GLint accumBlueBits, + GLint accumAlphaBits, + GLint numSamples ); + +extern GLboolean +_mesa_initialize_visual( GLvisual *v, + GLboolean rgbFlag, + GLboolean dbFlag, + GLboolean stereoFlag, + GLint redBits, + GLint greenBits, + GLint blueBits, + GLint alphaBits, + GLint indexBits, + GLint depthBits, + GLint stencilBits, + GLint accumRedBits, + GLint accumGreenBits, + GLint accumBlueBits, + GLint accumAlphaBits, + GLint numSamples ); + +extern void +_mesa_destroy_visual( GLvisual *vis ); + +/*@}*/ + + +/**********************************************************************/ +/** \name Create/destroy a GLcontext. */ +/*@{*/ + +extern GLcontext * +_mesa_create_context( const GLvisual *visual, + GLcontext *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext ); + +extern GLboolean +_mesa_initialize_context( GLcontext *ctx, + const GLvisual *visual, + GLcontext *share_list, + const struct dd_function_table *driverFunctions, + void *driverContext ); + +extern void +_mesa_free_context_data( GLcontext *ctx ); + +extern void +_mesa_destroy_context( GLcontext *ctx ); + + +extern void +_mesa_copy_context(const GLcontext *src, GLcontext *dst, GLuint mask); + + +extern void +_mesa_make_current( GLcontext *ctx, GLframebuffer *drawBuffer, + GLframebuffer *readBuffer ); + +extern GLboolean +_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare); + +extern GLcontext * +_mesa_get_current_context(void); + +/*@}*/ + + +/**********************************************************************/ +/** \name OpenGL SI-style export functions. */ +/*@{*/ + +extern GLboolean +_mesa_destroyContext(__GLcontext *gc); + +extern GLboolean +_mesa_loseCurrent(__GLcontext *gc); + +extern GLboolean +_mesa_makeCurrent(__GLcontext *gc); + +extern GLboolean +_mesa_shareContext(__GLcontext *gc, __GLcontext *gcShare); + +extern GLboolean +_mesa_copyContext(__GLcontext *dst, const __GLcontext *src, GLuint mask); + +extern GLboolean +_mesa_forceCurrent(__GLcontext *gc); + +extern GLboolean +_mesa_notifyResize(__GLcontext *gc); + +extern void +_mesa_notifyDestroy(__GLcontext *gc); + +extern void +_mesa_notifySwapBuffers(__GLcontext *gc); + +extern struct __GLdispatchStateRec * +_mesa_dispatchExec(__GLcontext *gc); + +extern void +_mesa_beginDispatchOverride(__GLcontext *gc); + +extern void +_mesa_endDispatchOverride(__GLcontext *gc); + +/*@}*/ + + +extern struct _glapi_table * +_mesa_get_dispatch(GLcontext *ctx); + + + +/**********************************************************************/ +/** \name Miscellaneous */ +/*@{*/ + +extern void +_mesa_record_error( GLcontext *ctx, GLenum error ); + + +extern void GLAPIENTRY +_mesa_Finish( void ); + +extern void GLAPIENTRY +_mesa_Flush( void ); + +/*@}*/ + + + +/**********************************************************************/ +/** \name Macros for contexts/flushing. */ +/*@{*/ + + +/** + * Flush vertices. + * + * \param ctx GL context. + * \param newstate new state. + * + * Checks if dd_function_table::NeedFlush is marked to flush stored vertices, + * and calls dd_function_table::FlushVertices if so. Marks + * __GLcontextRec::NewState with \p newstate. + */ +#define FLUSH_VERTICES(ctx, newstate) \ +do { \ + if (MESA_VERBOSE & VERBOSE_STATE) \ + _mesa_debug(ctx, "FLUSH_VERTICES in %s\n", MESA_FUNCTION);\ + if (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) \ + ctx->Driver.FlushVertices(ctx, FLUSH_STORED_VERTICES); \ + ctx->NewState |= newstate; \ +} while (0) + +/** + * Flush current state. + * + * \param ctx GL context. + * \param newstate new state. + * + * Checks if dd_function_table::NeedFlush is marked to flush current state, + * and calls dd_function_table::FlushVertices if so. Marks + * __GLcontextRec::NewState with \p newstate. + */ +#define FLUSH_CURRENT(ctx, newstate) \ +do { \ + if (MESA_VERBOSE & VERBOSE_STATE) \ + _mesa_debug(ctx, "FLUSH_CURRENT in %s\n", MESA_FUNCTION); \ + if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) \ + ctx->Driver.FlushVertices(ctx, FLUSH_UPDATE_CURRENT); \ + ctx->NewState |= newstate; \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair, with return value. + * + * \param ctx GL context. + * \param retval value to return value in case the assertion fails. + */ +#define ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval) \ +do { \ + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { \ + _mesa_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \ + return retval; \ + } \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair. + * + * \param ctx GL context. + */ +#define ASSERT_OUTSIDE_BEGIN_END(ctx) \ +do { \ + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { \ + _mesa_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \ + return; \ + } \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair and flush the vertices. + * + * \param ctx GL context. + */ +#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx) \ +do { \ + ASSERT_OUTSIDE_BEGIN_END(ctx); \ + FLUSH_VERTICES(ctx, 0); \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair and flush the vertices, with return value. + * + * \param ctx GL context. + * \param retval value to return value in case the assertion fails. + */ +#define ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval) \ +do { \ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, retval); \ + FLUSH_VERTICES(ctx, 0); \ +} while (0) + + +/*@}*/ + + + +/** + * Macros to help evaluate current state conditions + */ + +/*@{*/ + +/** + * Is the secondary color needed? + */ +#define NEED_SECONDARY_COLOR(CTX) \ + (((CTX)->Light.Enabled && \ + (CTX)->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) \ + || (CTX)->Fog.ColorSumEnabled \ + || ((CTX)->VertexProgram._Enabled && \ + ((CTX)->VertexProgram.Current->InputsRead & VERT_BIT_COLOR1)) \ + || ((CTX)->FragmentProgram._Enabled && \ + ((CTX)->FragmentProgram.Current->InputsRead & FRAG_BIT_COL1)) \ + ) + + +/** + * Is two-sided lighting in effect? + */ +#define NEED_TWO_SIDED_LIGHTING(CTX) \ + (ctx->Light.Enabled && ctx->Light.Model.TwoSide) + + +/*@}*/ + + +#endif diff --git a/src/mesa/main/convolve.c b/src/mesa/main/convolve.c new file mode 100644 index 00000000000..6b97c7f56cd --- /dev/null +++ b/src/mesa/main/convolve.c @@ -0,0 +1,1527 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Image convolution functions. + * + * Notes: filter kernel elements are indexed by <n> and <m> as in + * the GL spec. + */ + + +#include "glheader.h" +#include "bufferobj.h" +#include "colormac.h" +#include "convolve.h" +#include "context.h" +#include "image.h" +#include "mtypes.h" +#include "pixel.h" +#include "state.h" + + +/* + * Given an internalFormat token passed to glConvolutionFilter + * or glSeparableFilter, return the corresponding base format. + * Return -1 if invalid token. + */ +static GLint +base_filter_format( GLenum format ) +{ + switch (format) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return GL_ALPHA; + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return GL_INTENSITY; + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + default: + return -1; /* error */ + } +} + + +void GLAPIENTRY +_mesa_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *image) +{ + GLint baseFormat; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target != GL_CONVOLUTION_1D) { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(target)"); + return; + } + + baseFormat = base_filter_format(internalFormat); + if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(internalFormat)"); + return; + } + + if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { + _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter1D(width)"); + return; + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter1D(format or type)"); + return; + } + + if (format == GL_COLOR_INDEX || + format == GL_STENCIL_INDEX || + format == GL_DEPTH_COMPONENT || + format == GL_INTENSITY || + type == GL_BITMAP) { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter1D(format or type)"); + return; + } + + ctx->Convolution1D.Format = format; + ctx->Convolution1D.InternalFormat = internalFormat; + ctx->Convolution1D.Width = width; + ctx->Convolution1D.Height = 1; + + if (ctx->Unpack.BufferObj->Name) { + /* unpack filter from PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, + format, type, image)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glConvolutionFilter1D(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glConvolutionFilter1D(PBO is mapped)"); + return; + } + image = ADD_POINTERS(buf, image); + } + else if (!image) { + return; + } + + _mesa_unpack_color_span_float(ctx, width, GL_RGBA, + ctx->Convolution1D.Filter, + format, type, image, &ctx->Unpack, + 0); /* transferOps */ + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } + + _mesa_scale_and_bias_rgba(width, + (GLfloat (*)[4]) ctx->Convolution1D.Filter, + ctx->Pixel.ConvolutionFilterScale[0][0], + ctx->Pixel.ConvolutionFilterScale[0][1], + ctx->Pixel.ConvolutionFilterScale[0][2], + ctx->Pixel.ConvolutionFilterScale[0][3], + ctx->Pixel.ConvolutionFilterBias[0][0], + ctx->Pixel.ConvolutionFilterBias[0][1], + ctx->Pixel.ConvolutionFilterBias[0][2], + ctx->Pixel.ConvolutionFilterBias[0][3]); + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image) +{ + GLint baseFormat; + GLint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target != GL_CONVOLUTION_2D) { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(target)"); + return; + } + + baseFormat = base_filter_format(internalFormat); + if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(internalFormat)"); + return; + } + + if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { + _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(width)"); + return; + } + if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { + _mesa_error(ctx, GL_INVALID_VALUE, "glConvolutionFilter2D(height)"); + return; + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glConvolutionFilter2D(format or type)"); + return; + } + if (format == GL_COLOR_INDEX || + format == GL_STENCIL_INDEX || + format == GL_DEPTH_COMPONENT || + format == GL_INTENSITY || + type == GL_BITMAP) { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionFilter2D(format or type)"); + return; + } + + /* this should have been caught earlier */ + assert(_mesa_components_in_format(format)); + + ctx->Convolution2D.Format = format; + ctx->Convolution2D.InternalFormat = internalFormat; + ctx->Convolution2D.Width = width; + ctx->Convolution2D.Height = height; + + if (ctx->Unpack.BufferObj->Name) { + /* unpack filter from PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1, + format, type, image)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glConvolutionFilter2D(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glConvolutionFilter2D(PBO is mapped)"); + return; + } + image = ADD_POINTERS(buf, image); + } + else if (!image) { + return; + } + + /* Unpack filter image. We always store filters in RGBA format. */ + for (i = 0; i < height; i++) { + const GLvoid *src = _mesa_image_address2d(&ctx->Unpack, image, width, + height, format, type, i, 0); + GLfloat *dst = ctx->Convolution2D.Filter + i * width * 4; + _mesa_unpack_color_span_float(ctx, width, GL_RGBA, dst, + format, type, src, &ctx->Unpack, + 0); /* transferOps */ + } + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } + + _mesa_scale_and_bias_rgba(width * height, + (GLfloat (*)[4]) ctx->Convolution2D.Filter, + ctx->Pixel.ConvolutionFilterScale[1][0], + ctx->Pixel.ConvolutionFilterScale[1][1], + ctx->Pixel.ConvolutionFilterScale[1][2], + ctx->Pixel.ConvolutionFilterScale[1][3], + ctx->Pixel.ConvolutionFilterBias[1][0], + ctx->Pixel.ConvolutionFilterBias[1][1], + ctx->Pixel.ConvolutionFilterBias[1][2], + ctx->Pixel.ConvolutionFilterBias[1][3]); + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint c; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (target) { + case GL_CONVOLUTION_1D: + c = 0; + break; + case GL_CONVOLUTION_2D: + c = 1; + break; + case GL_SEPARABLE_2D: + c = 2; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(target)"); + return; + } + + switch (pname) { + case GL_CONVOLUTION_BORDER_MODE: + if (param == (GLfloat) GL_REDUCE || + param == (GLfloat) GL_CONSTANT_BORDER || + param == (GLfloat) GL_REPLICATE_BORDER) { + ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(params)"); + return; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterf(pname)"); + return; + } + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint c; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (target) { + case GL_CONVOLUTION_1D: + c = 0; + break; + case GL_CONVOLUTION_2D: + c = 1; + break; + case GL_SEPARABLE_2D: + c = 2; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(target)"); + return; + } + + switch (pname) { + case GL_CONVOLUTION_BORDER_COLOR: + COPY_4V(ctx->Pixel.ConvolutionBorderColor[c], params); + break; + case GL_CONVOLUTION_BORDER_MODE: + if (params[0] == (GLfloat) GL_REDUCE || + params[0] == (GLfloat) GL_CONSTANT_BORDER || + params[0] == (GLfloat) GL_REPLICATE_BORDER) { + ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(params)"); + return; + } + break; + case GL_CONVOLUTION_FILTER_SCALE: + COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); + break; + case GL_CONVOLUTION_FILTER_BIAS: + COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameterfv(pname)"); + return; + } + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint param) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint c; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (target) { + case GL_CONVOLUTION_1D: + c = 0; + break; + case GL_CONVOLUTION_2D: + c = 1; + break; + case GL_SEPARABLE_2D: + c = 2; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(target)"); + return; + } + + switch (pname) { + case GL_CONVOLUTION_BORDER_MODE: + if (param == (GLint) GL_REDUCE || + param == (GLint) GL_CONSTANT_BORDER || + param == (GLint) GL_REPLICATE_BORDER) { + ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) param; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(params)"); + return; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteri(pname)"); + return; + } + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint c; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + switch (target) { + case GL_CONVOLUTION_1D: + c = 0; + break; + case GL_CONVOLUTION_2D: + c = 1; + break; + case GL_SEPARABLE_2D: + c = 2; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(target)"); + return; + } + + switch (pname) { + case GL_CONVOLUTION_BORDER_COLOR: + ctx->Pixel.ConvolutionBorderColor[c][0] = INT_TO_FLOAT(params[0]); + ctx->Pixel.ConvolutionBorderColor[c][1] = INT_TO_FLOAT(params[1]); + ctx->Pixel.ConvolutionBorderColor[c][2] = INT_TO_FLOAT(params[2]); + ctx->Pixel.ConvolutionBorderColor[c][3] = INT_TO_FLOAT(params[3]); + break; + case GL_CONVOLUTION_BORDER_MODE: + if (params[0] == (GLint) GL_REDUCE || + params[0] == (GLint) GL_CONSTANT_BORDER || + params[0] == (GLint) GL_REPLICATE_BORDER) { + ctx->Pixel.ConvolutionBorderMode[c] = (GLenum) params[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(params)"); + return; + } + break; + case GL_CONVOLUTION_FILTER_SCALE: + /* COPY_4V(ctx->Pixel.ConvolutionFilterScale[c], params); */ + /* need cast to prevent compiler warnings */ + ctx->Pixel.ConvolutionFilterScale[c][0] = (GLfloat) params[0]; + ctx->Pixel.ConvolutionFilterScale[c][1] = (GLfloat) params[1]; + ctx->Pixel.ConvolutionFilterScale[c][2] = (GLfloat) params[2]; + ctx->Pixel.ConvolutionFilterScale[c][3] = (GLfloat) params[3]; + break; + case GL_CONVOLUTION_FILTER_BIAS: + /* COPY_4V(ctx->Pixel.ConvolutionFilterBias[c], params); */ + /* need cast to prevent compiler warnings */ + ctx->Pixel.ConvolutionFilterBias[c][0] = (GLfloat) params[0]; + ctx->Pixel.ConvolutionFilterBias[c][1] = (GLfloat) params[1]; + ctx->Pixel.ConvolutionFilterBias[c][2] = (GLfloat) params[2]; + ctx->Pixel.ConvolutionFilterBias[c][3] = (GLfloat) params[3]; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glConvolutionParameteriv(pname)"); + return; + } + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width) +{ + GLint baseFormat; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target != GL_CONVOLUTION_1D) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(target)"); + return; + } + + baseFormat = base_filter_format(internalFormat); + if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter1D(internalFormat)"); + return; + } + + if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter1D(width)"); + return; + } + + ctx->Driver.CopyConvolutionFilter1D( ctx, target, + internalFormat, x, y, width); +} + + +void GLAPIENTRY +_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height) +{ + GLint baseFormat; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target != GL_CONVOLUTION_2D) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(target)"); + return; + } + + baseFormat = base_filter_format(internalFormat); + if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCopyConvolutionFilter2D(internalFormat)"); + return; + } + + if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(width)"); + return; + } + if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCopyConvolutionFilter2D(height)"); + return; + } + + ctx->Driver.CopyConvolutionFilter2D( ctx, target, internalFormat, x, y, + width, height ); +} + + +void GLAPIENTRY +_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, GLvoid *image) +{ + const struct gl_convolution_attrib *filter; + GLuint row; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)"); + return; + } + + if (format == GL_COLOR_INDEX || + format == GL_STENCIL_INDEX || + format == GL_DEPTH_COMPONENT || + format == GL_INTENSITY || + type == GL_BITMAP) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)"); + return; + } + + switch (target) { + case GL_CONVOLUTION_1D: + filter = &(ctx->Convolution1D); + break; + case GL_CONVOLUTION_2D: + filter = &(ctx->Convolution2D); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(target)"); + return; + } + + if (ctx->Pack.BufferObj->Name) { + /* Pack the filter into a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(2, &ctx->Pack, + filter->Width, filter->Height, + 1, format, type, image)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetConvolutionFilter(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetConvolutionFilter(PBO is mapped)"); + return; + } + image = ADD_POINTERS(image, buf); + } + + for (row = 0; row < filter->Height; row++) { + GLvoid *dst = _mesa_image_address2d(&ctx->Pack, image, filter->Width, + filter->Height, format, type, + row, 0); + const GLfloat *src = filter->Filter + row * filter->Width * 4; + _mesa_pack_rgba_span_float(ctx, filter->Width, + (const GLfloat (*)[4]) src, + format, type, dst, &ctx->Pack, 0); + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + +void GLAPIENTRY +_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_convolution_attrib *conv; + GLuint c; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (target) { + case GL_CONVOLUTION_1D: + c = 0; + conv = &ctx->Convolution1D; + break; + case GL_CONVOLUTION_2D: + c = 1; + conv = &ctx->Convolution2D; + break; + case GL_SEPARABLE_2D: + c = 2; + conv = &ctx->Separable2D; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(target)"); + return; + } + + switch (pname) { + case GL_CONVOLUTION_BORDER_COLOR: + COPY_4V(params, ctx->Pixel.ConvolutionBorderColor[c]); + break; + case GL_CONVOLUTION_BORDER_MODE: + *params = (GLfloat) ctx->Pixel.ConvolutionBorderMode[c]; + break; + case GL_CONVOLUTION_FILTER_SCALE: + COPY_4V(params, ctx->Pixel.ConvolutionFilterScale[c]); + break; + case GL_CONVOLUTION_FILTER_BIAS: + COPY_4V(params, ctx->Pixel.ConvolutionFilterBias[c]); + break; + case GL_CONVOLUTION_FORMAT: + *params = (GLfloat) conv->Format; + break; + case GL_CONVOLUTION_WIDTH: + *params = (GLfloat) conv->Width; + break; + case GL_CONVOLUTION_HEIGHT: + *params = (GLfloat) conv->Height; + break; + case GL_MAX_CONVOLUTION_WIDTH: + *params = (GLfloat) ctx->Const.MaxConvolutionWidth; + break; + case GL_MAX_CONVOLUTION_HEIGHT: + *params = (GLfloat) ctx->Const.MaxConvolutionHeight; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameterfv(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_convolution_attrib *conv; + GLuint c; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (target) { + case GL_CONVOLUTION_1D: + c = 0; + conv = &ctx->Convolution1D; + break; + case GL_CONVOLUTION_2D: + c = 1; + conv = &ctx->Convolution2D; + break; + case GL_SEPARABLE_2D: + c = 2; + conv = &ctx->Separable2D; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(target)"); + return; + } + + switch (pname) { + case GL_CONVOLUTION_BORDER_COLOR: + params[0] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][0]); + params[1] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][1]); + params[2] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][2]); + params[3] = FLOAT_TO_INT(ctx->Pixel.ConvolutionBorderColor[c][3]); + break; + case GL_CONVOLUTION_BORDER_MODE: + *params = (GLint) ctx->Pixel.ConvolutionBorderMode[c]; + break; + case GL_CONVOLUTION_FILTER_SCALE: + params[0] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][0]; + params[1] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][1]; + params[2] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][2]; + params[3] = (GLint) ctx->Pixel.ConvolutionFilterScale[c][3]; + break; + case GL_CONVOLUTION_FILTER_BIAS: + params[0] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][0]; + params[1] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][1]; + params[2] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][2]; + params[3] = (GLint) ctx->Pixel.ConvolutionFilterBias[c][3]; + break; + case GL_CONVOLUTION_FORMAT: + *params = (GLint) conv->Format; + break; + case GL_CONVOLUTION_WIDTH: + *params = (GLint) conv->Width; + break; + case GL_CONVOLUTION_HEIGHT: + *params = (GLint) conv->Height; + break; + case GL_MAX_CONVOLUTION_WIDTH: + *params = (GLint) ctx->Const.MaxConvolutionWidth; + break; + case GL_MAX_CONVOLUTION_HEIGHT: + *params = (GLint) ctx->Const.MaxConvolutionHeight; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionParameteriv(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span) +{ + const GLint colStart = MAX_CONVOLUTION_WIDTH * 4; + const struct gl_convolution_attrib *filter; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + if (target != GL_SEPARABLE_2D) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetSeparableFilter(target)"); + return; + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetConvolutionFilter(format or type)"); + return; + } + + if (format == GL_COLOR_INDEX || + format == GL_STENCIL_INDEX || + format == GL_DEPTH_COMPONENT || + format == GL_INTENSITY || + type == GL_BITMAP) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetConvolutionFilter(format or type)"); + return; + } + + filter = &ctx->Separable2D; + + if (ctx->Pack.BufferObj->Name) { + /* Pack filter into PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Width, 1, 1, + format, type, row)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetSeparableFilter(invalid PBO access, width)"); + return; + } + if (!_mesa_validate_pbo_access(1, &ctx->Pack, filter->Height, 1, 1, + format, type, column)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetSeparableFilter(invalid PBO access, height)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetSeparableFilter(PBO is mapped)"); + return; + } + row = ADD_POINTERS(buf, row); + column = ADD_POINTERS(buf, column); + } + + /* Row filter */ + if (row) { + GLvoid *dst = _mesa_image_address1d(&ctx->Pack, row, filter->Width, + format, type, 0); + _mesa_pack_rgba_span_float(ctx, filter->Width, + (const GLfloat (*)[4]) filter->Filter, + format, type, dst, &ctx->Pack, 0); + } + + /* Column filter */ + if (column) { + GLvoid *dst = _mesa_image_address1d(&ctx->Pack, column, filter->Height, + format, type, 0); + const GLfloat *src = filter->Filter + colStart; + _mesa_pack_rgba_span_float(ctx, filter->Height, + (const GLfloat (*)[4]) src, + format, type, dst, &ctx->Pack, 0); + } + + (void) span; /* unused at this time */ + + if (ctx->Pack.BufferObj->Name) { + /* Pack filter into PBO */ + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } +} + + +void GLAPIENTRY +_mesa_SeparableFilter2D(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column) +{ + const GLint colStart = MAX_CONVOLUTION_WIDTH * 4; + GLint baseFormat; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target != GL_SEPARABLE_2D) { + _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(target)"); + return; + } + + baseFormat = base_filter_format(internalFormat); + if (baseFormat < 0 || baseFormat == GL_COLOR_INDEX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(internalFormat)"); + return; + } + + if (width < 0 || width > MAX_CONVOLUTION_WIDTH) { + _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(width)"); + return; + } + if (height < 0 || height > MAX_CONVOLUTION_HEIGHT) { + _mesa_error(ctx, GL_INVALID_VALUE, "glSeparableFilter2D(height)"); + return; + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glSeparableFilter2D(format or type)"); + return; + } + + if (format == GL_COLOR_INDEX || + format == GL_STENCIL_INDEX || + format == GL_DEPTH_COMPONENT || + format == GL_INTENSITY || + type == GL_BITMAP) { + _mesa_error(ctx, GL_INVALID_ENUM, "glSeparableFilter2D(format or type)"); + return; + } + + ctx->Separable2D.Format = format; + ctx->Separable2D.InternalFormat = internalFormat; + ctx->Separable2D.Width = width; + ctx->Separable2D.Height = height; + + if (ctx->Unpack.BufferObj->Name) { + /* unpack filter from PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Unpack, width, 1, 1, + format, type, row)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glSeparableFilter2D(invalid PBO access, width)"); + return; + } + if (!_mesa_validate_pbo_access(1, &ctx->Unpack, height, 1, 1, + format, type, column)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glSeparableFilter2D(invalid PBO access, height)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glSeparableFilter2D(PBO is mapped)"); + return; + } + row = ADD_POINTERS(buf, row); + column = ADD_POINTERS(buf, column); + } + + /* unpack row filter */ + if (row) { + _mesa_unpack_color_span_float(ctx, width, GL_RGBA, + ctx->Separable2D.Filter, + format, type, row, &ctx->Unpack, + 0); /* transferOps */ + + _mesa_scale_and_bias_rgba(width, + (GLfloat (*)[4]) ctx->Separable2D.Filter, + ctx->Pixel.ConvolutionFilterScale[2][0], + ctx->Pixel.ConvolutionFilterScale[2][1], + ctx->Pixel.ConvolutionFilterScale[2][2], + ctx->Pixel.ConvolutionFilterScale[2][3], + ctx->Pixel.ConvolutionFilterBias[2][0], + ctx->Pixel.ConvolutionFilterBias[2][1], + ctx->Pixel.ConvolutionFilterBias[2][2], + ctx->Pixel.ConvolutionFilterBias[2][3]); + } + + /* unpack column filter */ + if (column) { + _mesa_unpack_color_span_float(ctx, height, GL_RGBA, + &ctx->Separable2D.Filter[colStart], + format, type, column, &ctx->Unpack, + 0); /* transferOps */ + + _mesa_scale_and_bias_rgba(height, + (GLfloat (*)[4]) (ctx->Separable2D.Filter + colStart), + ctx->Pixel.ConvolutionFilterScale[2][0], + ctx->Pixel.ConvolutionFilterScale[2][1], + ctx->Pixel.ConvolutionFilterScale[2][2], + ctx->Pixel.ConvolutionFilterScale[2][3], + ctx->Pixel.ConvolutionFilterBias[2][0], + ctx->Pixel.ConvolutionFilterBias[2][1], + ctx->Pixel.ConvolutionFilterBias[2][2], + ctx->Pixel.ConvolutionFilterBias[2][3]); + } + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } + + ctx->NewState |= _NEW_PIXEL; +} + + +/**********************************************************************/ +/*** image convolution functions ***/ +/**********************************************************************/ + +static void +convolve_1d_reduce(GLint srcWidth, const GLfloat src[][4], + GLint filterWidth, const GLfloat filter[][4], + GLfloat dest[][4]) +{ + GLint dstWidth; + GLint i, n; + + if (filterWidth >= 1) + dstWidth = srcWidth - (filterWidth - 1); + else + dstWidth = srcWidth; + + if (dstWidth <= 0) + return; /* null result */ + + for (i = 0; i < dstWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (n = 0; n < filterWidth; n++) { + sumR += src[i + n][RCOMP] * filter[n][RCOMP]; + sumG += src[i + n][GCOMP] * filter[n][GCOMP]; + sumB += src[i + n][BCOMP] * filter[n][BCOMP]; + sumA += src[i + n][ACOMP] * filter[n][ACOMP]; + } + dest[i][RCOMP] = sumR; + dest[i][GCOMP] = sumG; + dest[i][BCOMP] = sumB; + dest[i][ACOMP] = sumA; + } +} + + +static void +convolve_1d_constant(GLint srcWidth, const GLfloat src[][4], + GLint filterWidth, const GLfloat filter[][4], + GLfloat dest[][4], + const GLfloat borderColor[4]) +{ + const GLint halfFilterWidth = filterWidth / 2; + GLint i, n; + + for (i = 0; i < srcWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (n = 0; n < filterWidth; n++) { + if (i + n < halfFilterWidth || i + n - halfFilterWidth >= srcWidth) { + sumR += borderColor[RCOMP] * filter[n][RCOMP]; + sumG += borderColor[GCOMP] * filter[n][GCOMP]; + sumB += borderColor[BCOMP] * filter[n][BCOMP]; + sumA += borderColor[ACOMP] * filter[n][ACOMP]; + } + else { + sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP]; + sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP]; + sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP]; + sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP]; + } + } + dest[i][RCOMP] = sumR; + dest[i][GCOMP] = sumG; + dest[i][BCOMP] = sumB; + dest[i][ACOMP] = sumA; + } +} + + +static void +convolve_1d_replicate(GLint srcWidth, const GLfloat src[][4], + GLint filterWidth, const GLfloat filter[][4], + GLfloat dest[][4]) +{ + const GLint halfFilterWidth = filterWidth / 2; + GLint i, n; + + for (i = 0; i < srcWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (n = 0; n < filterWidth; n++) { + if (i + n < halfFilterWidth) { + sumR += src[0][RCOMP] * filter[n][RCOMP]; + sumG += src[0][GCOMP] * filter[n][GCOMP]; + sumB += src[0][BCOMP] * filter[n][BCOMP]; + sumA += src[0][ACOMP] * filter[n][ACOMP]; + } + else if (i + n - halfFilterWidth >= srcWidth) { + sumR += src[srcWidth - 1][RCOMP] * filter[n][RCOMP]; + sumG += src[srcWidth - 1][GCOMP] * filter[n][GCOMP]; + sumB += src[srcWidth - 1][BCOMP] * filter[n][BCOMP]; + sumA += src[srcWidth - 1][ACOMP] * filter[n][ACOMP]; + } + else { + sumR += src[i + n - halfFilterWidth][RCOMP] * filter[n][RCOMP]; + sumG += src[i + n - halfFilterWidth][GCOMP] * filter[n][GCOMP]; + sumB += src[i + n - halfFilterWidth][BCOMP] * filter[n][BCOMP]; + sumA += src[i + n - halfFilterWidth][ACOMP] * filter[n][ACOMP]; + } + } + dest[i][RCOMP] = sumR; + dest[i][GCOMP] = sumG; + dest[i][BCOMP] = sumB; + dest[i][ACOMP] = sumA; + } +} + + +static void +convolve_2d_reduce(GLint srcWidth, GLint srcHeight, + const GLfloat src[][4], + GLint filterWidth, GLint filterHeight, + const GLfloat filter[][4], + GLfloat dest[][4]) +{ + GLint dstWidth, dstHeight; + GLint i, j, n, m; + + if (filterWidth >= 1) + dstWidth = srcWidth - (filterWidth - 1); + else + dstWidth = srcWidth; + + if (filterHeight >= 1) + dstHeight = srcHeight - (filterHeight - 1); + else + dstHeight = srcHeight; + + if (dstWidth <= 0 || dstHeight <= 0) + return; + + for (j = 0; j < dstHeight; j++) { + for (i = 0; i < dstWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (m = 0; m < filterHeight; m++) { + for (n = 0; n < filterWidth; n++) { + const GLint k = (j + m) * srcWidth + i + n; + const GLint f = m * filterWidth + n; + sumR += src[k][RCOMP] * filter[f][RCOMP]; + sumG += src[k][GCOMP] * filter[f][GCOMP]; + sumB += src[k][BCOMP] * filter[f][BCOMP]; + sumA += src[k][ACOMP] * filter[f][ACOMP]; + } + } + dest[j * dstWidth + i][RCOMP] = sumR; + dest[j * dstWidth + i][GCOMP] = sumG; + dest[j * dstWidth + i][BCOMP] = sumB; + dest[j * dstWidth + i][ACOMP] = sumA; + } + } +} + + +static void +convolve_2d_constant(GLint srcWidth, GLint srcHeight, + const GLfloat src[][4], + GLint filterWidth, GLint filterHeight, + const GLfloat filter[][4], + GLfloat dest[][4], + const GLfloat borderColor[4]) +{ + const GLint halfFilterWidth = filterWidth / 2; + const GLint halfFilterHeight = filterHeight / 2; + GLint i, j, n, m; + + for (j = 0; j < srcHeight; j++) { + for (i = 0; i < srcWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (m = 0; m < filterHeight; m++) { + for (n = 0; n < filterWidth; n++) { + const GLint f = m * filterWidth + n; + const GLint is = i + n - halfFilterWidth; + const GLint js = j + m - halfFilterHeight; + if (is < 0 || is >= srcWidth || + js < 0 || js >= srcHeight) { + sumR += borderColor[RCOMP] * filter[f][RCOMP]; + sumG += borderColor[GCOMP] * filter[f][GCOMP]; + sumB += borderColor[BCOMP] * filter[f][BCOMP]; + sumA += borderColor[ACOMP] * filter[f][ACOMP]; + } + else { + const GLint k = js * srcWidth + is; + sumR += src[k][RCOMP] * filter[f][RCOMP]; + sumG += src[k][GCOMP] * filter[f][GCOMP]; + sumB += src[k][BCOMP] * filter[f][BCOMP]; + sumA += src[k][ACOMP] * filter[f][ACOMP]; + } + } + } + dest[j * srcWidth + i][RCOMP] = sumR; + dest[j * srcWidth + i][GCOMP] = sumG; + dest[j * srcWidth + i][BCOMP] = sumB; + dest[j * srcWidth + i][ACOMP] = sumA; + } + } +} + + +static void +convolve_2d_replicate(GLint srcWidth, GLint srcHeight, + const GLfloat src[][4], + GLint filterWidth, GLint filterHeight, + const GLfloat filter[][4], + GLfloat dest[][4]) +{ + const GLint halfFilterWidth = filterWidth / 2; + const GLint halfFilterHeight = filterHeight / 2; + GLint i, j, n, m; + + for (j = 0; j < srcHeight; j++) { + for (i = 0; i < srcWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (m = 0; m < filterHeight; m++) { + for (n = 0; n < filterWidth; n++) { + const GLint f = m * filterWidth + n; + GLint is = i + n - halfFilterWidth; + GLint js = j + m - halfFilterHeight; + GLint k; + if (is < 0) + is = 0; + else if (is >= srcWidth) + is = srcWidth - 1; + if (js < 0) + js = 0; + else if (js >= srcHeight) + js = srcHeight - 1; + k = js * srcWidth + is; + sumR += src[k][RCOMP] * filter[f][RCOMP]; + sumG += src[k][GCOMP] * filter[f][GCOMP]; + sumB += src[k][BCOMP] * filter[f][BCOMP]; + sumA += src[k][ACOMP] * filter[f][ACOMP]; + } + } + dest[j * srcWidth + i][RCOMP] = sumR; + dest[j * srcWidth + i][GCOMP] = sumG; + dest[j * srcWidth + i][BCOMP] = sumB; + dest[j * srcWidth + i][ACOMP] = sumA; + } + } +} + + +static void +convolve_sep_reduce(GLint srcWidth, GLint srcHeight, + const GLfloat src[][4], + GLint filterWidth, GLint filterHeight, + const GLfloat rowFilt[][4], + const GLfloat colFilt[][4], + GLfloat dest[][4]) +{ + GLint dstWidth, dstHeight; + GLint i, j, n, m; + + if (filterWidth >= 1) + dstWidth = srcWidth - (filterWidth - 1); + else + dstWidth = srcWidth; + + if (filterHeight >= 1) + dstHeight = srcHeight - (filterHeight - 1); + else + dstHeight = srcHeight; + + if (dstWidth <= 0 || dstHeight <= 0) + return; + + for (j = 0; j < dstHeight; j++) { + for (i = 0; i < dstWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (m = 0; m < filterHeight; m++) { + for (n = 0; n < filterWidth; n++) { + GLint k = (j + m) * srcWidth + i + n; + sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; + sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; + sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; + sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; + } + } + dest[j * dstWidth + i][RCOMP] = sumR; + dest[j * dstWidth + i][GCOMP] = sumG; + dest[j * dstWidth + i][BCOMP] = sumB; + dest[j * dstWidth + i][ACOMP] = sumA; + } + } +} + + +static void +convolve_sep_constant(GLint srcWidth, GLint srcHeight, + const GLfloat src[][4], + GLint filterWidth, GLint filterHeight, + const GLfloat rowFilt[][4], + const GLfloat colFilt[][4], + GLfloat dest[][4], + const GLfloat borderColor[4]) +{ + const GLint halfFilterWidth = filterWidth / 2; + const GLint halfFilterHeight = filterHeight / 2; + GLint i, j, n, m; + + for (j = 0; j < srcHeight; j++) { + for (i = 0; i < srcWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (m = 0; m < filterHeight; m++) { + for (n = 0; n < filterWidth; n++) { + const GLint is = i + n - halfFilterWidth; + const GLint js = j + m - halfFilterHeight; + if (is < 0 || is >= srcWidth || + js < 0 || js >= srcHeight) { + sumR += borderColor[RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; + sumG += borderColor[GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; + sumB += borderColor[BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; + sumA += borderColor[ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; + } + else { + GLint k = js * srcWidth + is; + sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; + sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; + sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; + sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; + } + + } + } + dest[j * srcWidth + i][RCOMP] = sumR; + dest[j * srcWidth + i][GCOMP] = sumG; + dest[j * srcWidth + i][BCOMP] = sumB; + dest[j * srcWidth + i][ACOMP] = sumA; + } + } +} + + +static void +convolve_sep_replicate(GLint srcWidth, GLint srcHeight, + const GLfloat src[][4], + GLint filterWidth, GLint filterHeight, + const GLfloat rowFilt[][4], + const GLfloat colFilt[][4], + GLfloat dest[][4]) +{ + const GLint halfFilterWidth = filterWidth / 2; + const GLint halfFilterHeight = filterHeight / 2; + GLint i, j, n, m; + + for (j = 0; j < srcHeight; j++) { + for (i = 0; i < srcWidth; i++) { + GLfloat sumR = 0.0; + GLfloat sumG = 0.0; + GLfloat sumB = 0.0; + GLfloat sumA = 0.0; + for (m = 0; m < filterHeight; m++) { + for (n = 0; n < filterWidth; n++) { + GLint is = i + n - halfFilterWidth; + GLint js = j + m - halfFilterHeight; + GLint k; + if (is < 0) + is = 0; + else if (is >= srcWidth) + is = srcWidth - 1; + if (js < 0) + js = 0; + else if (js >= srcHeight) + js = srcHeight - 1; + k = js * srcWidth + is; + sumR += src[k][RCOMP] * rowFilt[n][RCOMP] * colFilt[m][RCOMP]; + sumG += src[k][GCOMP] * rowFilt[n][GCOMP] * colFilt[m][GCOMP]; + sumB += src[k][BCOMP] * rowFilt[n][BCOMP] * colFilt[m][BCOMP]; + sumA += src[k][ACOMP] * rowFilt[n][ACOMP] * colFilt[m][ACOMP]; + } + } + dest[j * srcWidth + i][RCOMP] = sumR; + dest[j * srcWidth + i][GCOMP] = sumG; + dest[j * srcWidth + i][BCOMP] = sumB; + dest[j * srcWidth + i][ACOMP] = sumA; + } + } +} + + + +void +_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width, + const GLfloat *srcImage, GLfloat *dstImage) +{ + switch (ctx->Pixel.ConvolutionBorderMode[0]) { + case GL_REDUCE: + convolve_1d_reduce(*width, (const GLfloat (*)[4]) srcImage, + ctx->Convolution1D.Width, + (const GLfloat (*)[4]) ctx->Convolution1D.Filter, + (GLfloat (*)[4]) dstImage); + *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1); + break; + case GL_CONSTANT_BORDER: + convolve_1d_constant(*width, (const GLfloat (*)[4]) srcImage, + ctx->Convolution1D.Width, + (const GLfloat (*)[4]) ctx->Convolution1D.Filter, + (GLfloat (*)[4]) dstImage, + ctx->Pixel.ConvolutionBorderColor[0]); + break; + case GL_REPLICATE_BORDER: + convolve_1d_replicate(*width, (const GLfloat (*)[4]) srcImage, + ctx->Convolution1D.Width, + (const GLfloat (*)[4]) ctx->Convolution1D.Filter, + (GLfloat (*)[4]) dstImage); + break; + default: + ; + } +} + + +void +_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height, + const GLfloat *srcImage, GLfloat *dstImage) +{ + switch (ctx->Pixel.ConvolutionBorderMode[1]) { + case GL_REDUCE: + convolve_2d_reduce(*width, *height, + (const GLfloat (*)[4]) srcImage, + ctx->Convolution2D.Width, + ctx->Convolution2D.Height, + (const GLfloat (*)[4]) ctx->Convolution2D.Filter, + (GLfloat (*)[4]) dstImage); + *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1); + *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1); + break; + case GL_CONSTANT_BORDER: + convolve_2d_constant(*width, *height, + (const GLfloat (*)[4]) srcImage, + ctx->Convolution2D.Width, + ctx->Convolution2D.Height, + (const GLfloat (*)[4]) ctx->Convolution2D.Filter, + (GLfloat (*)[4]) dstImage, + ctx->Pixel.ConvolutionBorderColor[1]); + break; + case GL_REPLICATE_BORDER: + convolve_2d_replicate(*width, *height, + (const GLfloat (*)[4]) srcImage, + ctx->Convolution2D.Width, + ctx->Convolution2D.Height, + (const GLfloat (*)[4])ctx->Convolution2D.Filter, + (GLfloat (*)[4]) dstImage); + break; + default: + ; + } +} + + +void +_mesa_convolve_sep_image(const GLcontext *ctx, + GLsizei *width, GLsizei *height, + const GLfloat *srcImage, GLfloat *dstImage) +{ + const GLfloat *rowFilter = ctx->Separable2D.Filter; + const GLfloat *colFilter = rowFilter + 4 * MAX_CONVOLUTION_WIDTH; + + switch (ctx->Pixel.ConvolutionBorderMode[2]) { + case GL_REDUCE: + convolve_sep_reduce(*width, *height, + (const GLfloat (*)[4]) srcImage, + ctx->Separable2D.Width, + ctx->Separable2D.Height, + (const GLfloat (*)[4]) rowFilter, + (const GLfloat (*)[4]) colFilter, + (GLfloat (*)[4]) dstImage); + *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1); + *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1); + break; + case GL_CONSTANT_BORDER: + convolve_sep_constant(*width, *height, + (const GLfloat (*)[4]) srcImage, + ctx->Separable2D.Width, + ctx->Separable2D.Height, + (const GLfloat (*)[4]) rowFilter, + (const GLfloat (*)[4]) colFilter, + (GLfloat (*)[4]) dstImage, + ctx->Pixel.ConvolutionBorderColor[2]); + break; + case GL_REPLICATE_BORDER: + convolve_sep_replicate(*width, *height, + (const GLfloat (*)[4]) srcImage, + ctx->Separable2D.Width, + ctx->Separable2D.Height, + (const GLfloat (*)[4]) rowFilter, + (const GLfloat (*)[4]) colFilter, + (GLfloat (*)[4]) dstImage); + break; + default: + ; + } +} + + + +/* + * This function computes an image's size after convolution. + * If the convolution border mode is GL_REDUCE, the post-convolution + * image will be smaller than the original. + */ +void +_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions, + GLsizei *width, GLsizei *height) +{ + if (ctx->Pixel.Convolution1DEnabled + && dimensions == 1 + && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) { + *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1); + } + else if (ctx->Pixel.Convolution2DEnabled + && dimensions > 1 + && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) { + *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1); + *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1); + } + else if (ctx->Pixel.Separable2DEnabled + && dimensions > 1 + && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) { + *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1); + *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1); + } +} diff --git a/src/mesa/main/convolve.h b/src/mesa/main/convolve.h new file mode 100644 index 00000000000..4505cdae01e --- /dev/null +++ b/src/mesa/main/convolve.h @@ -0,0 +1,114 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef CONVOLVE_H +#define CONVOLVE_H + + +#include "mtypes.h" + + +#if _HAVE_FULL_GL +extern void GLAPIENTRY +_mesa_ConvolutionFilter1D(GLenum target, GLenum internalformat, GLsizei width, + GLenum format, GLenum type, const GLvoid *image); + +extern void GLAPIENTRY +_mesa_ConvolutionFilter2D(GLenum target, GLenum internalformat, GLsizei width, + GLsizei height, GLenum format, GLenum type, + const GLvoid *image); + +extern void GLAPIENTRY +_mesa_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat params); + +extern void GLAPIENTRY +_mesa_ConvolutionParameterfv(GLenum target, GLenum pname, + const GLfloat *params); + +extern void GLAPIENTRY +_mesa_ConvolutionParameteri(GLenum target, GLenum pname, GLint params); + +extern void GLAPIENTRY +_mesa_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params); + +extern void GLAPIENTRY +_mesa_CopyConvolutionFilter1D(GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width); + +extern void GLAPIENTRY +_mesa_CopyConvolutionFilter2D(GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height); + +extern void GLAPIENTRY +_mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, + GLvoid *image); + +extern void GLAPIENTRY +_mesa_GetConvolutionParameterfv(GLenum target, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetConvolutionParameteriv(GLenum target, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type, + GLvoid *row, GLvoid *column, GLvoid *span); + +extern void GLAPIENTRY +_mesa_SeparableFilter2D(GLenum target, GLenum internalformat, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *row, const GLvoid *column); + + + +extern void +_mesa_convolve_1d_image(const GLcontext *ctx, GLsizei *width, + const GLfloat *srcImage, GLfloat *dstImage); + + +extern void +_mesa_convolve_2d_image(const GLcontext *ctx, GLsizei *width, GLsizei *height, + const GLfloat *srcImage, GLfloat *dstImage); + + +extern void +_mesa_convolve_sep_image(const GLcontext *ctx, + GLsizei *width, GLsizei *height, + const GLfloat *srcImage, GLfloat *dstImage); + + +extern void +_mesa_adjust_image_for_convolution(const GLcontext *ctx, GLuint dimensions, + GLsizei *width, GLsizei *height); + +#else +#define _mesa_adjust_image_for_convolution(c, d, w, h) ((void)0) +#define _mesa_convolve_1d_image(c,w,s,d) ((void)0) +#define _mesa_convolve_2d_image(c,w,h,s,d) ((void)0) +#define _mesa_convolve_sep_image(c,w,h,s,d) ((void)0) +#endif + +#endif diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h new file mode 100644 index 00000000000..e4c103c55e4 --- /dev/null +++ b/src/mesa/main/dd.h @@ -0,0 +1,1063 @@ +/** + * \file dd.h + * Device driver interfaces. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef DD_INCLUDED +#define DD_INCLUDED + +/* THIS FILE ONLY INCLUDED BY mtypes.h !!!!! */ + +struct gl_pixelstore_attrib; +struct mesa_display_list; + +/** + * Device driver function table. + * Core Mesa uses these function pointers to call into device drivers. + * Most of these functions directly correspond to OpenGL state commands. + * Core Mesa will call these functions after error checking has been done + * so that the drivers don't have to worry about error testing. + * + * Vertex transformation/clipping/lighting is patched into the T&L module. + * Rasterization functions are patched into the swrast module. + * + * Note: when new functions are added here, the drivers/common/driverfuncs.c + * file should be updated too!!! + */ +struct dd_function_table { + /** + * Return a string as needed by glGetString(). + * + * Only the GL_RENDERER token must be implemented. Otherwise, NULL can be + * returned. + */ + const GLubyte * (*GetString)( GLcontext *ctx, GLenum name ); + + /** + * Notify the driver after Mesa has made some internal state changes. + * + * This is in addition to any state change callbacks Mesa may already have + * made. + */ + void (*UpdateState)( GLcontext *ctx, GLuint new_state ); + + /** + * Get the width and height of the named buffer/window. + * + * Mesa uses this to determine when the driver's window size has changed. + */ + void (*GetBufferSize)( GLframebuffer *buffer, + GLuint *width, GLuint *height ); + + /** + * Resize the given framebuffer to the given size. + */ + void (*ResizeBuffers)( GLcontext *ctx, GLframebuffer *fb, + GLuint width, GLuint height); + + /** + * Called whenever an error is generated. + * + * __GLcontextRec::ErrorValue contains the error value. + */ + void (*Error)( GLcontext *ctx ); + + /** + * This is called whenever glFinish() is called. + */ + void (*Finish)( GLcontext *ctx ); + + /** + * This is called whenever glFlush() is called. + */ + void (*Flush)( GLcontext *ctx ); + + /** + * Clear the color/depth/stencil/accum buffer(s). + * + * \param mask a bitmask of the DD_*_BIT values defined above that indicates + * which buffers need to be cleared. + * \param all if true then clear the whole buffer, else clear only the + * region defined by <tt>(x, y, width, height)</tt>. + * + * This function must obey the glColorMask(), glIndexMask() and + * glStencilMask() settings! + * Software Mesa can do masked clears if the device driver can't. + */ + void (*Clear)( GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height ); + + + /** + * \name For hardware accumulation buffer + */ + /*@{*/ + /** + * Execute glAccum command within the given scissor region. + */ + void (*Accum)( GLcontext *ctx, GLenum op, GLfloat value, + GLint xpos, GLint ypos, GLint width, GLint height ); + /*@}*/ + + + /** + * \name glDraw(), glRead(), glCopyPixels() and glBitmap() functions + */ + /*@{*/ + + /** + * This is called by glDrawPixels(). + * + * \p unpack describes how to unpack the source image data. + */ + void (*DrawPixels)( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ); + + /** + * Called by glReadPixels(). + */ + void (*ReadPixels)( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + GLvoid *dest ); + + /** + * Do a glCopyPixels(). + * + * This function must respect all rasterization state, glPixelTransfer(), + * glPixelZoom(), etc. + */ + void (*CopyPixels)( GLcontext *ctx, GLint srcx, GLint srcy, + GLsizei width, GLsizei height, + GLint dstx, GLint dsty, GLenum type ); + + /** + * This is called by glBitmap(). + * + * Works the same as dd_function_table::DrawPixels, above. + */ + void (*Bitmap)( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap ); + /*@}*/ + + + /** + * \name Texture image functions + */ + /*@{*/ + + /** + * Choose texture format. + * + * This is called by the \c _mesa_store_tex[sub]image[123]d() fallback + * functions. The driver should examine \p internalFormat and return a + * pointer to an appropriate gl_texture_format. + */ + const struct gl_texture_format *(*ChooseTextureFormat)( GLcontext *ctx, + GLint internalFormat, GLenum srcFormat, GLenum srcType ); + + /** + * Called by glTexImage1D(). + * + * \param target user specified. + * \param format user specified. + * \param type user specified. + * \param pixels user specified. + * \param packing indicates the image packing of pixels. + * \param texObj is the target texture object. + * \param texImage is the target texture image. It will have the texture \p + * width, \p height, \p depth, \p border and \p internalFormat information. + * + * \p retainInternalCopy is returned by this function and indicates whether + * core Mesa should keep an internal copy of the texture image. + * + * Drivers should call a fallback routine from texstore.c if needed. + */ + void (*TexImage1D)( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glTexImage2D(). + * + * \sa dd_function_table::TexImage1D. + */ + void (*TexImage2D)( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glTexImage3D(). + * + * \sa dd_function_table::TexImage1D. + */ + void (*TexImage3D)( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glTexSubImage1D(). + * + * \param target user specified. + * \param level user specified. + * \param xoffset user specified. + * \param yoffset user specified. + * \param zoffset user specified. + * \param width user specified. + * \param height user specified. + * \param depth user specified. + * \param format user specified. + * \param type user specified. + * \param pixels user specified. + * \param packing indicates the image packing of pixels. + * \param texObj is the target texture object. + * \param texImage is the target texture image. It will have the texture \p + * width, \p height, \p border and \p internalFormat information. + * + * The driver should use a fallback routine from texstore.c if needed. + */ + void (*TexSubImage1D)( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glTexSubImage2D(). + * + * \sa dd_function_table::TexSubImage1D. + */ + void (*TexSubImage2D)( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glTexSubImage3D(). + * + * \sa dd_function_table::TexSubImage1D. + */ + void (*TexSubImage3D)( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLint depth, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glGetTexImage(). + */ + void (*GetTexImage)( GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage ); + + /** + * Called by glCopyTexImage1D(). + * + * Drivers should use a fallback routine from texstore.c if needed. + */ + void (*CopyTexImage1D)( GLcontext *ctx, GLenum target, GLint level, + GLenum internalFormat, GLint x, GLint y, + GLsizei width, GLint border ); + + /** + * Called by glCopyTexImage2D(). + * + * Drivers should use a fallback routine from texstore.c if needed. + */ + void (*CopyTexImage2D)( GLcontext *ctx, GLenum target, GLint level, + GLenum internalFormat, GLint x, GLint y, + GLsizei width, GLsizei height, GLint border ); + + /** + * Called by glCopyTexSubImage1D(). + * + * Drivers should use a fallback routine from texstore.c if needed. + */ + void (*CopyTexSubImage1D)( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, + GLint x, GLint y, GLsizei width ); + /** + * Called by glCopyTexSubImage2D(). + * + * Drivers should use a fallback routine from texstore.c if needed. + */ + void (*CopyTexSubImage2D)( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ); + /** + * Called by glCopyTexSubImage3D(). + * + * Drivers should use a fallback routine from texstore.c if needed. + */ + void (*CopyTexSubImage3D)( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ); + + /** + * Called by glTexImage[123]D when user specifies a proxy texture + * target. + * + * \return GL_TRUE if the proxy test passes, or GL_FALSE if the test fails. + */ + GLboolean (*TestProxyTexImage)(GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLenum format, GLenum type, + GLint width, GLint height, + GLint depth, GLint border); + /*@}*/ + + + /** + * \name Compressed texture functions + */ + /*@{*/ + + /** + * Called by glCompressedTexImage1D(). + * + * \param target user specified. + * \param format user specified. + * \param type user specified. + * \param pixels user specified. + * \param packing indicates the image packing of pixels. + * \param texObj is the target texture object. + * \param texImage is the target texture image. It will have the texture \p + * width, \p height, \p depth, \p border and \p internalFormat information. + * + * \a retainInternalCopy is returned by this function and indicates whether + * core Mesa should keep an internal copy of the texture image. + */ + void (*CompressedTexImage1D)( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLsizei width, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + /** + * Called by glCompressedTexImage2D(). + * + * \sa dd_function_table::CompressedTexImage1D. + */ + void (*CompressedTexImage2D)( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + /** + * Called by glCompressedTexImage3D(). + * + * \sa dd_function_table::CompressedTexImage3D. + */ + void (*CompressedTexImage3D)( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + + /** + * Called by glCompressedTexSubImage1D(). + * + * \param target user specified. + * \param level user specified. + * \param xoffset user specified. + * \param yoffset user specified. + * \param zoffset user specified. + * \param width user specified. + * \param height user specified. + * \param depth user specified. + * \param imageSize user specified. + * \param data user specified. + * \param texObj is the target texture object. + * \param texImage is the target texture image. It will have the texture \p + * width, \p height, \p depth, \p border and \p internalFormat information. + */ + void (*CompressedTexSubImage1D)(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + /** + * Called by glCompressedTexSubImage2D(). + * + * \sa dd_function_table::CompressedTexImage3D. + */ + void (*CompressedTexSubImage2D)(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLint height, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + /** + * Called by glCompressedTexSubImage3D(). + * + * \sa dd_function_table::CompressedTexImage3D. + */ + void (*CompressedTexSubImage3D)(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLint height, GLint depth, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + + /** + * Called by glGetCompressedTexImage. + */ + void (*GetCompressedTexImage)(GLcontext *ctx, GLenum target, GLint level, + GLvoid *img, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage); + + /** + * Called to query number of bytes of storage needed to store the + * specified compressed texture. + */ + GLuint (*CompressedTextureSize)( GLcontext *ctx, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format ); + /*@}*/ + + /** + * \name Texture object functions + */ + /*@{*/ + + /** + * Called by glBindTexture(). + */ + void (*BindTexture)( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj ); + + /** + * Called to allocate a new texture object. + * A new gl_texture_object should be returned. The driver should + * attach to it any device-specific info it needs. + */ + struct gl_texture_object * (*NewTextureObject)( GLcontext *ctx, GLuint name, + GLenum target ); + /** + * Called when a texture object is about to be deallocated. + * + * Driver should delete the gl_texture_object object and anything + * hanging off of it. + */ + void (*DeleteTexture)( GLcontext *ctx, struct gl_texture_object *tObj ); + + /** + * Called to allocate a new texture image object. + */ + struct gl_texture_image * (*NewTextureImage)( GLcontext *ctx ); + + /** + * Called to free tImage->Data. + */ + void (*FreeTexImageData)( GLcontext *ctx, struct gl_texture_image *tImage ); + + /** + * Note: no context argument. This function doesn't initially look + * like it belongs here, except that the driver is the only entity + * that knows for sure how the texture memory is allocated - via + * the above callbacks. There is then an argument that the driver + * knows what memcpy paths might be fast. Typically this is invoked with + * + * to -- a pointer into texture memory allocated by NewTextureImage() above. + * from -- a pointer into client memory or a mesa temporary. + * sz -- nr bytes to copy. + */ + void* (*TextureMemCpy)( void *to, const void *from, size_t sz ); + + /** + * Called by glAreTextureResident(). + */ + GLboolean (*IsTextureResident)( GLcontext *ctx, + struct gl_texture_object *t ); + + /** + * Called by glPrioritizeTextures(). + */ + void (*PrioritizeTexture)( GLcontext *ctx, struct gl_texture_object *t, + GLclampf priority ); + + /** + * Called by glActiveTextureARB() to set current texture unit. + */ + void (*ActiveTexture)( GLcontext *ctx, GLuint texUnitNumber ); + + /** + * Called when the texture's color lookup table is changed. + * + * If \p tObj is NULL then the shared texture palette + * gl_texture_object::Palette is to be updated. + */ + void (*UpdateTexturePalette)( GLcontext *ctx, + struct gl_texture_object *tObj ); + /*@}*/ + + + /** + * \name Imaging functionality + */ + /*@{*/ + void (*CopyColorTable)( GLcontext *ctx, + GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width ); + + void (*CopyColorSubTable)( GLcontext *ctx, + GLenum target, GLsizei start, + GLint x, GLint y, GLsizei width ); + + void (*CopyConvolutionFilter1D)( GLcontext *ctx, GLenum target, + GLenum internalFormat, + GLint x, GLint y, GLsizei width ); + + void (*CopyConvolutionFilter2D)( GLcontext *ctx, GLenum target, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLsizei height ); + /*@}*/ + + + /** + * \name Vertex/fragment program functions + */ + /*@{*/ + /** Bind a vertex/fragment program */ + void (*BindProgram)(GLcontext *ctx, GLenum target, struct program *prog); + /** Allocate a new program */ + struct program * (*NewProgram)(GLcontext *ctx, GLenum target, GLuint id); + /** Delete a program */ + void (*DeleteProgram)(GLcontext *ctx, struct program *prog); + /** Notify driver that a program string has been specified. */ + void (*ProgramStringNotify)(GLcontext *ctx, GLenum target, + struct program *prog); + + + + /** Query if program can be loaded onto hardware */ + GLboolean (*IsProgramNative)(GLcontext *ctx, GLenum target, + struct program *prog); + + /*@}*/ + + + /** + * \name State-changing functions. + * + * \note drawing functions are above. + * + * These functions are called by their corresponding OpenGL API functions. + * They are \e also called by the gl_PopAttrib() function!!! + * May add more functions like these to the device driver in the future. + */ + /*@{*/ + /** Specify the alpha test function */ + void (*AlphaFunc)(GLcontext *ctx, GLenum func, GLfloat ref); + /** Set the blend color */ + void (*BlendColor)(GLcontext *ctx, const GLfloat color[4]); + /** Set the blend equation */ + void (*BlendEquationSeparate)(GLcontext *ctx, GLenum modeRGB, GLenum modeA); + /** Specify pixel arithmetic */ + void (*BlendFuncSeparate)(GLcontext *ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA); + /** Specify clear values for the color buffers */ + void (*ClearColor)(GLcontext *ctx, const GLfloat color[4]); + /** Specify the clear value for the depth buffer */ + void (*ClearDepth)(GLcontext *ctx, GLclampd d); + /** Specify the clear value for the color index buffers */ + void (*ClearIndex)(GLcontext *ctx, GLuint index); + /** Specify the clear value for the stencil buffer */ + void (*ClearStencil)(GLcontext *ctx, GLint s); + /** Specify a plane against which all geometry is clipped */ + void (*ClipPlane)(GLcontext *ctx, GLenum plane, const GLfloat *equation ); + /** Enable and disable writing of frame buffer color components */ + void (*ColorMask)(GLcontext *ctx, GLboolean rmask, GLboolean gmask, + GLboolean bmask, GLboolean amask ); + /** Cause a material color to track the current color */ + void (*ColorMaterial)(GLcontext *ctx, GLenum face, GLenum mode); + /** Specify whether front- or back-facing facets can be culled */ + void (*CullFace)(GLcontext *ctx, GLenum mode); + /** Define front- and back-facing polygons */ + void (*FrontFace)(GLcontext *ctx, GLenum mode); + /** Specify the value used for depth buffer comparisons */ + void (*DepthFunc)(GLcontext *ctx, GLenum func); + /** Enable or disable writing into the depth buffer */ + void (*DepthMask)(GLcontext *ctx, GLboolean flag); + /** Specify mapping of depth values from NDC to window coordinates */ + void (*DepthRange)(GLcontext *ctx, GLclampd nearval, GLclampd farval); + /** Specify the current buffer for writing */ + void (*DrawBuffer)( GLcontext *ctx, GLenum buffer ); + /** Specify the buffers for writing for fragment programs*/ + void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers ); + /** Enable or disable server-side gl capabilities */ + void (*Enable)(GLcontext *ctx, GLenum cap, GLboolean state); + /** Specify fog parameters */ + void (*Fogfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + /** Specify implementation-specific hints */ + void (*Hint)(GLcontext *ctx, GLenum target, GLenum mode); + /** Control the writing of individual bits in the color index buffers */ + void (*IndexMask)(GLcontext *ctx, GLuint mask); + /** Set light source parameters */ + void (*Lightfv)(GLcontext *ctx, GLenum light, + GLenum pname, const GLfloat *params ); + /** Set the lighting model parameters */ + void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params); + /** Specify the line stipple pattern */ + void (*LineStipple)(GLcontext *ctx, GLint factor, GLushort pattern ); + /** Specify the width of rasterized lines */ + void (*LineWidth)(GLcontext *ctx, GLfloat width); + /** Specify a logical pixel operation for color index rendering */ + void (*LogicOpcode)(GLcontext *ctx, GLenum opcode); + void (*PointParameterfv)(GLcontext *ctx, GLenum pname, + const GLfloat *params); + /** Specify the diameter of rasterized points */ + void (*PointSize)(GLcontext *ctx, GLfloat size); + /** Select a polygon rasterization mode */ + void (*PolygonMode)(GLcontext *ctx, GLenum face, GLenum mode); + /** Set the scale and units used to calculate depth values */ + void (*PolygonOffset)(GLcontext *ctx, GLfloat factor, GLfloat units); + /** Set the polygon stippling pattern */ + void (*PolygonStipple)(GLcontext *ctx, const GLubyte *mask ); + /* Specifies the current buffer for reading */ + void (*ReadBuffer)( GLcontext *ctx, GLenum buffer ); + /** Set rasterization mode */ + void (*RenderMode)(GLcontext *ctx, GLenum mode ); + /** Define the scissor box */ + void (*Scissor)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h); + /** Select flat or smooth shading */ + void (*ShadeModel)(GLcontext *ctx, GLenum mode); + /** Set function and reference value for stencil testing */ + void (*StencilFunc)(GLcontext *ctx, GLenum func, GLint ref, GLuint mask); + /** Control the writing of individual bits in the stencil planes */ + void (*StencilMask)(GLcontext *ctx, GLuint mask); + /** Set stencil test actions */ + void (*StencilOp)(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass); + /** Set active stencil face (GL_EXT_stencil_two_side) */ + void (*ActiveStencilFace)(GLcontext *ctx, GLuint face); + /** OpenGL 2.0 two-sided StencilFunc */ + void (*StencilFuncSeparate)(GLcontext *ctx, GLenum face, GLenum func, + GLint ref, GLuint mask); + /** OpenGL 2.0 two-sided StencilMask */ + void (*StencilMaskSeparate)(GLcontext *ctx, GLenum face, GLuint mask); + /** OpenGL 2.0 two-sided StencilOp */ + void (*StencilOpSeparate)(GLcontext *ctx, GLenum face, GLenum fail, + GLenum zfail, GLenum zpass); + /** Control the generation of texture coordinates */ + void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname, + const GLfloat *params); + /** Set texture environment parameters */ + void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname, + const GLfloat *param); + /** Set texture parameters */ + void (*TexParameter)(GLcontext *ctx, GLenum target, + struct gl_texture_object *texObj, + GLenum pname, const GLfloat *params); + void (*TextureMatrix)(GLcontext *ctx, GLuint unit, const GLmatrix *mat); + /** Set the viewport */ + void (*Viewport)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h); + /*@}*/ + + + /** + * \name Vertex array functions + * + * Called by the corresponding OpenGL functions. + */ + /*@{*/ + void (*VertexPointer)(GLcontext *ctx, GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*NormalPointer)(GLcontext *ctx, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*ColorPointer)(GLcontext *ctx, GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*FogCoordPointer)(GLcontext *ctx, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*IndexPointer)(GLcontext *ctx, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*SecondaryColorPointer)(GLcontext *ctx, GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*TexCoordPointer)(GLcontext *ctx, GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr); + void (*EdgeFlagPointer)(GLcontext *ctx, GLsizei stride, const GLvoid *ptr); + void (*VertexAttribPointer)(GLcontext *ctx, GLuint index, GLint size, + GLenum type, GLsizei stride, const GLvoid *ptr); + void (*LockArraysEXT)( GLcontext *ctx, GLint first, GLsizei count ); + void (*UnlockArraysEXT)( GLcontext *ctx ); + /*@}*/ + + + /** + * \name State-query functions + * + * Return GL_TRUE if query was completed, GL_FALSE otherwise. + */ + /*@{*/ + /** Return the value or values of a selected parameter */ + GLboolean (*GetBooleanv)(GLcontext *ctx, GLenum pname, GLboolean *result); + /** Return the value or values of a selected parameter */ + GLboolean (*GetDoublev)(GLcontext *ctx, GLenum pname, GLdouble *result); + /** Return the value or values of a selected parameter */ + GLboolean (*GetFloatv)(GLcontext *ctx, GLenum pname, GLfloat *result); + /** Return the value or values of a selected parameter */ + GLboolean (*GetIntegerv)(GLcontext *ctx, GLenum pname, GLint *result); + /** Return the value or values of a selected parameter */ + GLboolean (*GetPointerv)(GLcontext *ctx, GLenum pname, GLvoid **result); + /*@}*/ + + + /** + * \name Vertex/pixel buffer object functions + */ +#if FEATURE_ARB_vertex_buffer_object + /*@{*/ + void (*BindBuffer)( GLcontext *ctx, GLenum target, + struct gl_buffer_object *obj ); + + struct gl_buffer_object * (*NewBufferObject)( GLcontext *ctx, GLuint buffer, + GLenum target ); + + void (*DeleteBuffer)( GLcontext *ctx, struct gl_buffer_object *obj ); + + void (*BufferData)( GLcontext *ctx, GLenum target, GLsizeiptrARB size, + const GLvoid *data, GLenum usage, + struct gl_buffer_object *obj ); + + void (*BufferSubData)( GLcontext *ctx, GLenum target, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid *data, + struct gl_buffer_object *obj ); + + void (*GetBufferSubData)( GLcontext *ctx, GLenum target, + GLintptrARB offset, GLsizeiptrARB size, + GLvoid *data, struct gl_buffer_object *obj ); + + void * (*MapBuffer)( GLcontext *ctx, GLenum target, GLenum access, + struct gl_buffer_object *obj ); + + GLboolean (*UnmapBuffer)( GLcontext *ctx, GLenum target, + struct gl_buffer_object *obj ); + /*@}*/ +#endif + + /** + * \name Functions for GL_EXT_framebuffer_object + */ +#if FEATURE_EXT_framebuffer_object + /*@{*/ + struct gl_framebuffer * (*NewFramebuffer)(GLcontext *ctx, GLuint name); + struct gl_renderbuffer * (*NewRenderbuffer)(GLcontext *ctx, GLuint name); + void (*FramebufferRenderbuffer)(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb); + void (*RenderbufferTexture)(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset); + /*@}*/ +#endif + + + /** + * \name Support for multiple T&L engines + */ + /*@{*/ + + /** + * Bitmask of state changes that require the current T&L module to be + * validated, using ValidateTnlModule() below. + */ + GLuint NeedValidate; + + /** + * Validate the current T&L module. + * + * This is called directly after UpdateState() when a state change that has + * occurred matches the dd_function_table::NeedValidate bitmask above. This + * ensures all computed values are up to date, thus allowing the driver to + * decide if the current T&L module needs to be swapped out. + * + * This must be non-NULL if a driver installs a custom T&L module and sets + * the dd_function_table::NeedValidate bitmask, but may be NULL otherwise. + */ + void (*ValidateTnlModule)( GLcontext *ctx, GLuint new_state ); + + +#define PRIM_OUTSIDE_BEGIN_END GL_POLYGON+1 +#define PRIM_INSIDE_UNKNOWN_PRIM GL_POLYGON+2 +#define PRIM_UNKNOWN GL_POLYGON+3 + + /** + * Set by the driver-supplied T&L engine. + * + * Set to PRIM_OUTSIDE_BEGIN_END when outside glBegin()/glEnd(). + */ + GLuint CurrentExecPrimitive; + + /** + * Current state of an in-progress compilation. + * + * May take on any of the additional values PRIM_OUTSIDE_BEGIN_END, + * PRIM_INSIDE_UNKNOWN_PRIM or PRIM_UNKNOWN defined above. + */ + GLuint CurrentSavePrimitive; + + +#define FLUSH_STORED_VERTICES 0x1 +#define FLUSH_UPDATE_CURRENT 0x2 + /** + * Set by the driver-supplied T&L engine whenever vertices are buffered + * between glBegin()/glEnd() objects or __GLcontextRec::Current is not + * updated. + * + * The dd_function_table::FlushVertices call below may be used to resolve + * these conditions. + */ + GLuint NeedFlush; + GLuint SaveNeedFlush; + + /** + * If inside glBegin()/glEnd(), it should ASSERT(0). Otherwise, if + * FLUSH_STORED_VERTICES bit in \p flags is set flushes any buffered + * vertices, if FLUSH_UPDATE_CURRENT bit is set updates + * __GLcontextRec::Current and gl_light_attrib::Material + * + * Note that the default T&L engine never clears the + * FLUSH_UPDATE_CURRENT bit, even after performing the update. + */ + void (*FlushVertices)( GLcontext *ctx, GLuint flags ); + void (*SaveFlushVertices)( GLcontext *ctx ); + + /** + * Give the driver the opportunity to hook in its own vtxfmt for + * compiling optimized display lists. This is called on each valid + * glBegin() during list compilation. + */ + GLboolean (*NotifySaveBegin)( GLcontext *ctx, GLenum mode ); + + /** + * Notify driver that the special derived value _NeedEyeCoords has + * changed. + */ + void (*LightingSpaceChange)( GLcontext *ctx ); + + /** + * Let the T&L component know when the context becomes current. + */ + void (*MakeCurrent)( GLcontext *ctx, GLframebuffer *drawBuffer, + GLframebuffer *readBuffer ); + + /** + * Called by glNewList(). + * + * Let the T&L component know what is going on with display lists + * in time to make changes to dispatch tables, etc. + */ + void (*NewList)( GLcontext *ctx, GLuint list, GLenum mode ); + /** + * Called by glEndList(). + * + * \sa dd_function_table::NewList. + */ + void (*EndList)( GLcontext *ctx ); + + /** + * Called by glCallList(s). + * + * Notify the T&L component before and after calling a display list. + */ + void (*BeginCallList)( GLcontext *ctx, + struct mesa_display_list *dlist ); + /** + * Called by glEndCallList(). + * + * \sa dd_function_table::BeginCallList. + */ + void (*EndCallList)( GLcontext *ctx ); + +}; + + +/** + * Transform/Clip/Lighting interface + * + * Drivers present a reduced set of the functions possible in + * glBegin()/glEnd() objects. Core mesa provides translation stubs for the + * remaining functions to map down to these entry points. + * + * These are the initial values to be installed into dispatch by + * mesa. If the T&L driver wants to modify the dispatch table + * while installed, it must do so itself. It would be possible for + * the vertexformat to install it's own initial values for these + * functions, but this way there is an obvious list of what is + * expected of the driver. + * + * If the driver wants to hook in entry points other than those + * listed, it must restore them to their original values in + * the disable() callback, below. + */ +typedef struct { + /** + * \name Vertex + */ + /*@{*/ + void (GLAPIENTRYP ArrayElement)( GLint ); /* NOTE */ + void (GLAPIENTRYP Color3f)( GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP Color3fv)( const GLfloat * ); + void (GLAPIENTRYP Color4f)( GLfloat, GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP Color4fv)( const GLfloat * ); + void (GLAPIENTRYP EdgeFlag)( GLboolean ); + void (GLAPIENTRYP EdgeFlagv)( const GLboolean * ); + void (GLAPIENTRYP EvalCoord1f)( GLfloat ); /* NOTE */ + void (GLAPIENTRYP EvalCoord1fv)( const GLfloat * ); /* NOTE */ + void (GLAPIENTRYP EvalCoord2f)( GLfloat, GLfloat ); /* NOTE */ + void (GLAPIENTRYP EvalCoord2fv)( const GLfloat * ); /* NOTE */ + void (GLAPIENTRYP EvalPoint1)( GLint ); /* NOTE */ + void (GLAPIENTRYP EvalPoint2)( GLint, GLint ); /* NOTE */ + void (GLAPIENTRYP FogCoordfEXT)( GLfloat ); + void (GLAPIENTRYP FogCoordfvEXT)( const GLfloat * ); + void (GLAPIENTRYP Indexf)( GLfloat ); + void (GLAPIENTRYP Indexfv)( const GLfloat * ); + void (GLAPIENTRYP Materialfv)( GLenum face, GLenum pname, const GLfloat * ); /* NOTE */ + void (GLAPIENTRYP MultiTexCoord1fARB)( GLenum, GLfloat ); + void (GLAPIENTRYP MultiTexCoord1fvARB)( GLenum, const GLfloat * ); + void (GLAPIENTRYP MultiTexCoord2fARB)( GLenum, GLfloat, GLfloat ); + void (GLAPIENTRYP MultiTexCoord2fvARB)( GLenum, const GLfloat * ); + void (GLAPIENTRYP MultiTexCoord3fARB)( GLenum, GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP MultiTexCoord3fvARB)( GLenum, const GLfloat * ); + void (GLAPIENTRYP MultiTexCoord4fARB)( GLenum, GLfloat, GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP MultiTexCoord4fvARB)( GLenum, const GLfloat * ); + void (GLAPIENTRYP Normal3f)( GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP Normal3fv)( const GLfloat * ); + void (GLAPIENTRYP SecondaryColor3fEXT)( GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP SecondaryColor3fvEXT)( const GLfloat * ); + void (GLAPIENTRYP TexCoord1f)( GLfloat ); + void (GLAPIENTRYP TexCoord1fv)( const GLfloat * ); + void (GLAPIENTRYP TexCoord2f)( GLfloat, GLfloat ); + void (GLAPIENTRYP TexCoord2fv)( const GLfloat * ); + void (GLAPIENTRYP TexCoord3f)( GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP TexCoord3fv)( const GLfloat * ); + void (GLAPIENTRYP TexCoord4f)( GLfloat, GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP TexCoord4fv)( const GLfloat * ); + void (GLAPIENTRYP Vertex2f)( GLfloat, GLfloat ); + void (GLAPIENTRYP Vertex2fv)( const GLfloat * ); + void (GLAPIENTRYP Vertex3f)( GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP Vertex3fv)( const GLfloat * ); + void (GLAPIENTRYP Vertex4f)( GLfloat, GLfloat, GLfloat, GLfloat ); + void (GLAPIENTRYP Vertex4fv)( const GLfloat * ); + void (GLAPIENTRYP CallList)( GLuint ); /* NOTE */ + void (GLAPIENTRYP CallLists)( GLsizei, GLenum, const GLvoid * ); /* NOTE */ + void (GLAPIENTRYP Begin)( GLenum ); + void (GLAPIENTRYP End)( void ); + void (GLAPIENTRYP VertexAttrib1fNV)( GLuint index, GLfloat x ); + void (GLAPIENTRYP VertexAttrib1fvNV)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib2fNV)( GLuint index, GLfloat x, GLfloat y ); + void (GLAPIENTRYP VertexAttrib2fvNV)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib3fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z ); + void (GLAPIENTRYP VertexAttrib3fvNV)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + void (GLAPIENTRYP VertexAttrib4fvNV)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib1fARB)( GLuint index, GLfloat x ); + void (GLAPIENTRYP VertexAttrib1fvARB)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib2fARB)( GLuint index, GLfloat x, GLfloat y ); + void (GLAPIENTRYP VertexAttrib2fvARB)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib3fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z ); + void (GLAPIENTRYP VertexAttrib3fvARB)( GLuint index, const GLfloat *v ); + void (GLAPIENTRYP VertexAttrib4fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ); + void (GLAPIENTRYP VertexAttrib4fvARB)( GLuint index, const GLfloat *v ); + /*@}*/ + + /* + */ + void (GLAPIENTRYP Rectf)( GLfloat, GLfloat, GLfloat, GLfloat ); + + /** + * \name Array + */ + /*@{*/ + void (GLAPIENTRYP DrawArrays)( GLenum mode, GLint start, GLsizei count ); + void (GLAPIENTRYP DrawElements)( GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices ); + void (GLAPIENTRYP DrawRangeElements)( GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, const GLvoid *indices ); + /*@}*/ + + /** + * \name Eval + * + * If you don't support eval, fallback to the default vertex format + * on receiving an eval call and use the pipeline mechanism to + * provide partial T&L acceleration. + * + * Mesa will provide a set of helper functions to do eval within + * accelerated vertex formats, eventually... + */ + /*@{*/ + void (GLAPIENTRYP EvalMesh1)( GLenum mode, GLint i1, GLint i2 ); + void (GLAPIENTRYP EvalMesh2)( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ); + /*@}*/ + +} GLvertexformat; + + +#endif /* DD_INCLUDED */ diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c new file mode 100644 index 00000000000..edc32b1f94d --- /dev/null +++ b/src/mesa/main/debug.c @@ -0,0 +1,218 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "mtypes.h" +#include "context.h" +#include "imports.h" +#include "debug.h" +#include "get.h" + +/** + * Primitive names + */ +const char *_mesa_prim_name[GL_POLYGON+4] = { + "GL_POINTS", + "GL_LINES", + "GL_LINE_LOOP", + "GL_LINE_STRIP", + "GL_TRIANGLES", + "GL_TRIANGLE_STRIP", + "GL_TRIANGLE_FAN", + "GL_QUADS", + "GL_QUAD_STRIP", + "GL_POLYGON", + "outside begin/end", + "inside unkown primitive", + "unknown state" +}; + +void +_mesa_print_state( const char *msg, GLuint state ) +{ + _mesa_debug(NULL, + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + msg, + state, + (state & _NEW_MODELVIEW) ? "ctx->ModelView, " : "", + (state & _NEW_PROJECTION) ? "ctx->Projection, " : "", + (state & _NEW_TEXTURE_MATRIX) ? "ctx->TextureMatrix, " : "", + (state & _NEW_COLOR_MATRIX) ? "ctx->ColorMatrix, " : "", + (state & _NEW_ACCUM) ? "ctx->Accum, " : "", + (state & _NEW_COLOR) ? "ctx->Color, " : "", + (state & _NEW_DEPTH) ? "ctx->Depth, " : "", + (state & _NEW_EVAL) ? "ctx->Eval/EvalMap, " : "", + (state & _NEW_FOG) ? "ctx->Fog, " : "", + (state & _NEW_HINT) ? "ctx->Hint, " : "", + (state & _NEW_LIGHT) ? "ctx->Light, " : "", + (state & _NEW_LINE) ? "ctx->Line, " : "", + (state & _NEW_PIXEL) ? "ctx->Pixel, " : "", + (state & _NEW_POINT) ? "ctx->Point, " : "", + (state & _NEW_POLYGON) ? "ctx->Polygon, " : "", + (state & _NEW_POLYGONSTIPPLE) ? "ctx->PolygonStipple, " : "", + (state & _NEW_SCISSOR) ? "ctx->Scissor, " : "", + (state & _NEW_TEXTURE) ? "ctx->Texture, " : "", + (state & _NEW_TRANSFORM) ? "ctx->Transform, " : "", + (state & _NEW_VIEWPORT) ? "ctx->Viewport, " : "", + (state & _NEW_PACKUNPACK) ? "ctx->Pack/Unpack, " : "", + (state & _NEW_ARRAY) ? "ctx->Array, " : "", + (state & _NEW_RENDERMODE) ? "ctx->RenderMode, " : "", + (state & _NEW_BUFFERS) ? "ctx->Visual, ctx->DrawBuffer,, " : ""); +} + + + +void +_mesa_print_tri_caps( const char *name, GLuint flags ) +{ + _mesa_debug(NULL, + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + name, + flags, + (flags & DD_FLATSHADE) ? "flat-shade, " : "", + (flags & DD_SEPARATE_SPECULAR) ? "separate-specular, " : "", + (flags & DD_TRI_LIGHT_TWOSIDE) ? "tri-light-twoside, " : "", + (flags & DD_TRI_TWOSTENCIL) ? "tri-twostencil, " : "", + (flags & DD_TRI_UNFILLED) ? "tri-unfilled, " : "", + (flags & DD_TRI_STIPPLE) ? "tri-stipple, " : "", + (flags & DD_TRI_OFFSET) ? "tri-offset, " : "", + (flags & DD_TRI_SMOOTH) ? "tri-smooth, " : "", + (flags & DD_LINE_SMOOTH) ? "line-smooth, " : "", + (flags & DD_LINE_STIPPLE) ? "line-stipple, " : "", + (flags & DD_LINE_WIDTH) ? "line-wide, " : "", + (flags & DD_POINT_SMOOTH) ? "point-smooth, " : "", + (flags & DD_POINT_SIZE) ? "point-size, " : "", + (flags & DD_POINT_ATTEN) ? "point-atten, " : "", + (flags & DD_TRI_CULL_FRONT_BACK) ? "cull-all, " : "" + ); +} + + +/** + * Print information about this Mesa version and build options. + */ +void _mesa_print_info( void ) +{ + _mesa_debug(NULL, "Mesa GL_VERSION = %s\n", + (char *) _mesa_GetString(GL_VERSION)); + _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n", + (char *) _mesa_GetString(GL_RENDERER)); + _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n", + (char *) _mesa_GetString(GL_VENDOR)); + _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n", + (char *) _mesa_GetString(GL_EXTENSIONS)); +#if defined(THREADS) + _mesa_debug(NULL, "Mesa thread-safe: YES\n"); +#else + _mesa_debug(NULL, "Mesa thread-safe: NO\n"); +#endif +#if defined(USE_X86_ASM) + _mesa_debug(NULL, "Mesa x86-optimized: YES\n"); +#else + _mesa_debug(NULL, "Mesa x86-optimized: NO\n"); +#endif +#if defined(USE_SPARC_ASM) + _mesa_debug(NULL, "Mesa sparc-optimized: YES\n"); +#else + _mesa_debug(NULL, "Mesa sparc-optimized: NO\n"); +#endif +} + + +/** + * Set the debugging flags. + * + * \param debug debug string + * + * If compiled with debugging support then search for keywords in \p debug and + * enables the verbose debug output of the respective feature. + */ +static void add_debug_flags( const char *debug ) +{ +#ifdef MESA_DEBUG + if (_mesa_strstr(debug, "varray")) + MESA_VERBOSE |= VERBOSE_VARRAY; + + if (_mesa_strstr(debug, "tex")) + MESA_VERBOSE |= VERBOSE_TEXTURE; + + if (_mesa_strstr(debug, "imm")) + MESA_VERBOSE |= VERBOSE_IMMEDIATE; + + if (_mesa_strstr(debug, "pipe")) + MESA_VERBOSE |= VERBOSE_PIPELINE; + + if (_mesa_strstr(debug, "driver")) + MESA_VERBOSE |= VERBOSE_DRIVER; + + if (_mesa_strstr(debug, "state")) + MESA_VERBOSE |= VERBOSE_STATE; + + if (_mesa_strstr(debug, "api")) + MESA_VERBOSE |= VERBOSE_API; + + if (_mesa_strstr(debug, "list")) + MESA_VERBOSE |= VERBOSE_DISPLAY_LIST; + + if (_mesa_strstr(debug, "lighting")) + MESA_VERBOSE |= VERBOSE_LIGHTING; + + if (_mesa_strstr(debug, "disassem")) + MESA_VERBOSE |= VERBOSE_DISASSEM; + + /* Debug flag: + */ + if (_mesa_strstr(debug, "flush")) + MESA_DEBUG_FLAGS |= DEBUG_ALWAYS_FLUSH; +#else + (void) debug; +#endif +} + + +void +_mesa_init_debug( GLcontext *ctx ) +{ + char *c; + + /* For debug/development only */ + ctx->FirstTimeCurrent = GL_TRUE; + + /* Dither disable */ + ctx->NoDither = _mesa_getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE; + if (ctx->NoDither) { + if (_mesa_getenv("MESA_DEBUG")) { + _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n"); + } + ctx->Color.DitherFlag = GL_FALSE; + } + + c = _mesa_getenv("MESA_DEBUG"); + if (c) + add_debug_flags(c); + + c = _mesa_getenv("MESA_VERBOSE"); + if (c) + add_debug_flags(c); +} + diff --git a/src/mesa/main/debug.h b/src/mesa/main/debug.h new file mode 100644 index 00000000000..94d99c384bd --- /dev/null +++ b/src/mesa/main/debug.h @@ -0,0 +1,60 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file debug.h + * Debugging functions. + * + * \if subset + * (No-op) + * + * \endif + */ + + +#ifndef _DEBUG_H +#define _DEBUG_H + +#if _HAVE_FULL_GL + +extern void _mesa_print_tri_caps( const char *name, GLuint flags ); +extern void _mesa_print_enable_flags( const char *msg, GLuint flags ); +extern void _mesa_print_state( const char *msg, GLuint state ); +extern void _mesa_print_info( void ); +extern void _mesa_init_debug( GLcontext *ctx ); + +#else + +/** No-op */ +#define _mesa_print_state( m, s ) ((void)0) + +/** No-op */ +#define _mesa_print_info() ((void)0) + +/** No-op */ +#define _mesa_init_debug( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c new file mode 100644 index 00000000000..aca471a06c8 --- /dev/null +++ b/src/mesa/main/depth.c @@ -0,0 +1,189 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "depth.h" +#include "enums.h" +#include "hash.h" +#include "macros.h" +#include "mtypes.h" + + +/**********************************************************************/ +/***** API Functions *****/ +/**********************************************************************/ + + + +void GLAPIENTRY +_mesa_ClearDepth( GLclampd depth ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + depth = CLAMP( depth, 0.0, 1.0 ); + + if (ctx->Depth.Clear == depth) + return; + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.Clear = depth; + if (ctx->Driver.ClearDepth) + (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear ); +} + + + +void GLAPIENTRY +_mesa_DepthFunc( GLenum func ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glDepthFunc %s\n", _mesa_lookup_enum_by_nr(func)); + + switch (func) { + case GL_LESS: /* (default) pass if incoming z < stored z */ + case GL_GEQUAL: + case GL_LEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + case GL_EQUAL: + case GL_ALWAYS: + case GL_NEVER: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glDepth.Func" ); + return; + } + + if (ctx->Depth.Func == func) + return; + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.Func = func; + + if (ctx->Driver.DepthFunc) + ctx->Driver.DepthFunc( ctx, func ); +} + + + +void GLAPIENTRY +_mesa_DepthMask( GLboolean flag ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glDepthMask %d\n", flag); + + /* + * GL_TRUE indicates depth buffer writing is enabled (default) + * GL_FALSE indicates depth buffer writing is disabled + */ + if (ctx->Depth.Mask == flag) + return; + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.Mask = flag; + + if (ctx->Driver.DepthMask) + ctx->Driver.DepthMask( ctx, flag ); +} + + + +/** + * Specified by the GL_EXT_depth_bounds_test extension. + */ +void GLAPIENTRY +_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (zmin > zmax) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)"); + return; + } + + zmin = CLAMP(zmin, 0.0, 1.0); + zmax = CLAMP(zmax, 0.0, 1.0); + + if (ctx->Depth.BoundsMin == zmin && ctx->Depth.BoundsMax == zmax) + return; + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.BoundsMin = (GLfloat) zmin; + ctx->Depth.BoundsMax = (GLfloat) zmax; +} + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + + +/** + * Initialize the depth buffer attribute group in the given context. + */ +void _mesa_init_depth( GLcontext * ctx ) +{ + /* Depth buffer group */ + ctx->Depth.Test = GL_FALSE; + ctx->Depth.Clear = 1.0; + ctx->Depth.Func = GL_LESS; + ctx->Depth.Mask = GL_TRUE; + ctx->Depth.OcclusionTest = GL_FALSE; + + /* XXX this is now per-framebuffer state */ +#if 00 + /* Z buffer stuff */ + if (ctx->Visual.depthBits == 0) { + /* Special case. Even if we don't have a depth buffer we need + * good values for DepthMax for Z vertex transformation purposes + * and for per-fragment fog computation. + */ + ctx->DepthMax = (1 << 16) - 1; + ctx->DepthMaxF = (GLfloat) ctx->DepthMax; + } + else if (ctx->Visual.depthBits < 32) { + ctx->DepthMax = (1 << ctx->Visual.depthBits) - 1; + ctx->DepthMaxF = (GLfloat) ctx->DepthMax; + } + else { + /* Special case since shift values greater than or equal to the + * number of bits in the left hand expression's type are undefined. + */ + ctx->DepthMax = 0xffffffff; + ctx->DepthMaxF = (GLfloat) ctx->DepthMax; + } + ctx->MRD = 1.0; /* Minimum resolvable depth value, for polygon offset */ +#endif +} diff --git a/src/mesa/main/depth.h b/src/mesa/main/depth.h new file mode 100644 index 00000000000..dcc0b4637a7 --- /dev/null +++ b/src/mesa/main/depth.h @@ -0,0 +1,62 @@ +/** + * \file depth.h + * Depth buffer operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef DEPTH_H +#define DEPTH_H + + +#include "mtypes.h" + + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_ClearDepth( GLclampd depth ); + +extern void GLAPIENTRY +_mesa_DepthFunc( GLenum func ); + +extern void GLAPIENTRY +_mesa_DepthMask( GLboolean flag ); + +extern void GLAPIENTRY +_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax ); + +extern void +_mesa_init_depth( GLcontext * ctx ); + +#else + +/** No-op */ +#define _mesa_init_depth( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/descrip.mms b/src/mesa/main/descrip.mms new file mode 100644 index 00000000000..ce298229c3e --- /dev/null +++ b/src/mesa/main/descrip.mms @@ -0,0 +1,210 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen [email protected] +# Last revision : 10 May 2005 + +.first + define gl [---.include.gl] + define math [-.math] + define shader [-.shader] + +.include [---]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [---.include],[-.glapi],[-.shader] +LIBDIR = [---.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short) + +SOURCES =accum.c \ + api_arrayelt.c \ + api_loopback.c \ + api_noop.c \ + api_validate.c \ + attrib.c \ + blend.c \ + bufferobj.c \ + buffers.c \ + clip.c \ + colortab.c \ + context.c \ + convolve.c \ + debug.c \ + depth.c \ + dispatch.c \ + dlist.c \ + drawpix.c \ + enable.c \ + enums.c \ + eval.c \ + execmem.c \ + extensions.c \ + fbobject.c \ + feedback.c \ + fog.c \ + framebuffer.c \ + get.c \ + getstring.c \ + hash.c \ + hint.c \ + histogram.c \ + image.c \ + imports.c \ + light.c \ + lines.c \ + matrix.c \ + mm.c \ + occlude.c \ + pixel.c \ + points.c \ + polygon.c \ + rastpos.c \ + renderbuffer.c \ + state.c \ + stencil.c \ + texcompress.c \ + texcompress_fxt1.c \ + texcompress_s3tc.c \ + texenvprogram.c \ + texformat.c \ + teximage.c \ + texobj.c \ + texrender.c \ + texstate.c \ + texstore.c \ + varray.c \ + vtxfmt.c + +OBJECTS=accum.obj,\ +api_arrayelt.obj,\ +api_loopback.obj,\ +api_noop.obj,\ +api_validate.obj,\ +attrib.obj,\ +blend.obj,\ +bufferobj.obj,\ +buffers.obj,\ +clip.obj,\ +colortab.obj,\ +context.obj,\ +convolve.obj,\ +debug.obj,\ +depth.obj,\ +dispatch.obj,\ +dlist.obj,\ +drawpix.obj,\ +enable.obj,\ +enums.obj,\ +eval.obj,\ +execmem.obj,\ +extensions.obj,\ +fbobject.obj,\ +feedback.obj,\ +fog.obj,\ +framebuffer.obj,\ +get.obj,\ +getstring.obj,\ +hash.obj,\ +hint.obj,\ +histogram.obj,\ +image.obj,\ +imports.obj,\ +light.obj,\ +lines.obj,\ +matrix.obj,\ +mm.obj,\ +occlude.obj,\ +pixel.obj,\ +points.obj,\ +polygon.obj,\ +rastpos.obj,\ +renderbuffer.obj,\ +state.obj,\ +stencil.obj,\ +texcompress.obj,\ +texcompress_fxt1.obj,\ +texcompress_s3tc.obj,\ +texenvprogram.obj,\ +texformat.obj,\ +teximage.obj,\ +texobj.obj,\ +texrender.obj,\ +texstate.obj,\ +texstore.obj,\ +varray.obj,\ +vtxfmt.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ $(MAKELIB) $(GL_LIB) $(OBJECTS) + @ rename $(GL_LIB)* $(LIBDIR) + +clean : + purge + delete *.obj;* + +accum.obj : accum.c +api_arrayelt.obj : api_arrayelt.c +api_loopback.obj : api_loopback.c +api_noop.obj : api_noop.c +api_validate.obj : api_validate.c +attrib.obj : attrib.c +blend.obj : blend.c +bufferobj.obj : bufferobj.c +buffers.obj : buffers.c +clip.obj : clip.c +colortab.obj : colortab.c +context.obj : context.c +convolve.obj : convolve.c +debug.obj : debug.c +depth.obj : depth.c +dispatch.obj : dispatch.c +dlist.obj : dlist.c +drawpix.obj : drawpix.c +enable.obj : enable.c +enums.obj : enums.c +eval.obj : eval.c +execmem.obj : execmem.c +extensions.obj : extensions.c +fbobject.obj : fbobject.c +feedback.obj : feedback.c +fog.obj : fog.c +framebuffer.obj : framebuffer.c +get.obj : get.c +getstring.obj : getstring.c +hash.obj : hash.c +hint.obj : hint.c +histogram.obj : histogram.c +image.obj : image.c +imports.obj : imports.c vsnprintf.c +light.obj : light.c +lines.obj : lines.c +matrix.obj : matrix.c +mm.obj: mm.c +occlude.obj : occlude.c +pixel.obj : pixel.c +points.obj : points.c +polygon.obj : polygon.c +rastpos.obj : rastpos.c +renderbuffer.obj : renderbuffer.c +state.obj : state.c +stencil.obj : stencil.c +texcompress.obj : texcompress.c +texcompress_fxt1.obj : texcompress_fxt1.c + cc$(CFLAGS)/warn=(disable=SHIFTCOUNT) texcompress_fxt1.c +texcompress_s3tc.obj : texcompress_s3tc.c +texenvprogram.obj : texenvprogram.c +texformat.obj : texformat.c +teximage.obj : teximage.c +texobj.obj : texobj.c +texrender.obj : texrender.c +texstate.obj : texstate.c +texstore.obj : texstore.c +varray.obj : varray.c +vtxfmt.obj : vtxfmt.c diff --git a/src/mesa/main/dispatch.c b/src/mesa/main/dispatch.c new file mode 100644 index 00000000000..05c1c36c0d2 --- /dev/null +++ b/src/mesa/main/dispatch.c @@ -0,0 +1,95 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file dispatch.c + * + * This file generates all the gl* function entrypoints. This code is not + * used if optimized assembly stubs are available (e.g., using x86/glapi_x86.S + * on IA32 or sparc/glapi_sparc.S on SPARC). + * + * \note + * This file is also used to build the client-side libGL that loads DRI-based + * device drivers. At build-time it is symlinked to src/glx/x11. + * + * \author Brian Paul <[email protected]> + */ + +#ifndef GLX_USE_APPLEGL + +#include "glheader.h" +#include "glapi.h" +#include "glapitable.h" +#include "glthread.h" + + +#if !(defined(USE_X86_ASM) || defined(USE_X86_64_ASM) || defined(USE_SPARC_ASM)) + +#if defined(WIN32) +#define KEYWORD1 GLAPI +#else +#define KEYWORD1 PUBLIC +#endif + +#define KEYWORD2 GLAPIENTRY + +#if defined(USE_MGL_NAMESPACE) +#define NAME(func) mgl##func +#else +#define NAME(func) gl##func +#endif + +#if 0 /* Use this to log GL calls to stdout (for DEBUG only!) */ + +#define F stdout +#define DISPATCH(FUNC, ARGS, MESSAGE) \ + fprintf MESSAGE; \ + CALL_ ## FUNC(GET_DISPATCH(), ARGS); + +#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \ + fprintf MESSAGE; \ + return CALL_ ## FUNC(GET_DISPATCH(), ARGS); + +#else + +#define DISPATCH(FUNC, ARGS, MESSAGE) \ + CALL_ ## FUNC(GET_DISPATCH(), ARGS); + +#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \ + return CALL_ ## FUNC(GET_DISPATCH(), ARGS); + +#endif /* logging */ + + +#ifndef GLAPIENTRY +#define GLAPIENTRY +#endif + +#include "dispatch.h" +#include "glapitemp.h" + +#endif /* USE_X86_ASM */ + +#endif /* !GLX_USE_APPLEGL */ diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c new file mode 100644 index 00000000000..7bd11c31af5 --- /dev/null +++ b/src/mesa/main/dlist.c @@ -0,0 +1,8434 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file dlist.c + * Display lists management functions. + */ + +#include "glheader.h" +#include "imports.h" +#include "api_arrayelt.h" +#include "api_loopback.h" +#include "config.h" +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program +#include "arbprogram.h" +#include "program.h" +#endif +#include "attrib.h" +#include "blend.h" +#include "buffers.h" +#if FEATURE_ARB_vertex_buffer_object +#include "bufferobj.h" +#endif +#include "clip.h" +#include "colormac.h" +#include "colortab.h" +#include "context.h" +#include "convolve.h" +#include "depth.h" +#include "dlist.h" +#include "enable.h" +#include "enums.h" +#include "eval.h" +#include "extensions.h" +#include "feedback.h" +#include "get.h" +#include "glapi.h" +#include "hash.h" +#include "histogram.h" +#include "image.h" +#include "light.h" +#include "lines.h" +#include "dlist.h" +#include "macros.h" +#include "matrix.h" +#include "occlude.h" +#include "pixel.h" +#include "points.h" +#include "polygon.h" +#include "state.h" +#include "texobj.h" +#include "teximage.h" +#include "texstate.h" +#include "mtypes.h" +#include "varray.h" +#if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program +#include "nvprogram.h" +#include "program.h" +#endif +#if FEATURE_ATI_fragment_shader +#include "atifragshader.h" +#endif + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "dispatch.h" + + +/** + * Flush vertices. + * + * \param ctx GL context. + * + * Checks if dd_function_table::SaveNeedFlush is marked to flush + * stored (save) vertices, and calls + * dd_function_table::SaveFlushVertices if so. + */ +#define SAVE_FLUSH_VERTICES(ctx) \ +do { \ + if (ctx->Driver.SaveNeedFlush) \ + ctx->Driver.SaveFlushVertices(ctx); \ +} while (0) + + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair, with return value. + * + * \param ctx GL context. + * \param retval value to return value in case the assertion fails. + */ +#define ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval) \ +do { \ + if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON || \ + ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) { \ + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \ + return retval; \ + } \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair. + * + * \param ctx GL context. + */ +#define ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx) \ +do { \ + if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON || \ + ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) { \ + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \ + return; \ + } \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair and flush the vertices. + * + * \param ctx GL context. + */ +#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx) \ +do { \ + ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx); \ + SAVE_FLUSH_VERTICES(ctx); \ +} while (0) + +/** + * Macro to assert that the API call was made outside the + * glBegin()/glEnd() pair and flush the vertices, with return value. + * + * \param ctx GL context. + * \param retval value to return value in case the assertion fails. + */ +#define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)\ +do { \ + ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval); \ + SAVE_FLUSH_VERTICES(ctx); \ +} while (0) + + + +/** + * Display list opcodes. + * + * The fact that these identifiers are assigned consecutive + * integer values starting at 0 is very important, see InstSize array usage) + */ +typedef enum { + OPCODE_INVALID = -1, /* Force signed enum */ + OPCODE_ACCUM, + OPCODE_ALPHA_FUNC, + OPCODE_BIND_TEXTURE, + OPCODE_BITMAP, + OPCODE_BLEND_COLOR, + OPCODE_BLEND_EQUATION, + OPCODE_BLEND_EQUATION_SEPARATE, + OPCODE_BLEND_FUNC_SEPARATE, + OPCODE_CALL_LIST, + OPCODE_CALL_LIST_OFFSET, + OPCODE_CLEAR, + OPCODE_CLEAR_ACCUM, + OPCODE_CLEAR_COLOR, + OPCODE_CLEAR_DEPTH, + OPCODE_CLEAR_INDEX, + OPCODE_CLEAR_STENCIL, + OPCODE_CLIP_PLANE, + OPCODE_COLOR_MASK, + OPCODE_COLOR_MATERIAL, + OPCODE_COLOR_TABLE, + OPCODE_COLOR_TABLE_PARAMETER_FV, + OPCODE_COLOR_TABLE_PARAMETER_IV, + OPCODE_COLOR_SUB_TABLE, + OPCODE_CONVOLUTION_FILTER_1D, + OPCODE_CONVOLUTION_FILTER_2D, + OPCODE_CONVOLUTION_PARAMETER_I, + OPCODE_CONVOLUTION_PARAMETER_IV, + OPCODE_CONVOLUTION_PARAMETER_F, + OPCODE_CONVOLUTION_PARAMETER_FV, + OPCODE_COPY_COLOR_SUB_TABLE, + OPCODE_COPY_COLOR_TABLE, + OPCODE_COPY_PIXELS, + OPCODE_COPY_TEX_IMAGE1D, + OPCODE_COPY_TEX_IMAGE2D, + OPCODE_COPY_TEX_SUB_IMAGE1D, + OPCODE_COPY_TEX_SUB_IMAGE2D, + OPCODE_COPY_TEX_SUB_IMAGE3D, + OPCODE_CULL_FACE, + OPCODE_DEPTH_FUNC, + OPCODE_DEPTH_MASK, + OPCODE_DEPTH_RANGE, + OPCODE_DISABLE, + OPCODE_DRAW_BUFFER, + OPCODE_DRAW_PIXELS, + OPCODE_ENABLE, + OPCODE_EVALMESH1, + OPCODE_EVALMESH2, + OPCODE_FOG, + OPCODE_FRONT_FACE, + OPCODE_FRUSTUM, + OPCODE_HINT, + OPCODE_HISTOGRAM, + OPCODE_INDEX_MASK, + OPCODE_INIT_NAMES, + OPCODE_LIGHT, + OPCODE_LIGHT_MODEL, + OPCODE_LINE_STIPPLE, + OPCODE_LINE_WIDTH, + OPCODE_LIST_BASE, + OPCODE_LOAD_IDENTITY, + OPCODE_LOAD_MATRIX, + OPCODE_LOAD_NAME, + OPCODE_LOGIC_OP, + OPCODE_MAP1, + OPCODE_MAP2, + OPCODE_MAPGRID1, + OPCODE_MAPGRID2, + OPCODE_MATRIX_MODE, + OPCODE_MIN_MAX, + OPCODE_MULT_MATRIX, + OPCODE_ORTHO, + OPCODE_PASSTHROUGH, + OPCODE_PIXEL_MAP, + OPCODE_PIXEL_TRANSFER, + OPCODE_PIXEL_ZOOM, + OPCODE_POINT_SIZE, + OPCODE_POINT_PARAMETERS, + OPCODE_POLYGON_MODE, + OPCODE_POLYGON_STIPPLE, + OPCODE_POLYGON_OFFSET, + OPCODE_POP_ATTRIB, + OPCODE_POP_MATRIX, + OPCODE_POP_NAME, + OPCODE_PRIORITIZE_TEXTURE, + OPCODE_PUSH_ATTRIB, + OPCODE_PUSH_MATRIX, + OPCODE_PUSH_NAME, + OPCODE_RASTER_POS, + OPCODE_READ_BUFFER, + OPCODE_RESET_HISTOGRAM, + OPCODE_RESET_MIN_MAX, + OPCODE_ROTATE, + OPCODE_SCALE, + OPCODE_SCISSOR, + OPCODE_SELECT_TEXTURE_SGIS, + OPCODE_SELECT_TEXTURE_COORD_SET, + OPCODE_SHADE_MODEL, + OPCODE_STENCIL_FUNC, + OPCODE_STENCIL_MASK, + OPCODE_STENCIL_OP, + OPCODE_TEXENV, + OPCODE_TEXGEN, + OPCODE_TEXPARAMETER, + OPCODE_TEX_IMAGE1D, + OPCODE_TEX_IMAGE2D, + OPCODE_TEX_IMAGE3D, + OPCODE_TEX_SUB_IMAGE1D, + OPCODE_TEX_SUB_IMAGE2D, + OPCODE_TEX_SUB_IMAGE3D, + OPCODE_TRANSLATE, + OPCODE_VIEWPORT, + OPCODE_WINDOW_POS, + /* GL_ARB_multitexture */ + OPCODE_ACTIVE_TEXTURE, + /* GL_SGIX/SGIS_pixel_texture */ + OPCODE_PIXEL_TEXGEN_SGIX, + OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS, + /* GL_ARB_texture_compression */ + OPCODE_COMPRESSED_TEX_IMAGE_1D, + OPCODE_COMPRESSED_TEX_IMAGE_2D, + OPCODE_COMPRESSED_TEX_IMAGE_3D, + OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, + OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, + OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, + /* GL_ARB_multisample */ + OPCODE_SAMPLE_COVERAGE, + /* GL_ARB_window_pos */ + OPCODE_WINDOW_POS_ARB, + /* GL_NV_vertex_program */ + OPCODE_BIND_PROGRAM_NV, + OPCODE_EXECUTE_PROGRAM_NV, + OPCODE_REQUEST_RESIDENT_PROGRAMS_NV, + OPCODE_LOAD_PROGRAM_NV, + OPCODE_PROGRAM_PARAMETER4F_NV, + OPCODE_TRACK_MATRIX_NV, + /* GL_NV_fragment_program */ + OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, + OPCODE_PROGRAM_NAMED_PARAMETER_NV, + /* GL_EXT_stencil_two_side */ + OPCODE_ACTIVE_STENCIL_FACE_EXT, + /* GL_EXT_depth_bounds_test */ + OPCODE_DEPTH_BOUNDS_EXT, + /* GL_ARB_vertex/fragment_program */ + OPCODE_PROGRAM_STRING_ARB, + OPCODE_PROGRAM_ENV_PARAMETER_ARB, + /* GL_ARB_occlusion_query */ + OPCODE_BEGIN_QUERY_ARB, + OPCODE_END_QUERY_ARB, + /* GL_ARB_draw_buffers */ + OPCODE_DRAW_BUFFERS_ARB, + /* GL_ATI_fragment_shader */ + OPCODE_BIND_FRAGMENT_SHADER_ATI, + OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI, + /* OpenGL 2.0 */ + OPCODE_STENCIL_FUNC_SEPARATE, + OPCODE_STENCIL_OP_SEPARATE, + OPCODE_STENCIL_MASK_SEPARATE, + + /* Vertex attributes -- fallback for when optimized display + * list build isn't active. + */ + OPCODE_ATTR_1F_NV, + OPCODE_ATTR_2F_NV, + OPCODE_ATTR_3F_NV, + OPCODE_ATTR_4F_NV, + OPCODE_ATTR_1F_ARB, + OPCODE_ATTR_2F_ARB, + OPCODE_ATTR_3F_ARB, + OPCODE_ATTR_4F_ARB, + OPCODE_MATERIAL, + OPCODE_INDEX, + OPCODE_EDGEFLAG, + OPCODE_BEGIN, + OPCODE_END, + OPCODE_RECTF, + OPCODE_EVAL_C1, + OPCODE_EVAL_C2, + OPCODE_EVAL_P1, + OPCODE_EVAL_P2, + + + /* The following three are meta instructions */ + OPCODE_ERROR, /* raise compiled-in error */ + OPCODE_CONTINUE, + OPCODE_END_OF_LIST, + OPCODE_EXT_0 +} OpCode; + + + +/** + * Display list node. + * + * Display list instructions are stored as sequences of "nodes". Nodes + * are allocated in blocks. Each block has BLOCK_SIZE nodes. Blocks + * are linked together with a pointer. + * + * Each instruction in the display list is stored as a sequence of + * contiguous nodes in memory. + * Each node is the union of a variety of data types. + */ +union node { + OpCode opcode; + GLboolean b; + GLbitfield bf; + GLubyte ub; + GLshort s; + GLushort us; + GLint i; + GLuint ui; + GLenum e; + GLfloat f; + GLvoid *data; + void *next; /* If prev node's opcode==OPCODE_CONTINUE */ +}; + + +/** + * How many nodes to allocate at a time. + * + * \note Reduced now that we hold vertices etc. elsewhere. + */ +#define BLOCK_SIZE 256 + + + +/** + * Number of nodes of storage needed for each instruction. + * Sizes for dynamically allocated opcodes are stored in the context struct. + */ +static GLuint InstSize[ OPCODE_END_OF_LIST+1 ]; + +void mesa_print_display_list( GLuint list ); + + +/**********************************************************************/ +/***** Private *****/ +/**********************************************************************/ + +/* + * Make an empty display list. This is used by glGenLists() to + * reserver display list IDs. + */ +static struct mesa_display_list *make_list( GLuint list, GLuint count ) +{ + struct mesa_display_list *dlist = CALLOC_STRUCT( mesa_display_list ); + dlist->id = list; + dlist->node = (Node *) MALLOC( sizeof(Node) * count ); + dlist->node[0].opcode = OPCODE_END_OF_LIST; + return dlist; +} + + + +/* + * Destroy all nodes in a display list. + * \param list - display list number + */ +void _mesa_destroy_list( GLcontext *ctx, GLuint list ) +{ + struct mesa_display_list *dlist; + Node *n, *block; + GLboolean done; + + if (list==0) + return; + + dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + if (!dlist) + return; + + n = block = dlist->node; + + done = block ? GL_FALSE : GL_TRUE; + while (!done) { + + /* check for extension opcodes first */ + + GLint i = (GLint) n[0].opcode - (GLint) OPCODE_EXT_0; + if (i >= 0 && i < (GLint) ctx->ListExt.NumOpcodes) { + ctx->ListExt.Opcode[i].Destroy(ctx, &n[1]); + n += ctx->ListExt.Opcode[i].Size; + } + else { + switch (n[0].opcode) { + /* for some commands, we need to free malloc'd memory */ + case OPCODE_MAP1: + FREE(n[6].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_MAP2: + FREE(n[10].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_DRAW_PIXELS: + FREE( n[5].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_BITMAP: + FREE( n[7].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COLOR_TABLE: + FREE( n[6].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COLOR_SUB_TABLE: + FREE( n[6].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_CONVOLUTION_FILTER_1D: + FREE( n[6].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_CONVOLUTION_FILTER_2D: + FREE( n[7].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_POLYGON_STIPPLE: + FREE( n[1].data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_IMAGE1D: + FREE(n[8].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_IMAGE2D: + FREE( n[9]. data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_IMAGE3D: + FREE( n[10]. data ); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_SUB_IMAGE1D: + FREE(n[7].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_SUB_IMAGE2D: + FREE(n[9].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_TEX_SUB_IMAGE3D: + FREE(n[11].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_IMAGE_1D: + FREE(n[7].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_IMAGE_2D: + FREE(n[8].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_IMAGE_3D: + FREE(n[9].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: + FREE(n[7].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: + FREE(n[9].data); + n += InstSize[n[0].opcode]; + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: + FREE(n[11].data); + n += InstSize[n[0].opcode]; + break; +#if FEATURE_NV_vertex_program + case OPCODE_LOAD_PROGRAM_NV: + FREE(n[4].data); /* program string */ + n += InstSize[n[0].opcode]; + break; + case OPCODE_REQUEST_RESIDENT_PROGRAMS_NV: + FREE(n[2].data); /* array of program ids */ + n += InstSize[n[0].opcode]; + break; +#endif +#if FEATURE_NV_fragment_program + case OPCODE_PROGRAM_NAMED_PARAMETER_NV: + FREE(n[3].data); /* parameter name */ + n += InstSize[n[0].opcode]; + break; +#endif +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + case OPCODE_PROGRAM_STRING_ARB: + FREE(n[4].data); /* program string */ + n += InstSize[n[0].opcode]; + break; +#endif + case OPCODE_CONTINUE: + n = (Node *) n[1].next; + FREE( block ); + block = n; + break; + case OPCODE_END_OF_LIST: + FREE( block ); + done = GL_TRUE; + break; + default: + /* Most frequent case */ + n += InstSize[n[0].opcode]; + break; + } + } + } + + FREE( dlist ); + _mesa_HashRemove(ctx->Shared->DisplayList, list); +} + + + +/* + * Translate the nth element of list from type to GLuint. + */ +static GLuint translate_id( GLsizei n, GLenum type, const GLvoid *list ) +{ + GLbyte *bptr; + GLubyte *ubptr; + GLshort *sptr; + GLushort *usptr; + GLint *iptr; + GLuint *uiptr; + GLfloat *fptr; + + switch (type) { + case GL_BYTE: + bptr = (GLbyte *) list; + return (GLuint) *(bptr+n); + case GL_UNSIGNED_BYTE: + ubptr = (GLubyte *) list; + return (GLuint) *(ubptr+n); + case GL_SHORT: + sptr = (GLshort *) list; + return (GLuint) *(sptr+n); + case GL_UNSIGNED_SHORT: + usptr = (GLushort *) list; + return (GLuint) *(usptr+n); + case GL_INT: + iptr = (GLint *) list; + return (GLuint) *(iptr+n); + case GL_UNSIGNED_INT: + uiptr = (GLuint *) list; + return (GLuint) *(uiptr+n); + case GL_FLOAT: + fptr = (GLfloat *) list; + return (GLuint) *(fptr+n); + case GL_2_BYTES: + ubptr = ((GLubyte *) list) + 2*n; + return (GLuint) *ubptr * 256 + (GLuint) *(ubptr+1); + case GL_3_BYTES: + ubptr = ((GLubyte *) list) + 3*n; + return (GLuint) *ubptr * 65536 + + (GLuint) *(ubptr+1) * 256 + + (GLuint) *(ubptr+2); + case GL_4_BYTES: + ubptr = ((GLubyte *) list) + 4*n; + return (GLuint) *ubptr * 16777216 + + (GLuint) *(ubptr+1) * 65536 + + (GLuint) *(ubptr+2) * 256 + + (GLuint) *(ubptr+3); + default: + return 0; + } +} + + + + +/**********************************************************************/ +/***** Public *****/ +/**********************************************************************/ + +/** + * Do one-time initialiazations for display lists. + */ +void +_mesa_init_lists( void ) +{ + static int init_flag = 0; + + if (init_flag==0) { + InstSize[OPCODE_ACCUM] = 3; + InstSize[OPCODE_ALPHA_FUNC] = 3; + InstSize[OPCODE_BIND_TEXTURE] = 3; + InstSize[OPCODE_BITMAP] = 8; + InstSize[OPCODE_BLEND_COLOR] = 5; + InstSize[OPCODE_BLEND_EQUATION] = 2; + InstSize[OPCODE_BLEND_EQUATION_SEPARATE] = 3; + InstSize[OPCODE_BLEND_FUNC_SEPARATE] = 5; + InstSize[OPCODE_CALL_LIST] = 2; + InstSize[OPCODE_CALL_LIST_OFFSET] = 3; + InstSize[OPCODE_CLEAR] = 2; + InstSize[OPCODE_CLEAR_ACCUM] = 5; + InstSize[OPCODE_CLEAR_COLOR] = 5; + InstSize[OPCODE_CLEAR_DEPTH] = 2; + InstSize[OPCODE_CLEAR_INDEX] = 2; + InstSize[OPCODE_CLEAR_STENCIL] = 2; + InstSize[OPCODE_CLIP_PLANE] = 6; + InstSize[OPCODE_COLOR_MASK] = 5; + InstSize[OPCODE_COLOR_MATERIAL] = 3; + InstSize[OPCODE_COLOR_TABLE] = 7; + InstSize[OPCODE_COLOR_TABLE_PARAMETER_FV] = 7; + InstSize[OPCODE_COLOR_TABLE_PARAMETER_IV] = 7; + InstSize[OPCODE_COLOR_SUB_TABLE] = 7; + InstSize[OPCODE_CONVOLUTION_FILTER_1D] = 7; + InstSize[OPCODE_CONVOLUTION_FILTER_2D] = 8; + InstSize[OPCODE_CONVOLUTION_PARAMETER_I] = 4; + InstSize[OPCODE_CONVOLUTION_PARAMETER_IV] = 7; + InstSize[OPCODE_CONVOLUTION_PARAMETER_F] = 4; + InstSize[OPCODE_CONVOLUTION_PARAMETER_FV] = 7; + InstSize[OPCODE_COPY_PIXELS] = 6; + InstSize[OPCODE_COPY_COLOR_SUB_TABLE] = 6; + InstSize[OPCODE_COPY_COLOR_TABLE] = 6; + InstSize[OPCODE_COPY_TEX_IMAGE1D] = 8; + InstSize[OPCODE_COPY_TEX_IMAGE2D] = 9; + InstSize[OPCODE_COPY_TEX_SUB_IMAGE1D] = 7; + InstSize[OPCODE_COPY_TEX_SUB_IMAGE2D] = 9; + InstSize[OPCODE_COPY_TEX_SUB_IMAGE3D] = 10; + InstSize[OPCODE_CULL_FACE] = 2; + InstSize[OPCODE_DEPTH_FUNC] = 2; + InstSize[OPCODE_DEPTH_MASK] = 2; + InstSize[OPCODE_DEPTH_RANGE] = 3; + InstSize[OPCODE_DISABLE] = 2; + InstSize[OPCODE_DRAW_BUFFER] = 2; + InstSize[OPCODE_DRAW_PIXELS] = 6; + InstSize[OPCODE_ENABLE] = 2; + InstSize[OPCODE_EVALMESH1] = 4; + InstSize[OPCODE_EVALMESH2] = 6; + InstSize[OPCODE_FOG] = 6; + InstSize[OPCODE_FRONT_FACE] = 2; + InstSize[OPCODE_FRUSTUM] = 7; + InstSize[OPCODE_HINT] = 3; + InstSize[OPCODE_HISTOGRAM] = 5; + InstSize[OPCODE_INDEX_MASK] = 2; + InstSize[OPCODE_INIT_NAMES] = 1; + InstSize[OPCODE_LIGHT] = 7; + InstSize[OPCODE_LIGHT_MODEL] = 6; + InstSize[OPCODE_LINE_STIPPLE] = 3; + InstSize[OPCODE_LINE_WIDTH] = 2; + InstSize[OPCODE_LIST_BASE] = 2; + InstSize[OPCODE_LOAD_IDENTITY] = 1; + InstSize[OPCODE_LOAD_MATRIX] = 17; + InstSize[OPCODE_LOAD_NAME] = 2; + InstSize[OPCODE_LOGIC_OP] = 2; + InstSize[OPCODE_MAP1] = 7; + InstSize[OPCODE_MAP2] = 11; + InstSize[OPCODE_MAPGRID1] = 4; + InstSize[OPCODE_MAPGRID2] = 7; + InstSize[OPCODE_MATRIX_MODE] = 2; + InstSize[OPCODE_MIN_MAX] = 4; + InstSize[OPCODE_MULT_MATRIX] = 17; + InstSize[OPCODE_ORTHO] = 7; + InstSize[OPCODE_PASSTHROUGH] = 2; + InstSize[OPCODE_PIXEL_MAP] = 4; + InstSize[OPCODE_PIXEL_TRANSFER] = 3; + InstSize[OPCODE_PIXEL_ZOOM] = 3; + InstSize[OPCODE_POINT_SIZE] = 2; + InstSize[OPCODE_POINT_PARAMETERS] = 5; + InstSize[OPCODE_POLYGON_MODE] = 3; + InstSize[OPCODE_POLYGON_STIPPLE] = 2; + InstSize[OPCODE_POLYGON_OFFSET] = 3; + InstSize[OPCODE_POP_ATTRIB] = 1; + InstSize[OPCODE_POP_MATRIX] = 1; + InstSize[OPCODE_POP_NAME] = 1; + InstSize[OPCODE_PRIORITIZE_TEXTURE] = 3; + InstSize[OPCODE_PUSH_ATTRIB] = 2; + InstSize[OPCODE_PUSH_MATRIX] = 1; + InstSize[OPCODE_PUSH_NAME] = 2; + InstSize[OPCODE_RASTER_POS] = 5; + InstSize[OPCODE_READ_BUFFER] = 2; + InstSize[OPCODE_RESET_HISTOGRAM] = 2; + InstSize[OPCODE_RESET_MIN_MAX] = 2; + InstSize[OPCODE_ROTATE] = 5; + InstSize[OPCODE_SCALE] = 4; + InstSize[OPCODE_SCISSOR] = 5; + InstSize[OPCODE_STENCIL_FUNC] = 4; + InstSize[OPCODE_STENCIL_MASK] = 2; + InstSize[OPCODE_STENCIL_OP] = 4; + InstSize[OPCODE_SHADE_MODEL] = 2; + InstSize[OPCODE_TEXENV] = 7; + InstSize[OPCODE_TEXGEN] = 7; + InstSize[OPCODE_TEXPARAMETER] = 7; + InstSize[OPCODE_TEX_IMAGE1D] = 9; + InstSize[OPCODE_TEX_IMAGE2D] = 10; + InstSize[OPCODE_TEX_IMAGE3D] = 11; + InstSize[OPCODE_TEX_SUB_IMAGE1D] = 8; + InstSize[OPCODE_TEX_SUB_IMAGE2D] = 10; + InstSize[OPCODE_TEX_SUB_IMAGE3D] = 12; + InstSize[OPCODE_TRANSLATE] = 4; + InstSize[OPCODE_VIEWPORT] = 5; + InstSize[OPCODE_WINDOW_POS] = 5; + InstSize[OPCODE_CONTINUE] = 2; + InstSize[OPCODE_ERROR] = 3; + InstSize[OPCODE_END_OF_LIST] = 1; + /* GL_SGIX/SGIS_pixel_texture */ + InstSize[OPCODE_PIXEL_TEXGEN_SGIX] = 2; + InstSize[OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS] = 3; + /* GL_ARB_texture_compression */ + InstSize[OPCODE_COMPRESSED_TEX_IMAGE_1D] = 8; + InstSize[OPCODE_COMPRESSED_TEX_IMAGE_2D] = 9; + InstSize[OPCODE_COMPRESSED_TEX_IMAGE_3D] = 10; + InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D] = 8; + InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D] = 10; + InstSize[OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D] = 12; + /* GL_ARB_multisample */ + InstSize[OPCODE_SAMPLE_COVERAGE] = 3; + /* GL_ARB_multitexture */ + InstSize[OPCODE_ACTIVE_TEXTURE] = 2; + /* GL_ARB_window_pos */ + InstSize[OPCODE_WINDOW_POS_ARB] = 4; + /* GL_NV_vertex_program */ + InstSize[OPCODE_BIND_PROGRAM_NV] = 3; + InstSize[OPCODE_EXECUTE_PROGRAM_NV] = 7; + InstSize[OPCODE_REQUEST_RESIDENT_PROGRAMS_NV] = 2; + InstSize[OPCODE_LOAD_PROGRAM_NV] = 5; + InstSize[OPCODE_PROGRAM_PARAMETER4F_NV] = 7; + InstSize[OPCODE_TRACK_MATRIX_NV] = 5; + /* GL_NV_fragment_program */ + InstSize[OPCODE_PROGRAM_LOCAL_PARAMETER_ARB] = 7; + InstSize[OPCODE_PROGRAM_NAMED_PARAMETER_NV] = 8; + /* GL_EXT_stencil_two_side */ + InstSize[OPCODE_ACTIVE_STENCIL_FACE_EXT] = 2; + /* GL_EXT_depth_bounds_test */ + InstSize[OPCODE_DEPTH_BOUNDS_EXT] = 3; +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + InstSize[OPCODE_PROGRAM_STRING_ARB] = 5; + InstSize[OPCODE_PROGRAM_ENV_PARAMETER_ARB] = 7; +#endif +#if FEATURE_ARB_occlusion_query + InstSize[OPCODE_BEGIN_QUERY_ARB] = 3; + InstSize[OPCODE_END_QUERY_ARB] = 2; +#endif + InstSize[OPCODE_DRAW_BUFFERS_ARB] = 2 + MAX_DRAW_BUFFERS; +#if FEATURE_ATI_fragment_shader + InstSize[OPCODE_BIND_FRAGMENT_SHADER_ATI] = 2; + InstSize[OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI] = 6; +#endif + /* OpenGL 2.0 */ + InstSize[OPCODE_STENCIL_FUNC_SEPARATE] = 5; + InstSize[OPCODE_STENCIL_MASK_SEPARATE] = 3; + InstSize[OPCODE_STENCIL_OP_SEPARATE] = 5; + + InstSize[OPCODE_ATTR_1F_NV] = 3; + InstSize[OPCODE_ATTR_2F_NV] = 4; + InstSize[OPCODE_ATTR_3F_NV] = 5; + InstSize[OPCODE_ATTR_4F_NV] = 6; + InstSize[OPCODE_ATTR_1F_ARB] = 3; + InstSize[OPCODE_ATTR_2F_ARB] = 4; + InstSize[OPCODE_ATTR_3F_ARB] = 5; + InstSize[OPCODE_ATTR_4F_ARB] = 6; + InstSize[OPCODE_MATERIAL] = 7; + InstSize[OPCODE_INDEX] = 2; + InstSize[OPCODE_EDGEFLAG] = 2; + InstSize[OPCODE_BEGIN] = 2; + InstSize[OPCODE_END] = 1; + InstSize[OPCODE_RECTF] = 5; + InstSize[OPCODE_EVAL_C1] = 2; + InstSize[OPCODE_EVAL_C2] = 3; + InstSize[OPCODE_EVAL_P1] = 2; + InstSize[OPCODE_EVAL_P2] = 3; + } + init_flag = 1; +} + + + +/** + * Wrapper for _mesa_unpack_image() that handles pixel buffer objects. + * \todo This won't suffice when the PBO is really in VRAM/GPU memory. + */ +static GLvoid * +unpack_image( GLuint dimensions, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack ) +{ + if (unpack->BufferObj->Name == 0) { + /* no PBO */ + return _mesa_unpack_image(dimensions, width, height, depth, format, type, + pixels, unpack); + } + else if (_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, + format, type, pixels)) { + const GLubyte *src = ADD_POINTERS(unpack->BufferObj->Data, pixels); + return _mesa_unpack_image(dimensions, width, height, depth, format, type, + src, unpack); + } + /* bad access! */ + return NULL; +} + + +/* + * Allocate space for a display list instruction. + * \param opcode - type of instruction + * argcount - size in bytes of data required. + * \return pointer to the usable data area (not including the internal + * opcode). + */ +void * +_mesa_alloc_instruction( GLcontext *ctx, int opcode, GLint sz ) +{ + Node *n, *newblock; + GLuint count = 1 + (sz + sizeof(Node) - 1) / sizeof(Node); + +#ifdef DEBUG + if (opcode < (int) OPCODE_EXT_0) { + assert( count == InstSize[opcode] ); + } +#endif + + if (ctx->ListState.CurrentPos + count + 2 > BLOCK_SIZE) { + /* This block is full. Allocate a new block and chain to it */ + n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos; + n[0].opcode = OPCODE_CONTINUE; + newblock = (Node *) MALLOC( sizeof(Node) * BLOCK_SIZE ); + if (!newblock) { + _mesa_error( ctx, GL_OUT_OF_MEMORY, "Building display list" ); + return NULL; + } + n[1].next = (Node *) newblock; + ctx->ListState.CurrentBlock = newblock; + ctx->ListState.CurrentPos = 0; + } + + n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos; + ctx->ListState.CurrentPos += count; + + n[0].opcode = (OpCode) opcode; + + return (void *)&n[1]; +} + + +/** + * This function allows modules and drivers to get their own opcodes + * for extending display list functionality. + * \param ctx the rendering context + * \param size number of bytes for storing the new display list command + * \param execute function to execute the new display list command + * \param destroy function to destroy the new display list command + * \param print function to print the new display list command + * \return the new opcode number or -1 if error + */ +GLint +_mesa_alloc_opcode( GLcontext *ctx, + GLuint size, + void (*execute)( GLcontext *, void * ), + void (*destroy)( GLcontext *, void * ), + void (*print)( GLcontext *, void * ) ) +{ + if (ctx->ListExt.NumOpcodes < MAX_DLIST_EXT_OPCODES) { + const GLuint i = ctx->ListExt.NumOpcodes++; + ctx->ListExt.Opcode[i].Size = 1 + (size + sizeof(Node) - 1)/sizeof(Node); + ctx->ListExt.Opcode[i].Execute = execute; + ctx->ListExt.Opcode[i].Destroy = destroy; + ctx->ListExt.Opcode[i].Print = print; + return i + OPCODE_EXT_0; + } + return -1; +} + + + +/* Mimic the old behaviour of alloc_instruction: + * - sz is in units of sizeof(Node) + * - return value a pointer to sizeof(Node) before the actual + * usable data area. + */ +#define ALLOC_INSTRUCTION(ctx, opcode, sz) \ + ((Node *)_mesa_alloc_instruction(ctx, opcode, sz*sizeof(Node)) - 1) + + + +/* + * Display List compilation functions + */ +static void GLAPIENTRY save_Accum( GLenum op, GLfloat value ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ACCUM, 2 ); + if (n) { + n[1].e = op; + n[2].f = value; + } + if (ctx->ExecuteFlag) { + CALL_Accum(ctx->Exec, ( op, value )); + } +} + + +static void GLAPIENTRY save_AlphaFunc( GLenum func, GLclampf ref ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ALPHA_FUNC, 2 ); + if (n) { + n[1].e = func; + n[2].f = (GLfloat) ref; + } + if (ctx->ExecuteFlag) { + CALL_AlphaFunc(ctx->Exec, ( func, ref )); + } +} + + +static void GLAPIENTRY save_BindTexture( GLenum target, GLuint texture ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BIND_TEXTURE, 2 ); + if (n) { + n[1].e = target; + n[2].ui = texture; + } + if (ctx->ExecuteFlag) { + CALL_BindTexture(ctx->Exec, ( target, texture )); + } +} + + +static void GLAPIENTRY save_Bitmap( GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, + GLfloat xmove, GLfloat ymove, + const GLubyte *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + GLvoid *image = _mesa_unpack_bitmap( width, height, pixels, &ctx->Unpack ); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BITMAP, 7 ); + if (n) { + n[1].i = (GLint) width; + n[2].i = (GLint) height; + n[3].f = xorig; + n[4].f = yorig; + n[5].f = xmove; + n[6].f = ymove; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_Bitmap(ctx->Exec, ( width, height, + xorig, yorig, xmove, ymove, pixels )); + } +} + + +static void GLAPIENTRY save_BlendEquation( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BLEND_EQUATION, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_BlendEquation(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY save_BlendEquationSeparateEXT( GLenum modeRGB, + GLenum modeA ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BLEND_EQUATION_SEPARATE, 2 ); + if (n) { + n[1].e = modeRGB; + n[2].e = modeA; + } + if (ctx->ExecuteFlag) { + CALL_BlendEquationSeparateEXT(ctx->Exec, ( modeRGB, modeA )); + } +} + + +static void GLAPIENTRY save_BlendFuncSeparateEXT(GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BLEND_FUNC_SEPARATE, 4 ); + if (n) { + n[1].e = sfactorRGB; + n[2].e = dfactorRGB; + n[3].e = sfactorA; + n[4].e = dfactorA; + } + if (ctx->ExecuteFlag) { + CALL_BlendFuncSeparateEXT(ctx->Exec, + (sfactorRGB, dfactorRGB, sfactorA, dfactorA)); + } +} + + +static void GLAPIENTRY save_BlendColor( GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BLEND_COLOR, 4 ); + if (n) { + n[1].f = red; + n[2].f = green; + n[3].f = blue; + n[4].f = alpha; + } + if (ctx->ExecuteFlag) { + CALL_BlendColor(ctx->Exec, ( red, green, blue, alpha )); + } +} + + +void GLAPIENTRY _mesa_save_CallList( GLuint list ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES(ctx); + + n = ALLOC_INSTRUCTION( ctx, OPCODE_CALL_LIST, 1 ); + if (n) { + n[1].ui = list; + } + + /* After this, we don't know what begin/end state we're in: + */ + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; + + if (ctx->ExecuteFlag) { + CALL_CallList(ctx->Exec, ( list )); + } +} + + +void GLAPIENTRY _mesa_save_CallLists( GLsizei n, GLenum type, const GLvoid *lists ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + GLboolean typeErrorFlag; + + SAVE_FLUSH_VERTICES(ctx); + + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_2_BYTES: + case GL_3_BYTES: + case GL_4_BYTES: + typeErrorFlag = GL_FALSE; + break; + default: + typeErrorFlag = GL_TRUE; + } + + for (i=0;i<n;i++) { + GLuint list = translate_id( i, type, lists ); + Node *n = ALLOC_INSTRUCTION( ctx, OPCODE_CALL_LIST_OFFSET, 2 ); + if (n) { + n[1].ui = list; + n[2].b = typeErrorFlag; + } + } + + /* After this, we don't know what begin/end state we're in: + */ + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; + + if (ctx->ExecuteFlag) { + CALL_CallLists(ctx->Exec, ( n, type, lists )); + } +} + + +static void GLAPIENTRY save_Clear( GLbitfield mask ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLEAR, 1 ); + if (n) { + n[1].bf = mask; + } + if (ctx->ExecuteFlag) { + CALL_Clear(ctx->Exec, ( mask )); + } +} + + +static void GLAPIENTRY save_ClearAccum( GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLEAR_ACCUM, 4 ); + if (n) { + n[1].f = red; + n[2].f = green; + n[3].f = blue; + n[4].f = alpha; + } + if (ctx->ExecuteFlag) { + CALL_ClearAccum(ctx->Exec, ( red, green, blue, alpha )); + } +} + + +static void GLAPIENTRY save_ClearColor( GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLEAR_COLOR, 4 ); + if (n) { + n[1].f = red; + n[2].f = green; + n[3].f = blue; + n[4].f = alpha; + } + if (ctx->ExecuteFlag) { + CALL_ClearColor(ctx->Exec, ( red, green, blue, alpha )); + } +} + + +static void GLAPIENTRY save_ClearDepth( GLclampd depth ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLEAR_DEPTH, 1 ); + if (n) { + n[1].f = (GLfloat) depth; + } + if (ctx->ExecuteFlag) { + CALL_ClearDepth(ctx->Exec, ( depth )); + } +} + + +static void GLAPIENTRY save_ClearIndex( GLfloat c ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLEAR_INDEX, 1 ); + if (n) { + n[1].f = c; + } + if (ctx->ExecuteFlag) { + CALL_ClearIndex(ctx->Exec, ( c )); + } +} + + +static void GLAPIENTRY save_ClearStencil( GLint s ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLEAR_STENCIL, 1 ); + if (n) { + n[1].i = s; + } + if (ctx->ExecuteFlag) { + CALL_ClearStencil(ctx->Exec, ( s )); + } +} + + +static void GLAPIENTRY save_ClipPlane( GLenum plane, const GLdouble *equ ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CLIP_PLANE, 5 ); + if (n) { + n[1].e = plane; + n[2].f = (GLfloat) equ[0]; + n[3].f = (GLfloat) equ[1]; + n[4].f = (GLfloat) equ[2]; + n[5].f = (GLfloat) equ[3]; + } + if (ctx->ExecuteFlag) { + CALL_ClipPlane(ctx->Exec, ( plane, equ )); + } +} + + + +static void GLAPIENTRY save_ColorMask( GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_MASK, 4 ); + if (n) { + n[1].b = red; + n[2].b = green; + n[3].b = blue; + n[4].b = alpha; + } + if (ctx->ExecuteFlag) { + CALL_ColorMask(ctx->Exec, ( red, green, blue, alpha )); + } +} + + +static void GLAPIENTRY save_ColorMaterial( GLenum face, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_MATERIAL, 2 ); + if (n) { + n[1].e = face; + n[2].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_ColorMaterial(ctx->Exec, ( face, mode )); + } +} + + +static void GLAPIENTRY save_ColorTable( GLenum target, GLenum internalFormat, + GLsizei width, GLenum format, GLenum type, + const GLvoid *table ) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_1D || + target == GL_PROXY_TEXTURE_2D || + target == GL_PROXY_TEXTURE_3D || + target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { + /* execute immediately */ + CALL_ColorTable(ctx->Exec, ( target, internalFormat, width, + format, type, table )); + } + else { + GLvoid *image = unpack_image(1, width, 1, 1, format, type, table, + &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_TABLE, 6 ); + if (n) { + n[1].e = target; + n[2].e = internalFormat; + n[3].i = width; + n[4].e = format; + n[5].e = type; + n[6].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_ColorTable(ctx->Exec, ( target, internalFormat, width, + format, type, table )); + } + } +} + + + +static void GLAPIENTRY +save_ColorTableParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_TABLE_PARAMETER_FV, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].f = params[0]; + if (pname == GL_COLOR_TABLE_SGI || + pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI || + pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI || + pname == GL_TEXTURE_COLOR_TABLE_SGI) { + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + } + + if (ctx->ExecuteFlag) { + CALL_ColorTableParameterfv(ctx->Exec, ( target, pname, params )); + } +} + + +static void GLAPIENTRY +save_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_TABLE_PARAMETER_IV, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].i = params[0]; + if (pname == GL_COLOR_TABLE_SGI || + pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI || + pname == GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI || + pname == GL_TEXTURE_COLOR_TABLE_SGI) { + n[4].i = params[1]; + n[5].i = params[2]; + n[6].i = params[3]; + } + } + + if (ctx->ExecuteFlag) { + CALL_ColorTableParameteriv(ctx->Exec, ( target, pname, params )); + } +} + + + +static void GLAPIENTRY save_ColorSubTable( GLenum target, GLsizei start, GLsizei count, + GLenum format, GLenum type, + const GLvoid *table) +{ + GET_CURRENT_CONTEXT(ctx); + GLvoid *image = unpack_image(1, count, 1, 1, format, type, table, + &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_SUB_TABLE, 6 ); + if (n) { + n[1].e = target; + n[2].i = start; + n[3].i = count; + n[4].e = format; + n[5].e = type; + n[6].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_ColorSubTable(ctx->Exec, (target, start, count, format, type, table)); + } +} + + +static void GLAPIENTRY +save_CopyColorSubTable(GLenum target, GLsizei start, + GLint x, GLint y, GLsizei width) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_COLOR_SUB_TABLE, 5 ); + if (n) { + n[1].e = target; + n[2].i = start; + n[3].i = x; + n[4].i = y; + n[5].i = width; + } + if (ctx->ExecuteFlag) { + CALL_CopyColorSubTable(ctx->Exec, (target, start, x, y, width)); + } +} + + +static void GLAPIENTRY +save_CopyColorTable(GLenum target, GLenum internalformat, + GLint x, GLint y, GLsizei width) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_COLOR_TABLE, 5 ); + if (n) { + n[1].e = target; + n[2].e = internalformat; + n[3].i = x; + n[4].i = y; + n[5].i = width; + } + if (ctx->ExecuteFlag) { + CALL_CopyColorTable(ctx->Exec, (target, internalformat, x, y, width)); + } +} + + +static void GLAPIENTRY +save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, + GLenum format, GLenum type, const GLvoid *filter) +{ + GET_CURRENT_CONTEXT(ctx); + GLvoid *image = unpack_image(1, width, 1, 1, format, type, filter, + &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_FILTER_1D, 6 ); + if (n) { + n[1].e = target; + n[2].e = internalFormat; + n[3].i = width; + n[4].e = format; + n[5].e = type; + n[6].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_ConvolutionFilter1D(ctx->Exec, ( target, internalFormat, width, + format, type, filter )); + } +} + + +static void GLAPIENTRY +save_ConvolutionFilter2D(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid *filter) +{ + GET_CURRENT_CONTEXT(ctx); + GLvoid *image = unpack_image(2, width, height, 1, format, type, filter, + &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_FILTER_2D, 7 ); + if (n) { + n[1].e = target; + n[2].e = internalFormat; + n[3].i = width; + n[4].i = height; + n[5].e = format; + n[6].e = type; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_ConvolutionFilter2D(ctx->Exec, ( target, internalFormat, width, height, + format, type, filter )); + } +} + + +static void GLAPIENTRY +save_ConvolutionParameteri(GLenum target, GLenum pname, GLint param) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_PARAMETER_I, 3 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].i = param; + } + if (ctx->ExecuteFlag) { + CALL_ConvolutionParameteri(ctx->Exec, ( target, pname, param )); + } +} + + +static void GLAPIENTRY +save_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_PARAMETER_IV, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].i = params[0]; + if (pname == GL_CONVOLUTION_BORDER_COLOR || + pname == GL_CONVOLUTION_FILTER_SCALE || + pname == GL_CONVOLUTION_FILTER_BIAS) { + n[4].i = params[1]; + n[5].i = params[2]; + n[6].i = params[3]; + } + else { + n[4].i = n[5].i = n[6].i = 0; + } + } + if (ctx->ExecuteFlag) { + CALL_ConvolutionParameteriv(ctx->Exec, ( target, pname, params )); + } +} + + +static void GLAPIENTRY +save_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_PARAMETER_F, 3 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].f = param; + } + if (ctx->ExecuteFlag) { + CALL_ConvolutionParameterf(ctx->Exec, ( target, pname, param )); + } +} + + +static void GLAPIENTRY +save_ConvolutionParameterfv(GLenum target, GLenum pname, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_PARAMETER_FV, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].f = params[0]; + if (pname == GL_CONVOLUTION_BORDER_COLOR || + pname == GL_CONVOLUTION_FILTER_SCALE || + pname == GL_CONVOLUTION_FILTER_BIAS) { + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + else { + n[4].f = n[5].f = n[6].f = 0.0F; + } + } + if (ctx->ExecuteFlag) { + CALL_ConvolutionParameterfv(ctx->Exec, ( target, pname, params )); + } +} + + +static void GLAPIENTRY +save_CopyPixels( GLint x, GLint y, + GLsizei width, GLsizei height, GLenum type ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_PIXELS, 5 ); + if (n) { + n[1].i = x; + n[2].i = y; + n[3].i = (GLint) width; + n[4].i = (GLint) height; + n[5].e = type; + } + if (ctx->ExecuteFlag) { + CALL_CopyPixels(ctx->Exec, ( x, y, width, height, type )); + } +} + + + +static void GLAPIENTRY +save_CopyTexImage1D( GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLint border ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_TEX_IMAGE1D, 7 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalformat; + n[4].i = x; + n[5].i = y; + n[6].i = width; + n[7].i = border; + } + if (ctx->ExecuteFlag) { + CALL_CopyTexImage1D(ctx->Exec, ( target, level, internalformat, + x, y, width, border )); + } +} + + +static void GLAPIENTRY +save_CopyTexImage2D( GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, GLsizei width, + GLsizei height, GLint border ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_TEX_IMAGE2D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalformat; + n[4].i = x; + n[5].i = y; + n[6].i = width; + n[7].i = height; + n[8].i = border; + } + if (ctx->ExecuteFlag) { + CALL_CopyTexImage2D(ctx->Exec, ( target, level, internalformat, + x, y, width, height, border )); + } +} + + + +static void GLAPIENTRY +save_CopyTexSubImage1D( GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, + GLsizei width ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_TEX_SUB_IMAGE1D, 6 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = x; + n[5].i = y; + n[6].i = width; + } + if (ctx->ExecuteFlag) { + CALL_CopyTexSubImage1D(ctx->Exec, ( target, level, xoffset, x, y, width )); + } +} + + +static void GLAPIENTRY +save_CopyTexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLint height ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_TEX_SUB_IMAGE2D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = x; + n[6].i = y; + n[7].i = width; + n[8].i = height; + } + if (ctx->ExecuteFlag) { + CALL_CopyTexSubImage2D(ctx->Exec, ( target, level, xoffset, yoffset, + x, y, width, height )); + } +} + + +static void GLAPIENTRY +save_CopyTexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, + GLsizei width, GLint height ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COPY_TEX_SUB_IMAGE3D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = zoffset; + n[6].i = x; + n[7].i = y; + n[8].i = width; + n[9].i = height; + } + if (ctx->ExecuteFlag) { + CALL_CopyTexSubImage3D(ctx->Exec, ( target, level, + xoffset, yoffset, zoffset, + x, y, width, height )); + } +} + + +static void GLAPIENTRY save_CullFace( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_CULL_FACE, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_CullFace(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY save_DepthFunc( GLenum func ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DEPTH_FUNC, 1 ); + if (n) { + n[1].e = func; + } + if (ctx->ExecuteFlag) { + CALL_DepthFunc(ctx->Exec, ( func )); + } +} + + +static void GLAPIENTRY save_DepthMask( GLboolean mask ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DEPTH_MASK, 1 ); + if (n) { + n[1].b = mask; + } + if (ctx->ExecuteFlag) { + CALL_DepthMask(ctx->Exec, ( mask )); + } +} + + +static void GLAPIENTRY save_DepthRange( GLclampd nearval, GLclampd farval ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DEPTH_RANGE, 2 ); + if (n) { + n[1].f = (GLfloat) nearval; + n[2].f = (GLfloat) farval; + } + if (ctx->ExecuteFlag) { + CALL_DepthRange(ctx->Exec, ( nearval, farval )); + } +} + + +static void GLAPIENTRY save_Disable( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DISABLE, 1 ); + if (n) { + n[1].e = cap; + } + if (ctx->ExecuteFlag) { + CALL_Disable(ctx->Exec, ( cap )); + } +} + + +static void GLAPIENTRY save_DrawBuffer( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DRAW_BUFFER, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_DrawBuffer(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY save_DrawPixels( GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + GLvoid *image = unpack_image(2, width, height, 1, format, type, + pixels, &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DRAW_PIXELS, 5 ); + if (n) { + n[1].i = width; + n[2].i = height; + n[3].e = format; + n[4].e = type; + n[5].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_DrawPixels(ctx->Exec, ( width, height, format, type, pixels )); + } +} + + + +static void GLAPIENTRY save_Enable( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ENABLE, 1 ); + if (n) { + n[1].e = cap; + } + if (ctx->ExecuteFlag) { + CALL_Enable(ctx->Exec, ( cap )); + } +} + + + +void GLAPIENTRY _mesa_save_EvalMesh1( GLenum mode, GLint i1, GLint i2 ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EVALMESH1, 3 ); + if (n) { + n[1].e = mode; + n[2].i = i1; + n[3].i = i2; + } + if (ctx->ExecuteFlag) { + CALL_EvalMesh1(ctx->Exec, ( mode, i1, i2 )); + } +} + + +void GLAPIENTRY _mesa_save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EVALMESH2, 5 ); + if (n) { + n[1].e = mode; + n[2].i = i1; + n[3].i = i2; + n[4].i = j1; + n[5].i = j2; + } + if (ctx->ExecuteFlag) { + CALL_EvalMesh2(ctx->Exec, ( mode, i1, i2, j1, j2 )); + } +} + + + + +static void GLAPIENTRY save_Fogfv( GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_FOG, 5 ); + if (n) { + n[1].e = pname; + n[2].f = params[0]; + n[3].f = params[1]; + n[4].f = params[2]; + n[5].f = params[3]; + } + if (ctx->ExecuteFlag) { + CALL_Fogfv(ctx->Exec, ( pname, params )); + } +} + + +static void GLAPIENTRY save_Fogf( GLenum pname, GLfloat param ) +{ + save_Fogfv(pname, ¶m); +} + + +static void GLAPIENTRY save_Fogiv(GLenum pname, const GLint *params ) +{ + GLfloat p[4]; + switch (pname) { + case GL_FOG_MODE: + case GL_FOG_DENSITY: + case GL_FOG_START: + case GL_FOG_END: + case GL_FOG_INDEX: + p[0] = (GLfloat) *params; + break; + case GL_FOG_COLOR: + p[0] = INT_TO_FLOAT( params[0] ); + p[1] = INT_TO_FLOAT( params[1] ); + p[2] = INT_TO_FLOAT( params[2] ); + p[3] = INT_TO_FLOAT( params[3] ); + break; + default: + /* Error will be caught later in gl_Fogfv */ + ; + } + save_Fogfv(pname, p); +} + + +static void GLAPIENTRY save_Fogi(GLenum pname, GLint param ) +{ + save_Fogiv(pname, ¶m); +} + + +static void GLAPIENTRY save_FrontFace( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_FRONT_FACE, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_FrontFace(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY save_Frustum( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_FRUSTUM, 6 ); + if (n) { + n[1].f = (GLfloat) left; + n[2].f = (GLfloat) right; + n[3].f = (GLfloat) bottom; + n[4].f = (GLfloat) top; + n[5].f = (GLfloat) nearval; + n[6].f = (GLfloat) farval; + } + if (ctx->ExecuteFlag) { + CALL_Frustum(ctx->Exec, ( left, right, bottom, top, nearval, farval )); + } +} + + +static void GLAPIENTRY save_Hint( GLenum target, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_HINT, 2 ); + if (n) { + n[1].e = target; + n[2].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_Hint(ctx->Exec, ( target, mode )); + } +} + + +static void GLAPIENTRY +save_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean sink) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_HISTOGRAM, 4 ); + if (n) { + n[1].e = target; + n[2].i = width; + n[3].e = internalFormat; + n[4].b = sink; + } + if (ctx->ExecuteFlag) { + CALL_Histogram(ctx->Exec, ( target, width, internalFormat, sink )); + } +} + + +static void GLAPIENTRY save_IndexMask( GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_INDEX_MASK, 1 ); + if (n) { + n[1].ui = mask; + } + if (ctx->ExecuteFlag) { + CALL_IndexMask(ctx->Exec, ( mask )); + } +} + + +static void GLAPIENTRY save_InitNames( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_INIT_NAMES, 0 ); + if (ctx->ExecuteFlag) { + CALL_InitNames(ctx->Exec, ()); + } +} + + +static void GLAPIENTRY save_Lightfv( GLenum light, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LIGHT, 6 ); + if (OPCODE_LIGHT) { + GLint i, nParams; + n[1].e = light; + n[2].e = pname; + switch (pname) { + case GL_AMBIENT: + nParams = 4; + break; + case GL_DIFFUSE: + nParams = 4; + break; + case GL_SPECULAR: + nParams = 4; + break; + case GL_POSITION: + nParams = 4; + break; + case GL_SPOT_DIRECTION: + nParams = 3; + break; + case GL_SPOT_EXPONENT: + nParams = 1; + break; + case GL_SPOT_CUTOFF: + nParams = 1; + break; + case GL_CONSTANT_ATTENUATION: + nParams = 1; + break; + case GL_LINEAR_ATTENUATION: + nParams = 1; + break; + case GL_QUADRATIC_ATTENUATION: + nParams = 1; + break; + default: + nParams = 0; + } + for (i = 0; i < nParams; i++) { + n[3+i].f = params[i]; + } + } + if (ctx->ExecuteFlag) { + CALL_Lightfv(ctx->Exec, ( light, pname, params )); + } +} + + +static void GLAPIENTRY save_Lightf( GLenum light, GLenum pname, GLfloat params ) +{ + save_Lightfv(light, pname, ¶ms); +} + + +static void GLAPIENTRY save_Lightiv( GLenum light, GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + switch (pname) { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + fparam[0] = INT_TO_FLOAT( params[0] ); + fparam[1] = INT_TO_FLOAT( params[1] ); + fparam[2] = INT_TO_FLOAT( params[2] ); + fparam[3] = INT_TO_FLOAT( params[3] ); + break; + case GL_POSITION: + fparam[0] = (GLfloat) params[0]; + fparam[1] = (GLfloat) params[1]; + fparam[2] = (GLfloat) params[2]; + fparam[3] = (GLfloat) params[3]; + break; + case GL_SPOT_DIRECTION: + fparam[0] = (GLfloat) params[0]; + fparam[1] = (GLfloat) params[1]; + fparam[2] = (GLfloat) params[2]; + break; + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + fparam[0] = (GLfloat) params[0]; + break; + default: + /* error will be caught later in gl_Lightfv */ + ; + } + save_Lightfv( light, pname, fparam ); +} + + +static void GLAPIENTRY save_Lighti( GLenum light, GLenum pname, GLint param ) +{ + save_Lightiv( light, pname, ¶m ); +} + + +static void GLAPIENTRY save_LightModelfv( GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LIGHT_MODEL, 5 ); + if (n) { + n[1].e = pname; + n[2].f = params[0]; + n[3].f = params[1]; + n[4].f = params[2]; + n[5].f = params[3]; + } + if (ctx->ExecuteFlag) { + CALL_LightModelfv(ctx->Exec, ( pname, params )); + } +} + + +static void GLAPIENTRY save_LightModelf( GLenum pname, GLfloat param ) +{ + save_LightModelfv(pname, ¶m); +} + + +static void GLAPIENTRY save_LightModeliv( GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + fparam[0] = INT_TO_FLOAT( params[0] ); + fparam[1] = INT_TO_FLOAT( params[1] ); + fparam[2] = INT_TO_FLOAT( params[2] ); + fparam[3] = INT_TO_FLOAT( params[3] ); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + case GL_LIGHT_MODEL_TWO_SIDE: + case GL_LIGHT_MODEL_COLOR_CONTROL: + fparam[0] = (GLfloat) params[0]; + break; + default: + /* Error will be caught later in gl_LightModelfv */ + ; + } + save_LightModelfv(pname, fparam); +} + + +static void GLAPIENTRY save_LightModeli( GLenum pname, GLint param ) +{ + save_LightModeliv(pname, ¶m); +} + + +static void GLAPIENTRY save_LineStipple( GLint factor, GLushort pattern ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LINE_STIPPLE, 2 ); + if (n) { + n[1].i = factor; + n[2].us = pattern; + } + if (ctx->ExecuteFlag) { + CALL_LineStipple(ctx->Exec, ( factor, pattern )); + } +} + + +static void GLAPIENTRY save_LineWidth( GLfloat width ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LINE_WIDTH, 1 ); + if (n) { + n[1].f = width; + } + if (ctx->ExecuteFlag) { + CALL_LineWidth(ctx->Exec, ( width )); + } +} + + +static void GLAPIENTRY save_ListBase( GLuint base ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LIST_BASE, 1 ); + if (n) { + n[1].ui = base; + } + if (ctx->ExecuteFlag) { + CALL_ListBase(ctx->Exec, ( base )); + } +} + + +static void GLAPIENTRY save_LoadIdentity( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_LOAD_IDENTITY, 0 ); + if (ctx->ExecuteFlag) { + CALL_LoadIdentity(ctx->Exec, ()); + } +} + + +static void GLAPIENTRY save_LoadMatrixf( const GLfloat *m ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LOAD_MATRIX, 16 ); + if (n) { + GLuint i; + for (i=0;i<16;i++) { + n[1+i].f = m[i]; + } + } + if (ctx->ExecuteFlag) { + CALL_LoadMatrixf(ctx->Exec, ( m )); + } +} + + +static void GLAPIENTRY save_LoadMatrixd( const GLdouble *m ) +{ + GLfloat f[16]; + GLint i; + for (i = 0; i < 16; i++) { + f[i] = (GLfloat) m[i]; + } + save_LoadMatrixf(f); +} + + +static void GLAPIENTRY save_LoadName( GLuint name ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LOAD_NAME, 1 ); + if (n) { + n[1].ui = name; + } + if (ctx->ExecuteFlag) { + CALL_LoadName(ctx->Exec, ( name )); + } +} + + +static void GLAPIENTRY save_LogicOp( GLenum opcode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LOGIC_OP, 1 ); + if (n) { + n[1].e = opcode; + } + if (ctx->ExecuteFlag) { + CALL_LogicOp(ctx->Exec, ( opcode )); + } +} + + +static void GLAPIENTRY save_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride, + GLint order, const GLdouble *points) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MAP1, 6 ); + if (n) { + GLfloat *pnts = _mesa_copy_map_points1d( target, stride, order, points ); + n[1].e = target; + n[2].f = (GLfloat) u1; + n[3].f = (GLfloat) u2; + n[4].i = _mesa_evaluator_components(target); /* stride */ + n[5].i = order; + n[6].data = (void *) pnts; + } + if (ctx->ExecuteFlag) { + CALL_Map1d(ctx->Exec, ( target, u1, u2, stride, order, points )); + } +} + +static void GLAPIENTRY save_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride, + GLint order, const GLfloat *points) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MAP1, 6 ); + if (n) { + GLfloat *pnts = _mesa_copy_map_points1f( target, stride, order, points ); + n[1].e = target; + n[2].f = u1; + n[3].f = u2; + n[4].i = _mesa_evaluator_components(target); /* stride */ + n[5].i = order; + n[6].data = (void *) pnts; + } + if (ctx->ExecuteFlag) { + CALL_Map1f(ctx->Exec, ( target, u1, u2, stride, order, points )); + } +} + + +static void GLAPIENTRY save_Map2d( GLenum target, + GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, + GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, + const GLdouble *points ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MAP2, 10 ); + if (n) { + GLfloat *pnts = _mesa_copy_map_points2d( target, ustride, uorder, + vstride, vorder, points ); + n[1].e = target; + n[2].f = (GLfloat) u1; + n[3].f = (GLfloat) u2; + n[4].f = (GLfloat) v1; + n[5].f = (GLfloat) v2; + /* XXX verify these strides are correct */ + n[6].i = _mesa_evaluator_components(target) * vorder; /*ustride*/ + n[7].i = _mesa_evaluator_components(target); /*vstride*/ + n[8].i = uorder; + n[9].i = vorder; + n[10].data = (void *) pnts; + } + if (ctx->ExecuteFlag) { + CALL_Map2d(ctx->Exec, ( target, + u1, u2, ustride, uorder, + v1, v2, vstride, vorder, points )); + } +} + + +static void GLAPIENTRY save_Map2f( GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MAP2, 10 ); + if (n) { + GLfloat *pnts = _mesa_copy_map_points2f( target, ustride, uorder, + vstride, vorder, points ); + n[1].e = target; + n[2].f = u1; + n[3].f = u2; + n[4].f = v1; + n[5].f = v2; + /* XXX verify these strides are correct */ + n[6].i = _mesa_evaluator_components(target) * vorder; /*ustride*/ + n[7].i = _mesa_evaluator_components(target); /*vstride*/ + n[8].i = uorder; + n[9].i = vorder; + n[10].data = (void *) pnts; + } + if (ctx->ExecuteFlag) { + CALL_Map2f(ctx->Exec, ( target, u1, u2, ustride, uorder, + v1, v2, vstride, vorder, points )); + } +} + + +static void GLAPIENTRY save_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MAPGRID1, 3 ); + if (n) { + n[1].i = un; + n[2].f = u1; + n[3].f = u2; + } + if (ctx->ExecuteFlag) { + CALL_MapGrid1f(ctx->Exec, ( un, u1, u2 )); + } +} + + +static void GLAPIENTRY save_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 ) +{ + save_MapGrid1f(un, (GLfloat) u1, (GLfloat) u2); +} + + +static void GLAPIENTRY save_MapGrid2f( GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MAPGRID2, 6 ); + if (n) { + n[1].i = un; + n[2].f = u1; + n[3].f = u2; + n[4].i = vn; + n[5].f = v1; + n[6].f = v2; + } + if (ctx->ExecuteFlag) { + CALL_MapGrid2f(ctx->Exec, ( un, u1, u2, vn, v1, v2 )); + } +} + + + +static void GLAPIENTRY save_MapGrid2d( GLint un, GLdouble u1, GLdouble u2, + GLint vn, GLdouble v1, GLdouble v2 ) +{ + save_MapGrid2f(un, (GLfloat) u1, (GLfloat) u2, + vn, (GLfloat) v1, (GLfloat) v2); +} + + +static void GLAPIENTRY save_MatrixMode( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MATRIX_MODE, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_MatrixMode(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY +save_Minmax(GLenum target, GLenum internalFormat, GLboolean sink) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MIN_MAX, 3 ); + if (n) { + n[1].e = target; + n[2].e = internalFormat; + n[3].b = sink; + } + if (ctx->ExecuteFlag) { + CALL_Minmax(ctx->Exec, ( target, internalFormat, sink )); + } +} + + +static void GLAPIENTRY save_MultMatrixf( const GLfloat *m ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_MULT_MATRIX, 16 ); + if (n) { + GLuint i; + for (i=0;i<16;i++) { + n[1+i].f = m[i]; + } + } + if (ctx->ExecuteFlag) { + CALL_MultMatrixf(ctx->Exec, ( m )); + } +} + + +static void GLAPIENTRY save_MultMatrixd( const GLdouble *m ) +{ + GLfloat f[16]; + GLint i; + for (i = 0; i < 16; i++) { + f[i] = (GLfloat) m[i]; + } + save_MultMatrixf(f); +} + + +static void GLAPIENTRY save_NewList( GLuint list, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + /* It's an error to call this function while building a display list */ + _mesa_error( ctx, GL_INVALID_OPERATION, "glNewList" ); + (void) list; + (void) mode; +} + + + +static void GLAPIENTRY save_Ortho( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ORTHO, 6 ); + if (n) { + n[1].f = (GLfloat) left; + n[2].f = (GLfloat) right; + n[3].f = (GLfloat) bottom; + n[4].f = (GLfloat) top; + n[5].f = (GLfloat) nearval; + n[6].f = (GLfloat) farval; + } + if (ctx->ExecuteFlag) { + CALL_Ortho(ctx->Exec, ( left, right, bottom, top, nearval, farval )); + } +} + + +static void GLAPIENTRY +save_PixelMapfv( GLenum map, GLint mapsize, const GLfloat *values ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PIXEL_MAP, 3 ); + if (n) { + n[1].e = map; + n[2].i = mapsize; + n[3].data = (void *) MALLOC( mapsize * sizeof(GLfloat) ); + MEMCPY( n[3].data, (void *) values, mapsize * sizeof(GLfloat) ); + } + if (ctx->ExecuteFlag) { + CALL_PixelMapfv(ctx->Exec, ( map, mapsize, values )); + } +} + + +static void GLAPIENTRY +save_PixelMapuiv(GLenum map, GLint mapsize, const GLuint *values ) +{ + GLfloat fvalues[MAX_PIXEL_MAP_TABLE]; + GLint i; + if (map==GL_PIXEL_MAP_I_TO_I || map==GL_PIXEL_MAP_S_TO_S) { + for (i=0;i<mapsize;i++) { + fvalues[i] = (GLfloat) values[i]; + } + } + else { + for (i=0;i<mapsize;i++) { + fvalues[i] = UINT_TO_FLOAT( values[i] ); + } + } + save_PixelMapfv(map, mapsize, fvalues); +} + + +static void GLAPIENTRY +save_PixelMapusv(GLenum map, GLint mapsize, const GLushort *values) +{ + GLfloat fvalues[MAX_PIXEL_MAP_TABLE]; + GLint i; + if (map==GL_PIXEL_MAP_I_TO_I || map==GL_PIXEL_MAP_S_TO_S) { + for (i=0;i<mapsize;i++) { + fvalues[i] = (GLfloat) values[i]; + } + } + else { + for (i=0;i<mapsize;i++) { + fvalues[i] = USHORT_TO_FLOAT( values[i] ); + } + } + save_PixelMapfv(map, mapsize, fvalues); +} + + +static void GLAPIENTRY +save_PixelTransferf( GLenum pname, GLfloat param ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PIXEL_TRANSFER, 2 ); + if (n) { + n[1].e = pname; + n[2].f = param; + } + if (ctx->ExecuteFlag) { + CALL_PixelTransferf(ctx->Exec, ( pname, param )); + } +} + + +static void GLAPIENTRY +save_PixelTransferi( GLenum pname, GLint param ) +{ + save_PixelTransferf( pname, (GLfloat) param ); +} + + +static void GLAPIENTRY +save_PixelZoom( GLfloat xfactor, GLfloat yfactor ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PIXEL_ZOOM, 2 ); + if (n) { + n[1].f = xfactor; + n[2].f = yfactor; + } + if (ctx->ExecuteFlag) { + CALL_PixelZoom(ctx->Exec, ( xfactor, yfactor )); + } +} + + +static void GLAPIENTRY +save_PointParameterfvEXT( GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_POINT_PARAMETERS, 4 ); + if (n) { + n[1].e = pname; + n[2].f = params[0]; + n[3].f = params[1]; + n[4].f = params[2]; + } + if (ctx->ExecuteFlag) { + CALL_PointParameterfvEXT(ctx->Exec, ( pname, params )); + } +} + + +static void GLAPIENTRY save_PointParameterfEXT( GLenum pname, GLfloat param ) +{ + save_PointParameterfvEXT(pname, ¶m); +} + +static void GLAPIENTRY save_PointParameteriNV( GLenum pname, GLint param ) +{ + GLfloat p = (GLfloat) param; + save_PointParameterfvEXT(pname, &p); +} + +static void GLAPIENTRY save_PointParameterivNV( GLenum pname, const GLint *param ) +{ + GLfloat p = (GLfloat) param[0]; + save_PointParameterfvEXT(pname, &p); +} + + +static void GLAPIENTRY save_PointSize( GLfloat size ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_POINT_SIZE, 1 ); + if (n) { + n[1].f = size; + } + if (ctx->ExecuteFlag) { + CALL_PointSize(ctx->Exec, ( size )); + } +} + + +static void GLAPIENTRY save_PolygonMode( GLenum face, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_POLYGON_MODE, 2 ); + if (n) { + n[1].e = face; + n[2].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_PolygonMode(ctx->Exec, ( face, mode )); + } +} + + +/* + * Polygon stipple must have been upacked already! + */ +static void GLAPIENTRY save_PolygonStipple( const GLubyte *pattern ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_POLYGON_STIPPLE, 1 ); + if (n) { + void *data; + n[1].data = MALLOC( 32 * 4 ); + data = n[1].data; /* This needed for Acorn compiler */ + MEMCPY( data, pattern, 32 * 4 ); + } + if (ctx->ExecuteFlag) { + CALL_PolygonStipple(ctx->Exec, ( (GLubyte*) pattern )); + } +} + + +static void GLAPIENTRY save_PolygonOffset( GLfloat factor, GLfloat units ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_POLYGON_OFFSET, 2 ); + if (n) { + n[1].f = factor; + n[2].f = units; + } + if (ctx->ExecuteFlag) { + CALL_PolygonOffset(ctx->Exec, ( factor, units )); + } +} + + +static void GLAPIENTRY save_PolygonOffsetEXT( GLfloat factor, GLfloat bias ) +{ + GET_CURRENT_CONTEXT(ctx); + /* XXX mult by DepthMaxF here??? */ + save_PolygonOffset(factor, ctx->DrawBuffer->_DepthMaxF * bias); +} + + +static void GLAPIENTRY save_PopAttrib( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_POP_ATTRIB, 0 ); + if (ctx->ExecuteFlag) { + CALL_PopAttrib(ctx->Exec, ()); + } +} + + +static void GLAPIENTRY save_PopMatrix( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_POP_MATRIX, 0 ); + if (ctx->ExecuteFlag) { + CALL_PopMatrix(ctx->Exec, ()); + } +} + + +static void GLAPIENTRY save_PopName( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_POP_NAME, 0 ); + if (ctx->ExecuteFlag) { + CALL_PopName(ctx->Exec, ()); + } +} + + +static void GLAPIENTRY save_PrioritizeTextures( GLsizei num, const GLuint *textures, + const GLclampf *priorities ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + for (i=0;i<num;i++) { + Node *n; + n = ALLOC_INSTRUCTION( ctx, OPCODE_PRIORITIZE_TEXTURE, 2 ); + if (n) { + n[1].ui = textures[i]; + n[2].f = priorities[i]; + } + } + if (ctx->ExecuteFlag) { + CALL_PrioritizeTextures(ctx->Exec, ( num, textures, priorities )); + } +} + + +static void GLAPIENTRY save_PushAttrib( GLbitfield mask ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PUSH_ATTRIB, 1 ); + if (n) { + n[1].bf = mask; + } + if (ctx->ExecuteFlag) { + CALL_PushAttrib(ctx->Exec, ( mask )); + } +} + + +static void GLAPIENTRY save_PushMatrix( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_PUSH_MATRIX, 0 ); + if (ctx->ExecuteFlag) { + CALL_PushMatrix(ctx->Exec, ()); + } +} + + +static void GLAPIENTRY save_PushName( GLuint name ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PUSH_NAME, 1 ); + if (n) { + n[1].ui = name; + } + if (ctx->ExecuteFlag) { + CALL_PushName(ctx->Exec, ( name )); + } +} + + +static void GLAPIENTRY save_RasterPos4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_RASTER_POS, 4 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + n[4].f = w; + } + if (ctx->ExecuteFlag) { + CALL_RasterPos4f(ctx->Exec, ( x, y, z, w )); + } +} + +static void GLAPIENTRY save_RasterPos2d(GLdouble x, GLdouble y) +{ + save_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos2f(GLfloat x, GLfloat y) +{ + save_RasterPos4f(x, y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos2i(GLint x, GLint y) +{ + save_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos2s(GLshort x, GLshort y) +{ + save_RasterPos4f(x, y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos3d(GLdouble x, GLdouble y, GLdouble z) +{ + save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +static void GLAPIENTRY save_RasterPos3f(GLfloat x, GLfloat y, GLfloat z) +{ + save_RasterPos4f(x, y, z, 1.0F); +} + +static void GLAPIENTRY save_RasterPos3i(GLint x, GLint y, GLint z) +{ + save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +static void GLAPIENTRY save_RasterPos3s(GLshort x, GLshort y, GLshort z) +{ + save_RasterPos4f(x, y, z, 1.0F); +} + +static void GLAPIENTRY save_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY save_RasterPos4i(GLint x, GLint y, GLint z, GLint w) +{ + save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY save_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + save_RasterPos4f(x, y, z, w); +} + +static void GLAPIENTRY save_RasterPos2dv(const GLdouble *v) +{ + save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos2fv(const GLfloat *v) +{ + save_RasterPos4f(v[0], v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos2iv(const GLint *v) +{ + save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos2sv(const GLshort *v) +{ + save_RasterPos4f(v[0], v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_RasterPos3dv(const GLdouble *v) +{ + save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +static void GLAPIENTRY save_RasterPos3fv(const GLfloat *v) +{ + save_RasterPos4f(v[0], v[1], v[2], 1.0F); +} + +static void GLAPIENTRY save_RasterPos3iv(const GLint *v) +{ + save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +static void GLAPIENTRY save_RasterPos3sv(const GLshort *v) +{ + save_RasterPos4f(v[0], v[1], v[2], 1.0F); +} + +static void GLAPIENTRY save_RasterPos4dv(const GLdouble *v) +{ + save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY save_RasterPos4fv(const GLfloat *v) +{ + save_RasterPos4f(v[0], v[1], v[2], v[3]); +} + +static void GLAPIENTRY save_RasterPos4iv(const GLint *v) +{ + save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY save_RasterPos4sv(const GLshort *v) +{ + save_RasterPos4f(v[0], v[1], v[2], v[3]); +} + + +static void GLAPIENTRY save_PassThrough( GLfloat token ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PASSTHROUGH, 1 ); + if (n) { + n[1].f = token; + } + if (ctx->ExecuteFlag) { + CALL_PassThrough(ctx->Exec, ( token )); + } +} + + +static void GLAPIENTRY save_ReadBuffer( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_READ_BUFFER, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_ReadBuffer(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY +save_ResetHistogram(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_RESET_HISTOGRAM, 1 ); + if (n) { + n[1].e = target; + } + if (ctx->ExecuteFlag) { + CALL_ResetHistogram(ctx->Exec, ( target )); + } +} + + +static void GLAPIENTRY +save_ResetMinmax(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_RESET_MIN_MAX, 1 ); + if (n) { + n[1].e = target; + } + if (ctx->ExecuteFlag) { + CALL_ResetMinmax(ctx->Exec, ( target )); + } +} + + +static void GLAPIENTRY save_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ROTATE, 4 ); + if (n) { + n[1].f = angle; + n[2].f = x; + n[3].f = y; + n[4].f = z; + } + if (ctx->ExecuteFlag) { + CALL_Rotatef(ctx->Exec, ( angle, x, y, z )); + } +} + + +static void GLAPIENTRY save_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ) +{ + save_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z); +} + + +static void GLAPIENTRY save_Scalef( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_SCALE, 3 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + } + if (ctx->ExecuteFlag) { + CALL_Scalef(ctx->Exec, ( x, y, z )); + } +} + + +static void GLAPIENTRY save_Scaled( GLdouble x, GLdouble y, GLdouble z ) +{ + save_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z); +} + + +static void GLAPIENTRY save_Scissor( GLint x, GLint y, GLsizei width, GLsizei height ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_SCISSOR, 4 ); + if (n) { + n[1].i = x; + n[2].i = y; + n[3].i = width; + n[4].i = height; + } + if (ctx->ExecuteFlag) { + CALL_Scissor(ctx->Exec, ( x, y, width, height )); + } +} + + +static void GLAPIENTRY save_ShadeModel( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_SHADE_MODEL, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_ShadeModel(ctx->Exec, ( mode )); + } +} + + +static void GLAPIENTRY save_StencilFunc( GLenum func, GLint ref, GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_STENCIL_FUNC, 3 ); + if (n) { + n[1].e = func; + n[2].i = ref; + n[3].ui = mask; + } + if (ctx->ExecuteFlag) { + CALL_StencilFunc(ctx->Exec, ( func, ref, mask )); + } +} + + +static void GLAPIENTRY save_StencilMask( GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_STENCIL_MASK, 1 ); + if (n) { + n[1].ui = mask; + } + if (ctx->ExecuteFlag) { + CALL_StencilMask(ctx->Exec, ( mask )); + } +} + + +static void GLAPIENTRY save_StencilOp( GLenum fail, GLenum zfail, GLenum zpass ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_STENCIL_OP, 3 ); + if (n) { + n[1].e = fail; + n[2].e = zfail; + n[3].e = zpass; + } + if (ctx->ExecuteFlag) { + CALL_StencilOp(ctx->Exec, ( fail, zfail, zpass )); + } +} + + +static void GLAPIENTRY +save_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4); + if (n) { + n[1].e = face; + n[2].e = func; + n[3].i = ref; + n[4].ui = mask; + } + if (ctx->ExecuteFlag) { + CALL_StencilFuncSeparate(ctx->Exec, (face, func, ref, mask)); + } +} + + +static void GLAPIENTRY +save_StencilMaskSeparate(GLenum face, GLuint mask) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION(ctx, OPCODE_STENCIL_MASK_SEPARATE, 2); + if (n) { + n[1].e = face; + n[2].ui = mask; + } + if (ctx->ExecuteFlag) { + CALL_StencilMaskSeparate(ctx->Exec, (face, mask)); + } +} + + +static void GLAPIENTRY +save_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_STENCIL_OP_SEPARATE, 4 ); + if (n) { + n[1].e = face; + n[2].e = fail; + n[3].e = zfail; + n[4].e = zpass; + } + if (ctx->ExecuteFlag) { + CALL_StencilOpSeparate(ctx->Exec, (face, fail, zfail, zpass)); + } +} + + +static void GLAPIENTRY save_TexEnvfv( GLenum target, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEXENV, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + if (pname == GL_TEXTURE_ENV_COLOR) { + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + else { + n[3].f = params[0]; + n[4].f = n[5].f = n[6].f = 0.0F; + } + } + if (ctx->ExecuteFlag) { + CALL_TexEnvfv(ctx->Exec, ( target, pname, params )); + } +} + + +static void GLAPIENTRY save_TexEnvf( GLenum target, GLenum pname, GLfloat param ) +{ + save_TexEnvfv( target, pname, ¶m ); +} + + +static void GLAPIENTRY save_TexEnvi( GLenum target, GLenum pname, GLint param ) +{ + GLfloat p[4]; + p[0] = (GLfloat) param; + p[1] = p[2] = p[3] = 0.0; + save_TexEnvfv( target, pname, p ); +} + + +static void GLAPIENTRY save_TexEnviv( GLenum target, GLenum pname, const GLint *param ) +{ + GLfloat p[4]; + if (pname == GL_TEXTURE_ENV_COLOR) { + p[0] = INT_TO_FLOAT( param[0] ); + p[1] = INT_TO_FLOAT( param[1] ); + p[2] = INT_TO_FLOAT( param[2] ); + p[3] = INT_TO_FLOAT( param[3] ); + } + else { + p[0] = (GLfloat) param[0]; + p[1] = p[2] = p[3] = 0.0F; + } + save_TexEnvfv( target, pname, p ); +} + + +static void GLAPIENTRY save_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEXGEN, 6 ); + if (n) { + n[1].e = coord; + n[2].e = pname; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + CALL_TexGenfv(ctx->Exec, ( coord, pname, params )); + } +} + + +static void GLAPIENTRY save_TexGeniv(GLenum coord, GLenum pname, const GLint *params ) +{ + GLfloat p[4]; + p[0] = (GLfloat) params[0]; + p[1] = (GLfloat) params[1]; + p[2] = (GLfloat) params[2]; + p[3] = (GLfloat) params[3]; + save_TexGenfv(coord, pname, p); +} + + +static void GLAPIENTRY save_TexGend(GLenum coord, GLenum pname, GLdouble param ) +{ + GLfloat p = (GLfloat) param; + save_TexGenfv( coord, pname, &p ); +} + + +static void GLAPIENTRY save_TexGendv(GLenum coord, GLenum pname, const GLdouble *params ) +{ + GLfloat p[4]; + p[0] = (GLfloat) params[0]; + p[1] = (GLfloat) params[1]; + p[2] = (GLfloat) params[2]; + p[3] = (GLfloat) params[3]; + save_TexGenfv( coord, pname, p ); +} + + +static void GLAPIENTRY save_TexGenf( GLenum coord, GLenum pname, GLfloat param ) +{ + save_TexGenfv(coord, pname, ¶m); +} + + +static void GLAPIENTRY save_TexGeni( GLenum coord, GLenum pname, GLint param ) +{ + save_TexGeniv( coord, pname, ¶m ); +} + + +static void GLAPIENTRY save_TexParameterfv( GLenum target, + GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEXPARAMETER, 6 ); + if (n) { + n[1].e = target; + n[2].e = pname; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + CALL_TexParameterfv(ctx->Exec, ( target, pname, params )); + } +} + + +static void GLAPIENTRY save_TexParameterf( GLenum target, GLenum pname, GLfloat param ) +{ + save_TexParameterfv(target, pname, ¶m); +} + + +static void GLAPIENTRY save_TexParameteri( GLenum target, GLenum pname, GLint param ) +{ + GLfloat fparam[4]; + fparam[0] = (GLfloat) param; + fparam[1] = fparam[2] = fparam[3] = 0.0; + save_TexParameterfv(target, pname, fparam); +} + + +static void GLAPIENTRY save_TexParameteriv( GLenum target, GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + fparam[0] = (GLfloat) params[0]; + fparam[1] = fparam[2] = fparam[3] = 0.0; + save_TexParameterfv(target, pname, fparam); +} + + +static void GLAPIENTRY save_TexImage1D( GLenum target, + GLint level, GLint components, + GLsizei width, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_1D) { + /* don't compile, execute immediately */ + CALL_TexImage1D(ctx->Exec, ( target, level, components, width, + border, format, type, pixels )); + } + else { + GLvoid *image = unpack_image(1, width, 1, 1, format, type, + pixels, &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_IMAGE1D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = border; + n[6].e = format; + n[7].e = type; + n[8].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_TexImage1D(ctx->Exec, ( target, level, components, width, + border, format, type, pixels )); + } + } +} + + +static void GLAPIENTRY save_TexImage2D( GLenum target, + GLint level, GLint components, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_2D) { + /* don't compile, execute immediately */ + CALL_TexImage2D(ctx->Exec, ( target, level, components, width, + height, border, format, type, pixels )); + } + else { + GLvoid *image = unpack_image(2, width, height, 1, format, type, + pixels, &ctx->Unpack); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_IMAGE2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = components; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = border; + n[7].e = format; + n[8].e = type; + n[9].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_TexImage2D(ctx->Exec, ( target, level, components, width, + height, border, format, type, pixels )); + } + } +} + + +static void GLAPIENTRY save_TexImage3D( GLenum target, + GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_3D) { + /* don't compile, execute immediately */ + CALL_TexImage3D(ctx->Exec, ( target, level, internalFormat, width, + height, depth, border, format, type, pixels )); + } + else { + Node *n; + GLvoid *image = unpack_image(3, width, height, depth, format, type, + pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_IMAGE3D, 10 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = (GLint) internalFormat; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = (GLint) depth; + n[7].i = border; + n[8].e = format; + n[9].e = type; + n[10].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_TexImage3D(ctx->Exec, ( target, level, internalFormat, width, + height, depth, border, format, type, pixels )); + } + } +} + + +static void GLAPIENTRY save_TexSubImage1D( GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLvoid *image = unpack_image(1, width, 1, 1, format, type, + pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_SUB_IMAGE1D, 7 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = (GLint) width; + n[5].e = format; + n[6].e = type; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_TexSubImage1D(ctx->Exec, ( target, level, xoffset, width, + format, type, pixels )); + } +} + + +static void GLAPIENTRY save_TexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLvoid *image = unpack_image(2, width, height, 1, format, type, + pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_SUB_IMAGE2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = (GLint) width; + n[6].i = (GLint) height; + n[7].e = format; + n[8].e = type; + n[9].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_TexSubImage2D(ctx->Exec, ( target, level, xoffset, yoffset, + width, height, format, type, pixels )); + } +} + + +static void GLAPIENTRY save_TexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset,GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLvoid *image = unpack_image(3, width, height, depth, format, type, + pixels, &ctx->Unpack); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_SUB_IMAGE3D, 11 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = zoffset; + n[6].i = (GLint) width; + n[7].i = (GLint) height; + n[8].i = (GLint) depth; + n[9].e = format; + n[10].e = type; + n[11].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_TexSubImage3D(ctx->Exec, ( target, level, + xoffset, yoffset, zoffset, + width, height, depth, format, type, pixels )); + } +} + + +static void GLAPIENTRY save_Translatef( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TRANSLATE, 3 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + } + if (ctx->ExecuteFlag) { + CALL_Translatef(ctx->Exec, ( x, y, z )); + } +} + + +static void GLAPIENTRY save_Translated( GLdouble x, GLdouble y, GLdouble z ) +{ + save_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z); +} + + + +static void GLAPIENTRY save_Viewport( GLint x, GLint y, GLsizei width, GLsizei height ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_VIEWPORT, 4 ); + if (n) { + n[1].i = x; + n[2].i = y; + n[3].i = (GLint) width; + n[4].i = (GLint) height; + } + if (ctx->ExecuteFlag) { + CALL_Viewport(ctx->Exec, ( x, y, width, height )); + } +} + + +static void GLAPIENTRY save_WindowPos4fMESA( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_WINDOW_POS, 4 ); + if (n) { + n[1].f = x; + n[2].f = y; + n[3].f = z; + n[4].f = w; + } + if (ctx->ExecuteFlag) { + CALL_WindowPos4fMESA(ctx->Exec, ( x, y, z, w )); + } +} + +static void GLAPIENTRY save_WindowPos2dMESA(GLdouble x, GLdouble y) +{ + save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos2fMESA(GLfloat x, GLfloat y) +{ + save_WindowPos4fMESA(x, y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos2iMESA(GLint x, GLint y) +{ + save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos2sMESA(GLshort x, GLshort y) +{ + save_WindowPos4fMESA(x, y, 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z) +{ + save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +static void GLAPIENTRY save_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z) +{ + save_WindowPos4fMESA(x, y, z, 1.0F); +} + +static void GLAPIENTRY save_WindowPos3iMESA(GLint x, GLint y, GLint z) +{ + save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +static void GLAPIENTRY save_WindowPos3sMESA(GLshort x, GLshort y, GLshort z) +{ + save_WindowPos4fMESA(x, y, z, 1.0F); +} + +static void GLAPIENTRY save_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY save_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w) +{ + save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +static void GLAPIENTRY save_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w) +{ + save_WindowPos4fMESA(x, y, z, w); +} + +static void GLAPIENTRY save_WindowPos2dvMESA(const GLdouble *v) +{ + save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos2fvMESA(const GLfloat *v) +{ + save_WindowPos4fMESA(v[0], v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos2ivMESA(const GLint *v) +{ + save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos2svMESA(const GLshort *v) +{ + save_WindowPos4fMESA(v[0], v[1], 0.0F, 1.0F); +} + +static void GLAPIENTRY save_WindowPos3dvMESA(const GLdouble *v) +{ + save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +static void GLAPIENTRY save_WindowPos3fvMESA(const GLfloat *v) +{ + save_WindowPos4fMESA(v[0], v[1], v[2], 1.0F); +} + +static void GLAPIENTRY save_WindowPos3ivMESA(const GLint *v) +{ + save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +static void GLAPIENTRY save_WindowPos3svMESA(const GLshort *v) +{ + save_WindowPos4fMESA(v[0], v[1], v[2], 1.0F); +} + +static void GLAPIENTRY save_WindowPos4dvMESA(const GLdouble *v) +{ + save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY save_WindowPos4fvMESA(const GLfloat *v) +{ + save_WindowPos4fMESA(v[0], v[1], v[2], v[3]); +} + +static void GLAPIENTRY save_WindowPos4ivMESA(const GLint *v) +{ + save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +static void GLAPIENTRY save_WindowPos4svMESA(const GLshort *v) +{ + save_WindowPos4fMESA(v[0], v[1], v[2], v[3]); +} + + + +/* GL_ARB_multitexture */ +static void GLAPIENTRY save_ActiveTextureARB( GLenum target ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ACTIVE_TEXTURE, 1 ); + if (n) { + n[1].e = target; + } + if (ctx->ExecuteFlag) { + CALL_ActiveTextureARB(ctx->Exec, ( target )); + } +} + + +/* GL_ARB_transpose_matrix */ + +static void GLAPIENTRY save_LoadTransposeMatrixdARB( const GLdouble m[16] ) +{ + GLfloat tm[16]; + _math_transposefd(tm, m); + save_LoadMatrixf(tm); +} + + +static void GLAPIENTRY save_LoadTransposeMatrixfARB( const GLfloat m[16] ) +{ + GLfloat tm[16]; + _math_transposef(tm, m); + save_LoadMatrixf(tm); +} + + +static void GLAPIENTRY +save_MultTransposeMatrixdARB( const GLdouble m[16] ) +{ + GLfloat tm[16]; + _math_transposefd(tm, m); + save_MultMatrixf(tm); +} + + +static void GLAPIENTRY +save_MultTransposeMatrixfARB( const GLfloat m[16] ) +{ + GLfloat tm[16]; + _math_transposef(tm, m); + save_MultMatrixf(tm); +} + + +static void GLAPIENTRY +save_PixelTexGenSGIX(GLenum mode) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PIXEL_TEXGEN_SGIX, 1 ); + if (n) { + n[1].e = mode; + } + if (ctx->ExecuteFlag) { + CALL_PixelTexGenSGIX(ctx->Exec, ( mode )); + } +} + + +/* GL_ARB_texture_compression */ +static void GLAPIENTRY +save_CompressedTexImage1DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLint border, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_1D) { + /* don't compile, execute immediately */ + CALL_CompressedTexImage1DARB(ctx->Exec, (target, level, internalFormat, + width, border, imageSize, data)); + } + else { + Node *n; + GLvoid *image; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D, 7 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalFormat; + n[4].i = (GLint) width; + n[5].i = border; + n[6].i = imageSize; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_CompressedTexImage1DARB(ctx->Exec, (target, level, internalFormat, + width, border, imageSize, data)); + } + } +} + + +static void GLAPIENTRY +save_CompressedTexImage2DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_2D) { + /* don't compile, execute immediately */ + CALL_CompressedTexImage2DARB(ctx->Exec, (target, level, internalFormat, + width, height, border, imageSize, data)); + } + else { + Node *n; + GLvoid *image; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D, 8 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalFormat; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = border; + n[7].i = imageSize; + n[8].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_CompressedTexImage2DARB(ctx->Exec, (target, level, internalFormat, + width, height, border, imageSize, data)); + } + } +} + + +static void GLAPIENTRY +save_CompressedTexImage3DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + if (target == GL_PROXY_TEXTURE_3D) { + /* don't compile, execute immediately */ + CALL_CompressedTexImage3DARB(ctx->Exec, (target, level, internalFormat, + width, height, depth, border, imageSize, data)); + } + else { + Node *n; + GLvoid *image; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].e = internalFormat; + n[4].i = (GLint) width; + n[5].i = (GLint) height; + n[6].i = (GLint) depth; + n[7].i = border; + n[8].i = imageSize; + n[9].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_CompressedTexImage3DARB(ctx->Exec, (target, level, internalFormat, + width, height, depth, border, imageSize, data)); + } + } +} + + +static void GLAPIENTRY +save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + Node *n; + GLvoid *image; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage1DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D, 7 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = (GLint) width; + n[5].e = format; + n[6].i = imageSize; + n[7].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_CompressedTexSubImage1DARB(ctx->Exec, (target, level, xoffset, + width, format, imageSize, data)); + } +} + + +static void GLAPIENTRY +save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data) +{ + Node *n; + GLvoid *image; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D, 9 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = (GLint) width; + n[6].i = (GLint) height; + n[7].e = format; + n[8].i = imageSize; + n[9].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_CompressedTexSubImage2DARB(ctx->Exec, (target, level, xoffset, yoffset, + width, height, format, imageSize, data)); + } +} + + +static void GLAPIENTRY +save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + Node *n; + GLvoid *image; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + + /* make copy of image */ + image = MALLOC(imageSize); + if (!image) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage3DARB"); + return; + } + MEMCPY(image, data, imageSize); + n = ALLOC_INSTRUCTION( ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D, 11 ); + if (n) { + n[1].e = target; + n[2].i = level; + n[3].i = xoffset; + n[4].i = yoffset; + n[5].i = zoffset; + n[6].i = (GLint) width; + n[7].i = (GLint) height; + n[8].i = (GLint) depth; + n[9].e = format; + n[10].i = imageSize; + n[11].data = image; + } + else if (image) { + FREE(image); + } + if (ctx->ExecuteFlag) { + CALL_CompressedTexSubImage3DARB(ctx->Exec, (target, level, xoffset, yoffset, + zoffset, width, height, depth, format, imageSize, data)); + } +} + + +/* GL_ARB_multisample */ +static void GLAPIENTRY +save_SampleCoverageARB(GLclampf value, GLboolean invert) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_SAMPLE_COVERAGE, 2 ); + if (n) { + n[1].f = value; + n[2].b = invert; + } + if (ctx->ExecuteFlag) { + CALL_SampleCoverageARB(ctx->Exec, ( value, invert )); + } +} + + +/* GL_SGIS_pixel_texture */ + +static void GLAPIENTRY +save_PixelTexGenParameteriSGIS(GLenum target, GLint value) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS, 2 ); + if (n) { + n[1].e = target; + n[2].i = value; + } + if (ctx->ExecuteFlag) { + CALL_PixelTexGenParameteriSGIS(ctx->Exec, ( target, value )); + } +} + + +static void GLAPIENTRY +save_PixelTexGenParameterfSGIS(GLenum target, GLfloat value) +{ + save_PixelTexGenParameteriSGIS(target, (GLint) value); +} + + +static void GLAPIENTRY +save_PixelTexGenParameterivSGIS(GLenum target, const GLint *value) +{ + save_PixelTexGenParameteriSGIS(target, *value); +} + + +static void GLAPIENTRY +save_PixelTexGenParameterfvSGIS(GLenum target, const GLfloat *value) +{ + save_PixelTexGenParameteriSGIS(target, (GLint) *value); +} + + +/* + * GL_NV_vertex_program + */ +#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program +static void GLAPIENTRY +save_BindProgramNV(GLenum target, GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BIND_PROGRAM_NV, 2 ); + if (n) { + n[1].e = target; + n[2].ui = id; + } + if (ctx->ExecuteFlag) { + CALL_BindProgramNV(ctx->Exec, ( target, id )); + } +} +#endif /* FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program */ + +#if FEATURE_NV_vertex_program +static void GLAPIENTRY +save_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EXECUTE_PROGRAM_NV, 6 ); + if (n) { + n[1].e = target; + n[2].ui = id; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + CALL_ExecuteProgramNV(ctx->Exec, (target, id, params)); + } +} + + +static void GLAPIENTRY +save_ProgramParameter4fNV(GLenum target, GLuint index, + GLfloat x, GLfloat y, + GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_PARAMETER4F_NV, 6 ); + if (n) { + n[1].e = target; + n[2].ui = index; + n[3].f = x; + n[4].f = y; + n[5].f = z; + n[6].f = w; + } + if (ctx->ExecuteFlag) { + CALL_ProgramParameter4fNV(ctx->Exec, (target, index, x, y, z, w)); + } +} + + +static void GLAPIENTRY +save_ProgramParameter4fvNV(GLenum target, GLuint index, const GLfloat *params) +{ + save_ProgramParameter4fNV(target, index, params[0], params[1], + params[2], params[3]); +} + + +static void GLAPIENTRY +save_ProgramParameter4dNV(GLenum target, GLuint index, + GLdouble x, GLdouble y, + GLdouble z, GLdouble w) +{ + save_ProgramParameter4fNV(target, index, (GLfloat) x, (GLfloat) y, + (GLfloat) z, (GLfloat) w); +} + + +static void GLAPIENTRY +save_ProgramParameter4dvNV(GLenum target, GLuint index, + const GLdouble *params) +{ + save_ProgramParameter4fNV(target, index, (GLfloat) params[0], + (GLfloat) params[1], (GLfloat) params[2], + (GLfloat) params[3]); +} + + +static void GLAPIENTRY +save_ProgramParameters4dvNV(GLenum target, GLuint index, + GLuint num, const GLdouble *params) +{ + GLuint i; + for (i = 0; i < num; i++) { + save_ProgramParameter4dvNV(target, index + i, params + 4 * i); + } +} + + +static void GLAPIENTRY +save_ProgramParameters4fvNV(GLenum target, GLuint index, + GLuint num, const GLfloat *params) +{ + GLuint i; + for (i = 0; i < num; i++) { + save_ProgramParameter4fvNV(target, index + i, params + 4 * i); + } +} + + +static void GLAPIENTRY +save_LoadProgramNV(GLenum target, GLuint id, GLsizei len, + const GLubyte *program) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLubyte *programCopy; + + programCopy = (GLubyte *) _mesa_malloc(len); + if (!programCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); + return; + } + _mesa_memcpy(programCopy, program, len); + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_LOAD_PROGRAM_NV, 4 ); + if (n) { + n[1].e = target; + n[2].ui = id; + n[3].i = len; + n[4].data = programCopy; + } + if (ctx->ExecuteFlag) { + CALL_LoadProgramNV(ctx->Exec, (target, id, len, program)); + } +} + + +static void GLAPIENTRY +save_RequestResidentProgramsNV(GLsizei num, const GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLuint *idCopy = (GLuint *) _mesa_malloc(num * sizeof(GLuint)); + if (!idCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRequestResidentProgramsNV"); + return; + } + _mesa_memcpy(idCopy, ids, num * sizeof(GLuint)); + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TRACK_MATRIX_NV, 2 ); + if (n) { + n[1].i = num; + n[2].data = idCopy; + } + if (ctx->ExecuteFlag) { + CALL_RequestResidentProgramsNV(ctx->Exec, (num, ids)); + } +} + + +static void GLAPIENTRY +save_TrackMatrixNV(GLenum target, GLuint address, + GLenum matrix, GLenum transform) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_TRACK_MATRIX_NV, 4 ); + if (n) { + n[1].e = target; + n[2].ui = address; + n[3].e = matrix; + n[4].e = transform; + } + if (ctx->ExecuteFlag) { + CALL_TrackMatrixNV(ctx->Exec, (target, address, matrix, transform)); + } +} +#endif /* FEATURE_NV_vertex_program */ + + +/* + * GL_NV_fragment_program + */ +#if FEATURE_NV_fragment_program +static void GLAPIENTRY +save_ProgramLocalParameter4fARB(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6 ); + if (n) { + n[1].e = target; + n[2].ui = index; + n[3].f = x; + n[4].f = y; + n[5].f = z; + n[6].f = w; + } + if (ctx->ExecuteFlag) { + CALL_ProgramLocalParameter4fARB(ctx->Exec, (target, index, x, y, z, w)); + } +} + + +static void GLAPIENTRY +save_ProgramLocalParameter4fvARB(GLenum target, GLuint index, + const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6 ); + if (n) { + n[1].e = target; + n[2].ui = index; + n[3].f = params[0]; + n[4].f = params[1]; + n[5].f = params[2]; + n[6].f = params[3]; + } + if (ctx->ExecuteFlag) { + CALL_ProgramLocalParameter4fvARB(ctx->Exec, (target, index, params)); + } +} + + +static void GLAPIENTRY +save_ProgramLocalParameter4dARB(GLenum target, GLuint index, + GLdouble x, GLdouble y, + GLdouble z, GLdouble w) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6 ); + if (n) { + n[1].e = target; + n[2].ui = index; + n[3].f = (GLfloat) x; + n[4].f = (GLfloat) y; + n[5].f = (GLfloat) z; + n[6].f = (GLfloat) w; + } + if (ctx->ExecuteFlag) { + CALL_ProgramLocalParameter4dARB(ctx->Exec, (target, index, x, y, z, w)); + } +} + + +static void GLAPIENTRY +save_ProgramLocalParameter4dvARB(GLenum target, GLuint index, + const GLdouble *params) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6 ); + if (n) { + n[1].e = target; + n[2].ui = index; + n[3].f = (GLfloat) params[0]; + n[4].f = (GLfloat) params[1]; + n[5].f = (GLfloat) params[2]; + n[6].f = (GLfloat) params[3]; + } + if (ctx->ExecuteFlag) { + CALL_ProgramLocalParameter4dvARB(ctx->Exec, (target, index, params)); + } +} + +static void GLAPIENTRY +save_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLubyte *nameCopy = (GLubyte *) _mesa_malloc(len); + if (!nameCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramNamedParameter4fNV"); + return; + } + _mesa_memcpy(nameCopy, name, len); + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_NAMED_PARAMETER_NV, 6 ); + if (n) { + n[1].ui = id; + n[2].i = len; + n[3].data = nameCopy; + n[4].f = x; + n[5].f = y; + n[6].f = z; + n[7].f = w; + } + if (ctx->ExecuteFlag) { + CALL_ProgramNamedParameter4fNV(ctx->Exec, (id, len, name, x, y, z, w)); + } +} + + +static void GLAPIENTRY +save_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, + const float v[]) +{ + save_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); +} + + +static void GLAPIENTRY +save_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + save_ProgramNamedParameter4fNV(id, len, name, (GLfloat) x, (GLfloat) y, + (GLfloat) z,(GLfloat) w); +} + + +static void GLAPIENTRY +save_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, + const double v[]) +{ + save_ProgramNamedParameter4fNV(id, len, name, (GLfloat) v[0], + (GLfloat) v[1], (GLfloat) v[2], + (GLfloat) v[3]); +} + +#endif /* FEATURE_NV_fragment_program */ + + + +/* GL_EXT_stencil_two_side */ +static void GLAPIENTRY save_ActiveStencilFaceEXT( GLenum face ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ACTIVE_STENCIL_FACE_EXT, 1 ); + if (n) { + n[1].e = face; + } + if (ctx->ExecuteFlag) { + CALL_ActiveStencilFaceEXT(ctx->Exec, ( face )); + } +} + + +/* GL_EXT_depth_bounds_test */ +static void GLAPIENTRY save_DepthBoundsEXT( GLclampd zmin, GLclampd zmax ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DEPTH_BOUNDS_EXT, 2 ); + if (n) { + n[1].f = (GLfloat) zmin; + n[2].f = (GLfloat) zmax; + } + if (ctx->ExecuteFlag) { + CALL_DepthBoundsEXT(ctx->Exec, ( zmin, zmax )); + } +} + + + +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + +static void GLAPIENTRY +save_ProgramStringARB(GLenum target, GLenum format, GLsizei len, + const GLvoid *string) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLubyte *programCopy; + + programCopy = (GLubyte *) _mesa_malloc(len); + if (!programCopy) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB"); + return; + } + _mesa_memcpy(programCopy, string, len); + + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_STRING_ARB, 4 ); + if (n) { + n[1].e = target; + n[2].e = format; + n[3].i = len; + n[4].data = programCopy; + } + if (ctx->ExecuteFlag) { + CALL_ProgramStringARB(ctx->Exec, (target, format, len, string)); + } +} + + +static void GLAPIENTRY +save_ProgramEnvParameter4fARB(GLenum target, GLuint index, + GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6 ); + if (n) { + n[1].e = target; + n[2].ui = index; + n[3].f = x; + n[4].f = y; + n[5].f = z; + n[6].f = w; + } + if (ctx->ExecuteFlag) { + CALL_ProgramEnvParameter4fARB(ctx->Exec, ( target, index, x, y, z, w)); + } +} + + +static void GLAPIENTRY +save_ProgramEnvParameter4fvARB(GLenum target, GLuint index, + const GLfloat *params) +{ + save_ProgramEnvParameter4fARB(target, index, params[0], params[1], + params[2], params[3]); +} + + +static void GLAPIENTRY +save_ProgramEnvParameter4dARB(GLenum target, GLuint index, + GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + save_ProgramEnvParameter4fARB(target, index, + (GLfloat) x, + (GLfloat) y, + (GLfloat) z, + (GLfloat) w); +} + + +static void GLAPIENTRY +save_ProgramEnvParameter4dvARB(GLenum target, GLuint index, + const GLdouble *params) +{ + save_ProgramEnvParameter4fARB(target, index, + (GLfloat) params[0], + (GLfloat) params[1], + (GLfloat) params[2], + (GLfloat) params[3]); +} + +#endif /* FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program */ + + +#ifdef FEATURE_ARB_occlusion_query + +static void GLAPIENTRY +save_BeginQueryARB(GLenum target, GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BEGIN_QUERY_ARB, 2 ); + if (n) { + n[1].e = target; + n[2].ui = id; + } + if (ctx->ExecuteFlag) { + CALL_BeginQueryARB(ctx->Exec, ( target, id )); + } +} + + +static void GLAPIENTRY +save_EndQueryARB(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_END_QUERY_ARB, 1 ); + if (n) { + n[1].e = target; + } + if (ctx->ExecuteFlag) { + CALL_EndQueryARB(ctx->Exec, ( target )); + } +} + +#endif /* FEATURE_ARB_occlusion_query */ + + +static void GLAPIENTRY +save_DrawBuffersARB(GLsizei count, const GLenum *buffers) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + n = ALLOC_INSTRUCTION( ctx, OPCODE_DRAW_BUFFERS_ARB, 1 + MAX_DRAW_BUFFERS ); + if (n) { + GLint i; + n[1].i = count; + if (count > MAX_DRAW_BUFFERS) + count = MAX_DRAW_BUFFERS; + for (i = 0; i < count; i++) { + n[2 + i].e = buffers[i]; + } + } + if (ctx->ExecuteFlag) { + CALL_DrawBuffersARB(ctx->Exec, (count, buffers)); + } +} + +#if FEATURE_ATI_fragment_shader +static void GLAPIENTRY +save_BindFragmentShaderATI(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + n = ALLOC_INSTRUCTION( ctx, OPCODE_BIND_FRAGMENT_SHADER_ATI, 1); + if (n) { + n[1].ui = id; + } + if (ctx->ExecuteFlag) { + CALL_BindFragmentShaderATI(ctx->Exec, (id)); + } +} + +static void GLAPIENTRY +save_SetFragmentShaderConstantATI(GLuint dst, const GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + + n = ALLOC_INSTRUCTION( ctx, OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI, 5); + if (n) { + n[1].ui = dst; + n[2].f = value[0]; + n[3].f = value[1]; + n[4].f = value[2]; + n[5].f = value[3]; + } + if (ctx->ExecuteFlag) { + CALL_SetFragmentShaderConstantATI(ctx->Exec, (dst, value)); + } +} +#endif + +static void save_Attr1fNV( GLenum attr, GLfloat x ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_1F_NV, 2 ); + if (n) { + n[1].e = attr; + n[2].f = x; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 1; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib1fNV(ctx->Exec, ( attr, x )); + } +} + +static void save_Attr2fNV( GLenum attr, GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_2F_NV, 3 ); + if (n) { + n[1].e = attr; + n[2].f = x; + n[3].f = y; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 2; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, 0, 1); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib2fNV(ctx->Exec, ( attr, x, y )); + } +} + +static void save_Attr3fNV( GLenum attr, GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_3F_NV, 4 ); + if (n) { + n[1].e = attr; + n[2].f = x; + n[3].f = y; + n[4].f = z; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 3; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, z, 1); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib3fNV(ctx->Exec, ( attr, x, y, z )); + } +} + +static void save_Attr4fNV( GLenum attr, GLfloat x, GLfloat y, GLfloat z, + GLfloat w ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_4F_NV, 5 ); + if (n) { + n[1].e = attr; + n[2].f = x; + n[3].f = y; + n[4].f = z; + n[5].f = w; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 4; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, z, w); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib4fNV(ctx->Exec, ( attr, x, y, z, w )); + } +} + + +static void save_Attr1fARB( GLenum attr, GLfloat x ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_1F_ARB, 2 ); + if (n) { + n[1].e = attr; + n[2].f = x; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 1; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib1fARB(ctx->Exec, ( attr, x )); + } +} + +static void save_Attr2fARB( GLenum attr, GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_2F_ARB, 3 ); + if (n) { + n[1].e = attr; + n[2].f = x; + n[3].f = y; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 2; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, 0, 1); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib2fARB(ctx->Exec, ( attr, x, y )); + } +} + +static void save_Attr3fARB( GLenum attr, GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_3F_ARB, 4 ); + if (n) { + n[1].e = attr; + n[2].f = x; + n[3].f = y; + n[4].f = z; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 3; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, z, 1); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib3fARB(ctx->Exec, ( attr, x, y, z )); + } +} + +static void save_Attr4fARB( GLenum attr, GLfloat x, GLfloat y, GLfloat z, + GLfloat w ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_ATTR_4F_ARB, 5 ); + if (n) { + n[1].e = attr; + n[2].f = x; + n[3].f = y; + n[4].f = z; + n[5].f = w; + } + + ASSERT(attr < VERT_ATTRIB_MAX); + ctx->ListState.ActiveAttribSize[attr] = 4; + ASSIGN_4V( ctx->ListState.CurrentAttrib[attr], x, y, z, w); + + if (ctx->ExecuteFlag) { + CALL_VertexAttrib4fARB(ctx->Exec, ( attr, x, y, z, w )); + } +} + + +static void GLAPIENTRY save_EvalCoord1f( GLfloat x ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_C1, 1 ); + if (n) { + n[1].f = x; + } + if (ctx->ExecuteFlag) { + CALL_EvalCoord1f(ctx->Exec, ( x )); + } +} + +static void GLAPIENTRY save_EvalCoord1fv( const GLfloat *v ) +{ + save_EvalCoord1f( v[0] ); +} + +static void GLAPIENTRY save_EvalCoord2f( GLfloat x, GLfloat y ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_C2, 2 ); + if (n) { + n[1].f = x; + n[2].f = y; + } + if (ctx->ExecuteFlag) { + CALL_EvalCoord2f(ctx->Exec, ( x, y )); + } +} + +static void GLAPIENTRY save_EvalCoord2fv( const GLfloat *v ) +{ + save_EvalCoord2f( v[0], v[1] ); +} + + +static void GLAPIENTRY save_EvalPoint1( GLint x ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_P1, 1 ); + if (n) { + n[1].i = x; + } + if (ctx->ExecuteFlag) { + CALL_EvalPoint1(ctx->Exec, ( x )); + } +} + +static void GLAPIENTRY save_EvalPoint2( GLint x, GLint y ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EVAL_P2, 2 ); + if (n) { + n[1].i = x; + n[2].i = y; + } + if (ctx->ExecuteFlag) { + CALL_EvalPoint2(ctx->Exec, ( x, y )); + } +} + +static void GLAPIENTRY save_Indexf( GLfloat x ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_INDEX, 1 ); + if (n) { + n[1].f = x; + } + + ctx->ListState.ActiveIndex = 1; + ctx->ListState.CurrentIndex = x; + + if (ctx->ExecuteFlag) { + CALL_Indexi(ctx->Exec, ( (GLint) x )); + } +} + +static void GLAPIENTRY save_Indexfv( const GLfloat *v ) +{ + save_Indexf( v[0] ); +} + +static void GLAPIENTRY save_EdgeFlag( GLboolean x ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_EDGEFLAG, 1 ); + if (n) { + n[1].b = x; + } + + ctx->ListState.ActiveEdgeFlag = 1; + ctx->ListState.CurrentEdgeFlag = x; + + if (ctx->ExecuteFlag) { + CALL_EdgeFlag(ctx->Exec, ( x )); + } +} + +static void GLAPIENTRY save_EdgeFlagv( const GLboolean *v ) +{ + save_EdgeFlag( v[0] ); +} + +static void GLAPIENTRY save_Materialfv( GLenum face, GLenum pname, const GLfloat *param ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + int args, i; + + SAVE_FLUSH_VERTICES( ctx ); + + switch (face) { + case GL_BACK: + case GL_FRONT: + case GL_FRONT_AND_BACK: + break; + default: + _mesa_compile_error( ctx, GL_INVALID_ENUM, "material(face)" ); + return; + } + + switch (pname) { + case GL_EMISSION: + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + case GL_AMBIENT_AND_DIFFUSE: + args = 4; + break; + case GL_SHININESS: + args = 1; + break; + case GL_COLOR_INDEXES: + args = 3; + break; + default: + _mesa_compile_error( ctx, GL_INVALID_ENUM, "material(pname)" ); + return; + } + + n = ALLOC_INSTRUCTION( ctx, OPCODE_MATERIAL, 6 ); + if (n) { + n[1].e = face; + n[2].e = pname; + for (i = 0 ; i < args ; i++) + n[3+i].f = param[i]; + } + + { + GLuint bitmask = _mesa_material_bitmask( ctx, face, pname, ~0, NULL ); + for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) + if (bitmask & (1<<i)) { + ctx->ListState.ActiveMaterialSize[i] = args; + COPY_SZ_4V( ctx->ListState.CurrentMaterial[i], args, param ); + } + } + + if (ctx->ExecuteFlag) { + CALL_Materialfv(ctx->Exec, ( face, pname, param )); + } +} + +static void GLAPIENTRY save_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + GLboolean error = GL_FALSE; + + if (/*mode < GL_POINTS ||*/ mode > GL_POLYGON) { + _mesa_compile_error( ctx, GL_INVALID_ENUM, "Begin (mode)"); + error = GL_TRUE; + } + else if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN) { + /* Typically the first begin. This may raise an error on + * playback, depending on whether CallList is issued from inside + * a begin/end or not. + */ + ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM; + } + else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END) { + ctx->Driver.CurrentSavePrimitive = mode; + } + else { + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "recursive begin" ); + error = GL_TRUE; + } + + if (!error) { + /* Give the driver an opportunity to hook in an optimized + * display list compiler. + */ + if (ctx->Driver.NotifySaveBegin( ctx, mode )) + return; + + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_BEGIN, 1 ); + if (n) { + n[1].e = mode; + } + } + + if (ctx->ExecuteFlag) { + CALL_Begin(ctx->Exec, ( mode )); + } +} + +static void GLAPIENTRY save_End( void ) +{ + GET_CURRENT_CONTEXT(ctx); + SAVE_FLUSH_VERTICES( ctx ); + (void) ALLOC_INSTRUCTION( ctx, OPCODE_END, 0 ); + ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; + if (ctx->ExecuteFlag) { + CALL_End(ctx->Exec, ( )); + } +} + +static void GLAPIENTRY save_Rectf( GLfloat a, GLfloat b, GLfloat c, GLfloat d ) +{ + GET_CURRENT_CONTEXT(ctx); + Node *n; + SAVE_FLUSH_VERTICES( ctx ); + n = ALLOC_INSTRUCTION( ctx, OPCODE_RECTF, 4 ); + if (n) { + n[1].f = a; + n[2].f = b; + n[3].f = c; + n[4].f = d; + } + if (ctx->ExecuteFlag) { + CALL_Rectf(ctx->Exec, ( a, b, c, d )); + } +} + + +static void GLAPIENTRY save_Vertex2f( GLfloat x, GLfloat y ) +{ + save_Attr2fNV( VERT_ATTRIB_POS, x, y ); +} + +static void GLAPIENTRY save_Vertex2fv( const GLfloat *v ) +{ + save_Attr2fNV( VERT_ATTRIB_POS, v[0], v[1] ); +} + +static void GLAPIENTRY save_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + save_Attr3fNV( VERT_ATTRIB_POS, x, y, z ); +} + +static void GLAPIENTRY save_Vertex3fv( const GLfloat *v ) +{ + save_Attr3fNV( VERT_ATTRIB_POS, v[0], v[1], v[2] ); +} + +static void GLAPIENTRY save_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + save_Attr4fNV( VERT_ATTRIB_POS, x, y, z, w ); +} + +static void GLAPIENTRY save_Vertex4fv( const GLfloat *v ) +{ + save_Attr4fNV( VERT_ATTRIB_POS, v[0], v[1], v[2], v[3] ); +} + +static void GLAPIENTRY save_TexCoord1f( GLfloat x ) +{ + save_Attr1fNV( VERT_ATTRIB_TEX0, x ); +} + +static void GLAPIENTRY save_TexCoord1fv( const GLfloat *v ) +{ + save_Attr1fNV( VERT_ATTRIB_TEX0, v[0] ); +} + +static void GLAPIENTRY save_TexCoord2f( GLfloat x, GLfloat y ) +{ + save_Attr2fNV( VERT_ATTRIB_TEX0, x, y ); +} + +static void GLAPIENTRY save_TexCoord2fv( const GLfloat *v ) +{ + save_Attr2fNV( VERT_ATTRIB_TEX0, v[0], v[1] ); +} + +static void GLAPIENTRY save_TexCoord3f( GLfloat x, GLfloat y, GLfloat z ) +{ + save_Attr3fNV( VERT_ATTRIB_TEX0, x, y, z ); +} + +static void GLAPIENTRY save_TexCoord3fv( const GLfloat *v ) +{ + save_Attr3fNV( VERT_ATTRIB_TEX0, v[0], v[1], v[2] ); +} + +static void GLAPIENTRY save_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + save_Attr4fNV( VERT_ATTRIB_TEX0, x, y, z, w ); +} + +static void GLAPIENTRY save_TexCoord4fv( const GLfloat *v ) +{ + save_Attr4fNV( VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3] ); +} + +static void GLAPIENTRY save_Normal3f( GLfloat x, GLfloat y, GLfloat z ) +{ + save_Attr3fNV( VERT_ATTRIB_NORMAL, x, y, z ); +} + +static void GLAPIENTRY save_Normal3fv( const GLfloat *v ) +{ + save_Attr3fNV( VERT_ATTRIB_NORMAL, v[0], v[1], v[2] ); +} + +static void GLAPIENTRY save_FogCoordfEXT( GLfloat x ) +{ + save_Attr1fNV( VERT_ATTRIB_FOG, x ); +} + +static void GLAPIENTRY save_FogCoordfvEXT( const GLfloat *v ) +{ + save_Attr1fNV( VERT_ATTRIB_FOG, v[0] ); +} + +static void GLAPIENTRY save_Color3f( GLfloat x, GLfloat y, GLfloat z ) +{ + save_Attr3fNV( VERT_ATTRIB_COLOR0, x, y, z ); +} + +static void GLAPIENTRY save_Color3fv( const GLfloat *v ) +{ + save_Attr3fNV( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] ); +} + +static void GLAPIENTRY save_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + save_Attr4fNV( VERT_ATTRIB_COLOR0, x, y, z, w ); +} + +static void GLAPIENTRY save_Color4fv( const GLfloat *v ) +{ + save_Attr4fNV( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] ); +} + +static void GLAPIENTRY save_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z ) +{ + save_Attr3fNV( VERT_ATTRIB_COLOR1, x, y, z ); +} + +static void GLAPIENTRY save_SecondaryColor3fvEXT( const GLfloat *v ) +{ + save_Attr3fNV( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] ); +} + + +/* Just call the respective ATTR for texcoord + */ +static void GLAPIENTRY save_MultiTexCoord1f( GLenum target, GLfloat x ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr1fNV( attr, x ); +} + +static void GLAPIENTRY save_MultiTexCoord1fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr1fNV( attr, v[0] ); +} + +static void GLAPIENTRY save_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr2fNV( attr, x, y ); +} + +static void GLAPIENTRY save_MultiTexCoord2fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr2fNV( attr, v[0], v[1] ); +} + +static void GLAPIENTRY save_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y, + GLfloat z) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr3fNV( attr, x, y, z ); +} + +static void GLAPIENTRY save_MultiTexCoord3fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr3fNV( attr, v[0], v[1], v[2] ); +} + +static void GLAPIENTRY save_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr4fNV( attr, x, y, z, w ); +} + +static void GLAPIENTRY save_MultiTexCoord4fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + save_Attr4fNV( attr, v[0], v[1], v[2], v[3] ); +} + + +static void enum_error( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + _mesa_error( ctx, GL_INVALID_ENUM, "VertexAttribfNV" ); +} + +/* First level for NV_vertex_program: + * + * Check for errors at compile time?. + */ +static void GLAPIENTRY save_VertexAttrib1fNV( GLuint index, GLfloat x ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr1fNV( index, x ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr1fNV( index, v[0] ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr2fNV( index, x, y ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr2fNV( index, v[0], v[1] ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr3fNV( index, x, y, z ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr3fNV( index, v[0], v[1], v[2] ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr4fNV( index, x, y, z, w ); + else + enum_error(); +} + +static void GLAPIENTRY save_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr4fNV( index, v[0], v[1], v[2], v[3] ); + else + enum_error(); +} + + + + +static void GLAPIENTRY +save_VertexAttrib1fARB( GLuint index, GLfloat x ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr1fARB( index, x ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib1fvARB( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr1fARB( index, v[0] ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib2fARB( GLuint index, GLfloat x, GLfloat y ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr2fARB( index, x, y ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib2fvARB( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr2fARB( index, v[0], v[1] ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib3fARB( GLuint index, GLfloat x, GLfloat y, GLfloat z ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr3fARB( index, x, y, z ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib3fvARB( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr3fARB( index, v[0], v[1], v[2] ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib4fARB( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr4fARB( index, x, y, z, w ); + else + enum_error(); +} + +static void GLAPIENTRY +save_VertexAttrib4fvARB( GLuint index, const GLfloat *v ) +{ + if (index < VERT_ATTRIB_MAX) + save_Attr4fARB( index, v[0], v[1], v[2], v[3] ); + else + enum_error(); +} + + + + + +/* KW: Compile commands + * + * Will appear in the list before the vertex buffer containing the + * command that provoked the error. I don't see this as a problem. + */ +void +_mesa_save_error( GLcontext *ctx, GLenum error, const char *s ) +{ + Node *n; + n = ALLOC_INSTRUCTION( ctx, OPCODE_ERROR, 2 ); + if (n) { + n[1].e = error; + n[2].data = (void *) s; + } + /* execute already done */ +} + + +/* + * Compile an error into current display list. + */ +void +_mesa_compile_error( GLcontext *ctx, GLenum error, const char *s ) +{ + if (ctx->CompileFlag) + _mesa_save_error( ctx, error, s ); + + if (ctx->ExecuteFlag) + _mesa_error( ctx, error, s ); +} + + + +static GLboolean +islist(GLcontext *ctx, GLuint list) +{ + if (list > 0 && _mesa_HashLookup(ctx->Shared->DisplayList, list)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/**********************************************************************/ +/* Display list execution */ +/**********************************************************************/ + + +/* + * Execute a display list. Note that the ListBase offset must have already + * been added before calling this function. I.e. the list argument is + * the absolute list number, not relative to ListBase. + * \param list - display list number + */ +static void GLAPIENTRY +execute_list( GLcontext *ctx, GLuint list ) +{ + struct mesa_display_list *dlist; + Node *n; + GLboolean done; + + if (list == 0 || !islist(ctx,list)) + return; + + if (ctx->ListState.CallDepth == MAX_LIST_NESTING) { + /* raise an error? */ + return; + } + + + dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + if (!dlist) + return; + + ctx->ListState.CallStack[ctx->ListState.CallDepth++] = dlist; + + if (ctx->Driver.BeginCallList) + ctx->Driver.BeginCallList( ctx, dlist ); + + n = dlist->node; + + done = GL_FALSE; + while (!done) { + OpCode opcode = n[0].opcode; + int i = (int)n[0].opcode - (int)OPCODE_EXT_0; + + if (i >= 0 && i < (GLint) ctx->ListExt.NumOpcodes) { + /* this is a driver-extended opcode */ + ctx->ListExt.Opcode[i].Execute(ctx, &n[1]); + n += ctx->ListExt.Opcode[i].Size; + } + else { + switch (opcode) { + case OPCODE_ERROR: + _mesa_error( ctx, n[1].e, (const char *) n[2].data ); + break; + case OPCODE_ACCUM: + CALL_Accum(ctx->Exec, ( n[1].e, n[2].f )); + break; + case OPCODE_ALPHA_FUNC: + CALL_AlphaFunc(ctx->Exec, ( n[1].e, n[2].f )); + break; + case OPCODE_BIND_TEXTURE: + CALL_BindTexture(ctx->Exec, ( n[1].e, n[2].ui )); + break; + case OPCODE_BITMAP: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_Bitmap(ctx->Exec, ( (GLsizei) n[1].i, (GLsizei) n[2].i, + n[3].f, n[4].f, n[5].f, n[6].f, (const GLubyte *) n[7].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_BLEND_COLOR: + CALL_BlendColor(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f )); + break; + case OPCODE_BLEND_EQUATION: + CALL_BlendEquation(ctx->Exec, ( n[1].e )); + break; + case OPCODE_BLEND_EQUATION_SEPARATE: + CALL_BlendEquationSeparateEXT(ctx->Exec, ( n[1].e, n[2].e )); + break; + case OPCODE_BLEND_FUNC_SEPARATE: + CALL_BlendFuncSeparateEXT(ctx->Exec, (n[1].e, n[2].e, n[3].e, n[4].e)); + break; + case OPCODE_CALL_LIST: + /* Generated by glCallList(), don't add ListBase */ + if (ctx->ListState.CallDepth<MAX_LIST_NESTING) { + execute_list( ctx, n[1].ui ); + } + break; + case OPCODE_CALL_LIST_OFFSET: + /* Generated by glCallLists() so we must add ListBase */ + if (n[2].b) { + /* user specified a bad data type at compile time */ + _mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)"); + } + else if (ctx->ListState.CallDepth < MAX_LIST_NESTING) { + execute_list( ctx, ctx->List.ListBase + n[1].ui ); + } + break; + case OPCODE_CLEAR: + CALL_Clear(ctx->Exec, ( n[1].bf )); + break; + case OPCODE_CLEAR_COLOR: + CALL_ClearColor(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f )); + break; + case OPCODE_CLEAR_ACCUM: + CALL_ClearAccum(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f )); + break; + case OPCODE_CLEAR_DEPTH: + CALL_ClearDepth(ctx->Exec, ( (GLclampd) n[1].f )); + break; + case OPCODE_CLEAR_INDEX: + CALL_ClearIndex(ctx->Exec, ( (GLfloat) n[1].ui )); + break; + case OPCODE_CLEAR_STENCIL: + CALL_ClearStencil(ctx->Exec, ( n[1].i )); + break; + case OPCODE_CLIP_PLANE: + { + GLdouble eq[4]; + eq[0] = n[2].f; + eq[1] = n[3].f; + eq[2] = n[4].f; + eq[3] = n[5].f; + CALL_ClipPlane(ctx->Exec, ( n[1].e, eq )); + } + break; + case OPCODE_COLOR_MASK: + CALL_ColorMask(ctx->Exec, ( n[1].b, n[2].b, n[3].b, n[4].b )); + break; + case OPCODE_COLOR_MATERIAL: + CALL_ColorMaterial(ctx->Exec, ( n[1].e, n[2].e )); + break; + case OPCODE_COLOR_TABLE: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_ColorTable(ctx->Exec, ( n[1].e, n[2].e, n[3].i, n[4].e, + n[5].e, n[6].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_COLOR_TABLE_PARAMETER_FV: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + CALL_ColorTableParameterfv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_COLOR_TABLE_PARAMETER_IV: + { + GLint params[4]; + params[0] = n[3].i; + params[1] = n[4].i; + params[2] = n[5].i; + params[3] = n[6].i; + CALL_ColorTableParameteriv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_COLOR_SUB_TABLE: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_ColorSubTable(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].e, n[5].e, n[6].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_CONVOLUTION_FILTER_1D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_ConvolutionFilter1D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].e, n[5].e, n[6].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_CONVOLUTION_FILTER_2D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_ConvolutionFilter2D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].e, n[6].e, n[7].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_CONVOLUTION_PARAMETER_I: + CALL_ConvolutionParameteri(ctx->Exec, ( n[1].e, n[2].e, n[3].i )); + break; + case OPCODE_CONVOLUTION_PARAMETER_IV: + { + GLint params[4]; + params[0] = n[3].i; + params[1] = n[4].i; + params[2] = n[5].i; + params[3] = n[6].i; + CALL_ConvolutionParameteriv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_CONVOLUTION_PARAMETER_F: + CALL_ConvolutionParameterf(ctx->Exec, ( n[1].e, n[2].e, n[3].f )); + break; + case OPCODE_CONVOLUTION_PARAMETER_FV: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + CALL_ConvolutionParameterfv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_COPY_COLOR_SUB_TABLE: + CALL_CopyColorSubTable(ctx->Exec, ( n[1].e, n[2].i, + n[3].i, n[4].i, n[5].i )); + break; + case OPCODE_COPY_COLOR_TABLE: + CALL_CopyColorSubTable(ctx->Exec, ( n[1].e, n[2].i, + n[3].i, n[4].i, n[5].i )); + break; + case OPCODE_COPY_PIXELS: + CALL_CopyPixels(ctx->Exec, ( n[1].i, n[2].i, + (GLsizei) n[3].i, (GLsizei) n[4].i, n[5].e )); + break; + case OPCODE_COPY_TEX_IMAGE1D: + CALL_CopyTexImage1D(ctx->Exec, ( n[1].e, n[2].i, n[3].e, n[4].i, + n[5].i, n[6].i, n[7].i )); + break; + case OPCODE_COPY_TEX_IMAGE2D: + CALL_CopyTexImage2D(ctx->Exec, ( n[1].e, n[2].i, n[3].e, n[4].i, + n[5].i, n[6].i, n[7].i, n[8].i )); + break; + case OPCODE_COPY_TEX_SUB_IMAGE1D: + CALL_CopyTexSubImage1D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i )); + break; + case OPCODE_COPY_TEX_SUB_IMAGE2D: + CALL_CopyTexSubImage2D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].i )); + break; + case OPCODE_COPY_TEX_SUB_IMAGE3D: + CALL_CopyTexSubImage3D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].i , n[9].i)); + break; + case OPCODE_CULL_FACE: + CALL_CullFace(ctx->Exec, ( n[1].e )); + break; + case OPCODE_DEPTH_FUNC: + CALL_DepthFunc(ctx->Exec, ( n[1].e )); + break; + case OPCODE_DEPTH_MASK: + CALL_DepthMask(ctx->Exec, ( n[1].b )); + break; + case OPCODE_DEPTH_RANGE: + CALL_DepthRange(ctx->Exec, ( (GLclampd) n[1].f, (GLclampd) n[2].f )); + break; + case OPCODE_DISABLE: + CALL_Disable(ctx->Exec, ( n[1].e )); + break; + case OPCODE_DRAW_BUFFER: + CALL_DrawBuffer(ctx->Exec, ( n[1].e )); + break; + case OPCODE_DRAW_PIXELS: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_DrawPixels(ctx->Exec, ( n[1].i, n[2].i, n[3].e, n[4].e, + n[5].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_ENABLE: + CALL_Enable(ctx->Exec, ( n[1].e )); + break; + case OPCODE_EVALMESH1: + CALL_EvalMesh1(ctx->Exec, ( n[1].e, n[2].i, n[3].i )); + break; + case OPCODE_EVALMESH2: + CALL_EvalMesh2(ctx->Exec, ( n[1].e, n[2].i, n[3].i, n[4].i, n[5].i )); + break; + case OPCODE_FOG: + { + GLfloat p[4]; + p[0] = n[2].f; + p[1] = n[3].f; + p[2] = n[4].f; + p[3] = n[5].f; + CALL_Fogfv(ctx->Exec, ( n[1].e, p )); + } + break; + case OPCODE_FRONT_FACE: + CALL_FrontFace(ctx->Exec, ( n[1].e )); + break; + case OPCODE_FRUSTUM: + CALL_Frustum(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f )); + break; + case OPCODE_HINT: + CALL_Hint(ctx->Exec, ( n[1].e, n[2].e )); + break; + case OPCODE_HISTOGRAM: + CALL_Histogram(ctx->Exec, ( n[1].e, n[2].i, n[3].e, n[4].b )); + break; + case OPCODE_INDEX_MASK: + CALL_IndexMask(ctx->Exec, ( n[1].ui )); + break; + case OPCODE_INIT_NAMES: + CALL_InitNames(ctx->Exec, ()); + break; + case OPCODE_LIGHT: + { + GLfloat p[4]; + p[0] = n[3].f; + p[1] = n[4].f; + p[2] = n[5].f; + p[3] = n[6].f; + CALL_Lightfv(ctx->Exec, ( n[1].e, n[2].e, p )); + } + break; + case OPCODE_LIGHT_MODEL: + { + GLfloat p[4]; + p[0] = n[2].f; + p[1] = n[3].f; + p[2] = n[4].f; + p[3] = n[5].f; + CALL_LightModelfv(ctx->Exec, ( n[1].e, p )); + } + break; + case OPCODE_LINE_STIPPLE: + CALL_LineStipple(ctx->Exec, ( n[1].i, n[2].us )); + break; + case OPCODE_LINE_WIDTH: + CALL_LineWidth(ctx->Exec, ( n[1].f )); + break; + case OPCODE_LIST_BASE: + CALL_ListBase(ctx->Exec, ( n[1].ui )); + break; + case OPCODE_LOAD_IDENTITY: + CALL_LoadIdentity(ctx->Exec, ()); + break; + case OPCODE_LOAD_MATRIX: + if (sizeof(Node)==sizeof(GLfloat)) { + CALL_LoadMatrixf(ctx->Exec, ( &n[1].f )); + } + else { + GLfloat m[16]; + GLuint i; + for (i=0;i<16;i++) { + m[i] = n[1+i].f; + } + CALL_LoadMatrixf(ctx->Exec, ( m )); + } + break; + case OPCODE_LOAD_NAME: + CALL_LoadName(ctx->Exec, ( n[1].ui )); + break; + case OPCODE_LOGIC_OP: + CALL_LogicOp(ctx->Exec, ( n[1].e )); + break; + case OPCODE_MAP1: + { + GLenum target = n[1].e; + GLint ustride = _mesa_evaluator_components(target); + GLint uorder = n[5].i; + GLfloat u1 = n[2].f; + GLfloat u2 = n[3].f; + CALL_Map1f(ctx->Exec, ( target, u1, u2, ustride, uorder, + (GLfloat *) n[6].data )); + } + break; + case OPCODE_MAP2: + { + GLenum target = n[1].e; + GLfloat u1 = n[2].f; + GLfloat u2 = n[3].f; + GLfloat v1 = n[4].f; + GLfloat v2 = n[5].f; + GLint ustride = n[6].i; + GLint vstride = n[7].i; + GLint uorder = n[8].i; + GLint vorder = n[9].i; + CALL_Map2f(ctx->Exec, ( target, u1, u2, ustride, uorder, + v1, v2, vstride, vorder, + (GLfloat *) n[10].data )); + } + break; + case OPCODE_MAPGRID1: + CALL_MapGrid1f(ctx->Exec, ( n[1].i, n[2].f, n[3].f )); + break; + case OPCODE_MAPGRID2: + CALL_MapGrid2f(ctx->Exec, ( n[1].i, n[2].f, n[3].f, n[4].i, n[5].f, n[6].f)); + break; + case OPCODE_MATRIX_MODE: + CALL_MatrixMode(ctx->Exec, ( n[1].e )); + break; + case OPCODE_MIN_MAX: + CALL_Minmax(ctx->Exec, (n[1].e, n[2].e, n[3].b)); + break; + case OPCODE_MULT_MATRIX: + if (sizeof(Node)==sizeof(GLfloat)) { + CALL_MultMatrixf(ctx->Exec, ( &n[1].f )); + } + else { + GLfloat m[16]; + GLuint i; + for (i=0;i<16;i++) { + m[i] = n[1+i].f; + } + CALL_MultMatrixf(ctx->Exec, ( m )); + } + break; + case OPCODE_ORTHO: + CALL_Ortho(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f )); + break; + case OPCODE_PASSTHROUGH: + CALL_PassThrough(ctx->Exec, ( n[1].f )); + break; + case OPCODE_PIXEL_MAP: + CALL_PixelMapfv(ctx->Exec, ( n[1].e, n[2].i, (GLfloat *) n[3].data )); + break; + case OPCODE_PIXEL_TRANSFER: + CALL_PixelTransferf(ctx->Exec, ( n[1].e, n[2].f )); + break; + case OPCODE_PIXEL_ZOOM: + CALL_PixelZoom(ctx->Exec, ( n[1].f, n[2].f )); + break; + case OPCODE_POINT_SIZE: + CALL_PointSize(ctx->Exec, ( n[1].f )); + break; + case OPCODE_POINT_PARAMETERS: + { + GLfloat params[3]; + params[0] = n[2].f; + params[1] = n[3].f; + params[2] = n[4].f; + CALL_PointParameterfvEXT(ctx->Exec, ( n[1].e, params )); + } + break; + case OPCODE_POLYGON_MODE: + CALL_PolygonMode(ctx->Exec, ( n[1].e, n[2].e )); + break; + case OPCODE_POLYGON_STIPPLE: + CALL_PolygonStipple(ctx->Exec, ( (GLubyte *) n[1].data )); + break; + case OPCODE_POLYGON_OFFSET: + CALL_PolygonOffset(ctx->Exec, ( n[1].f, n[2].f )); + break; + case OPCODE_POP_ATTRIB: + CALL_PopAttrib(ctx->Exec, ()); + break; + case OPCODE_POP_MATRIX: + CALL_PopMatrix(ctx->Exec, ()); + break; + case OPCODE_POP_NAME: + CALL_PopName(ctx->Exec, ()); + break; + case OPCODE_PRIORITIZE_TEXTURE: + CALL_PrioritizeTextures(ctx->Exec, ( 1, &n[1].ui, &n[2].f )); + break; + case OPCODE_PUSH_ATTRIB: + CALL_PushAttrib(ctx->Exec, ( n[1].bf )); + break; + case OPCODE_PUSH_MATRIX: + CALL_PushMatrix(ctx->Exec, ()); + break; + case OPCODE_PUSH_NAME: + CALL_PushName(ctx->Exec, ( n[1].ui )); + break; + case OPCODE_RASTER_POS: + CALL_RasterPos4f(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f )); + break; + case OPCODE_READ_BUFFER: + CALL_ReadBuffer(ctx->Exec, ( n[1].e )); + break; + case OPCODE_RESET_HISTOGRAM: + CALL_ResetHistogram(ctx->Exec, ( n[1].e )); + break; + case OPCODE_RESET_MIN_MAX: + CALL_ResetMinmax(ctx->Exec, ( n[1].e )); + break; + case OPCODE_ROTATE: + CALL_Rotatef(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f )); + break; + case OPCODE_SCALE: + CALL_Scalef(ctx->Exec, ( n[1].f, n[2].f, n[3].f )); + break; + case OPCODE_SCISSOR: + CALL_Scissor(ctx->Exec, ( n[1].i, n[2].i, n[3].i, n[4].i )); + break; + case OPCODE_SHADE_MODEL: + CALL_ShadeModel(ctx->Exec, ( n[1].e )); + break; + case OPCODE_STENCIL_FUNC: + CALL_StencilFunc(ctx->Exec, ( n[1].e, n[2].i, n[3].ui )); + break; + case OPCODE_STENCIL_MASK: + CALL_StencilMask(ctx->Exec, ( n[1].ui )); + break; + case OPCODE_STENCIL_OP: + CALL_StencilOp(ctx->Exec, ( n[1].e, n[2].e, n[3].e )); + break; + case OPCODE_STENCIL_FUNC_SEPARATE: + CALL_StencilFuncSeparate(ctx->Exec, ( n[1].e, n[2].e, n[3].i, n[4].ui )); + break; + case OPCODE_STENCIL_MASK_SEPARATE: + CALL_StencilMaskSeparate(ctx->Exec, ( n[1].e, n[2].ui )); + break; + case OPCODE_STENCIL_OP_SEPARATE: + CALL_StencilOpSeparate(ctx->Exec, ( n[1].e, n[2].e, n[3].e, n[4].e )); + break; + case OPCODE_TEXENV: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + CALL_TexEnvfv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_TEXGEN: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + CALL_TexGenfv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_TEXPARAMETER: + { + GLfloat params[4]; + params[0] = n[3].f; + params[1] = n[4].f; + params[2] = n[5].f; + params[3] = n[6].f; + CALL_TexParameterfv(ctx->Exec, ( n[1].e, n[2].e, params )); + } + break; + case OPCODE_TEX_IMAGE1D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_TexImage1D(ctx->Exec, ( + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].e, /* border */ + n[6].e, /* format */ + n[7].e, /* type */ + n[8].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_TEX_IMAGE2D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_TexImage2D(ctx->Exec, ( + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].i, /* height */ + n[6].e, /* border */ + n[7].e, /* format */ + n[8].e, /* type */ + n[9].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_TEX_IMAGE3D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_TexImage3D(ctx->Exec, ( + n[1].e, /* target */ + n[2].i, /* level */ + n[3].i, /* components */ + n[4].i, /* width */ + n[5].i, /* height */ + n[6].i, /* depth */ + n[7].e, /* border */ + n[8].e, /* format */ + n[9].e, /* type */ + n[10].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_TEX_SUB_IMAGE1D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_TexSubImage1D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].e, + n[6].e, n[7].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_TEX_SUB_IMAGE2D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_TexSubImage2D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].e, + n[6].i, n[7].e, n[8].e, n[9].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_TEX_SUB_IMAGE3D: + { + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; + CALL_TexSubImage3D(ctx->Exec, ( n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].i, + n[8].i, n[9].e, n[10].e, + n[11].data )); + ctx->Unpack = save; /* restore */ + } + break; + case OPCODE_TRANSLATE: + CALL_Translatef(ctx->Exec, ( n[1].f, n[2].f, n[3].f )); + break; + case OPCODE_VIEWPORT: + CALL_Viewport(ctx->Exec, (n[1].i, n[2].i, + (GLsizei) n[3].i, (GLsizei) n[4].i)); + break; + case OPCODE_WINDOW_POS: + CALL_WindowPos4fMESA(ctx->Exec, ( n[1].f, n[2].f, n[3].f, n[4].f )); + break; + case OPCODE_ACTIVE_TEXTURE: /* GL_ARB_multitexture */ + CALL_ActiveTextureARB(ctx->Exec, ( n[1].e )); + break; + case OPCODE_PIXEL_TEXGEN_SGIX: /* GL_SGIX_pixel_texture */ + CALL_PixelTexGenSGIX(ctx->Exec, ( n[1].e )); + break; + case OPCODE_PIXEL_TEXGEN_PARAMETER_SGIS: /* GL_SGIS_pixel_texture */ + CALL_PixelTexGenParameteriSGIS(ctx->Exec, ( n[1].e, n[2].i )); + break; + case OPCODE_COMPRESSED_TEX_IMAGE_1D: /* GL_ARB_texture_compression */ + CALL_CompressedTexImage1DARB(ctx->Exec, (n[1].e, n[2].i, n[3].e, + n[4].i, n[5].i, n[6].i, n[7].data)); + break; + case OPCODE_COMPRESSED_TEX_IMAGE_2D: /* GL_ARB_texture_compression */ + CALL_CompressedTexImage2DARB(ctx->Exec, (n[1].e, n[2].i, n[3].e, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].data)); + break; + case OPCODE_COMPRESSED_TEX_IMAGE_3D: /* GL_ARB_texture_compression */ + CALL_CompressedTexImage3DARB(ctx->Exec, (n[1].e, n[2].i, n[3].e, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, n[9].data)); + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D: /* GL_ARB_texture_compress */ + CALL_CompressedTexSubImage1DARB(ctx->Exec, (n[1].e, n[2].i, n[3].i, + n[4].i, n[5].e, n[6].i, n[7].data)); + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D: /* GL_ARB_texture_compress */ + CALL_CompressedTexSubImage2DARB(ctx->Exec, (n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].e, n[8].i, n[9].data)); + break; + case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D: /* GL_ARB_texture_compress */ + CALL_CompressedTexSubImage3DARB(ctx->Exec, (n[1].e, n[2].i, n[3].i, + n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, + n[9].e, n[10].i, n[11].data)); + break; + case OPCODE_SAMPLE_COVERAGE: /* GL_ARB_multisample */ + CALL_SampleCoverageARB(ctx->Exec, (n[1].f, n[2].b)); + break; + case OPCODE_WINDOW_POS_ARB: /* GL_ARB_window_pos */ + CALL_WindowPos3fMESA(ctx->Exec, ( n[1].f, n[2].f, n[3].f )); + break; +#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + case OPCODE_BIND_PROGRAM_NV: /* GL_NV_vertex_program */ + CALL_BindProgramNV(ctx->Exec, ( n[1].e, n[2].ui )); + break; +#endif +#if FEATURE_NV_vertex_program + case OPCODE_EXECUTE_PROGRAM_NV: + { + GLfloat v[4]; + v[0] = n[3].f; + v[1] = n[4].f; + v[2] = n[5].f; + v[3] = n[6].f; + CALL_ExecuteProgramNV(ctx->Exec, (n[1].e, n[2].ui, v)); + } + break; + case OPCODE_REQUEST_RESIDENT_PROGRAMS_NV: + CALL_RequestResidentProgramsNV(ctx->Exec, (n[1].ui, + (GLuint *) n[2].data)); + break; + case OPCODE_LOAD_PROGRAM_NV: + CALL_LoadProgramNV(ctx->Exec, (n[1].e, n[2].ui, n[3].i, + (const GLubyte *) n[4].data)); + break; + case OPCODE_PROGRAM_PARAMETER4F_NV: + CALL_ProgramParameter4fNV(ctx->Exec, (n[1].e, n[2].ui, n[3].f, + n[4].f, n[5].f, n[6].f)); + break; + case OPCODE_TRACK_MATRIX_NV: + CALL_TrackMatrixNV(ctx->Exec, (n[1].e, n[2].ui, n[3].e, n[4].e)); + break; +#endif + +#if FEATURE_NV_fragment_program + case OPCODE_PROGRAM_LOCAL_PARAMETER_ARB: + CALL_ProgramLocalParameter4fARB(ctx->Exec, (n[1].e, n[2].ui, n[3].f, + n[4].f, n[5].f, n[6].f)); + break; + case OPCODE_PROGRAM_NAMED_PARAMETER_NV: + CALL_ProgramNamedParameter4fNV(ctx->Exec, (n[1].ui, n[2].i, + (const GLubyte *) n[3].data, + n[4].f, n[5].f, n[6].f, n[7].f)); + break; +#endif + + case OPCODE_ACTIVE_STENCIL_FACE_EXT: + CALL_ActiveStencilFaceEXT(ctx->Exec, (n[1].e)); + break; + case OPCODE_DEPTH_BOUNDS_EXT: + CALL_DepthBoundsEXT(ctx->Exec, (n[1].f, n[2].f)); + break; +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + case OPCODE_PROGRAM_STRING_ARB: + CALL_ProgramStringARB(ctx->Exec, (n[1].e, n[2].e, n[3].i, n[4].data)); + break; + case OPCODE_PROGRAM_ENV_PARAMETER_ARB: + CALL_ProgramEnvParameter4fARB(ctx->Exec, (n[1].e, n[2].ui, n[3].f, + n[4].f, n[5].f, n[6].f)); + break; +#endif +#if FEATURE_ARB_occlusion_query + case OPCODE_BEGIN_QUERY_ARB: + CALL_BeginQueryARB(ctx->Exec, (n[1].e, n[2].ui)); + break; + case OPCODE_END_QUERY_ARB: + CALL_EndQueryARB(ctx->Exec, (n[1].e)); + break; +#endif + case OPCODE_DRAW_BUFFERS_ARB: + { + GLenum buffers[MAX_DRAW_BUFFERS]; + GLint i, count = MIN2(n[1].i, MAX_DRAW_BUFFERS); + for (i = 0; i < count; i++) + buffers[i] = n[2 + i].e; + CALL_DrawBuffersARB(ctx->Exec, (n[1].i, buffers)); + } + break; +#if FEATURE_ATI_fragment_shader + case OPCODE_BIND_FRAGMENT_SHADER_ATI: + CALL_BindFragmentShaderATI(ctx->Exec, (n[1].i)); + break; + case OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI: + { + GLfloat values[4]; + GLuint i, dst = n[1].ui; + + for (i = 0; i < 4; i++) + values[i] = n[1+i].f; + CALL_SetFragmentShaderConstantATI(ctx->Exec, (dst, values)); + } + break; +#endif + case OPCODE_ATTR_1F_NV: + CALL_VertexAttrib1fNV(ctx->Exec, (n[1].e, n[2].f)); + break; + case OPCODE_ATTR_2F_NV: + /* Really shouldn't have to do this - the Node structure + * is convenient, but it would be better to store the data + * packed appropriately so that it can be sent directly + * on. With x86_64 becoming common, this will start to + * matter more. + */ + if (sizeof(Node)==sizeof(GLfloat)) + CALL_VertexAttrib2fvNV(ctx->Exec, (n[1].e, &n[2].f)); + else + CALL_VertexAttrib2fNV(ctx->Exec, (n[1].e, n[2].f, n[3].f)); + break; + case OPCODE_ATTR_3F_NV: + if (sizeof(Node)==sizeof(GLfloat)) + CALL_VertexAttrib3fvNV(ctx->Exec, (n[1].e, &n[2].f)); + else + CALL_VertexAttrib3fNV(ctx->Exec, (n[1].e, n[2].f, n[3].f, + n[4].f)); + break; + case OPCODE_ATTR_4F_NV: + if (sizeof(Node)==sizeof(GLfloat)) + CALL_VertexAttrib4fvNV(ctx->Exec, (n[1].e, &n[2].f)); + else + CALL_VertexAttrib4fNV(ctx->Exec, (n[1].e, n[2].f, n[3].f, + n[4].f, n[5].f)); + break; + case OPCODE_ATTR_1F_ARB: + CALL_VertexAttrib1fARB(ctx->Exec, (n[1].e, n[2].f)); + break; + case OPCODE_ATTR_2F_ARB: + /* Really shouldn't have to do this - the Node structure + * is convenient, but it would be better to store the data + * packed appropriately so that it can be sent directly + * on. With x86_64 becoming common, this will start to + * matter more. + */ + if (sizeof(Node)==sizeof(GLfloat)) + CALL_VertexAttrib2fvARB(ctx->Exec, (n[1].e, &n[2].f)); + else + CALL_VertexAttrib2fARB(ctx->Exec, (n[1].e, n[2].f, n[3].f)); + break; + case OPCODE_ATTR_3F_ARB: + if (sizeof(Node)==sizeof(GLfloat)) + CALL_VertexAttrib3fvARB(ctx->Exec, (n[1].e, &n[2].f)); + else + CALL_VertexAttrib3fARB(ctx->Exec, (n[1].e, n[2].f, n[3].f, + n[4].f)); + break; + case OPCODE_ATTR_4F_ARB: + if (sizeof(Node)==sizeof(GLfloat)) + CALL_VertexAttrib4fvARB(ctx->Exec, (n[1].e, &n[2].f)); + else + CALL_VertexAttrib4fARB(ctx->Exec, (n[1].e, n[2].f, n[3].f, + n[4].f, n[5].f)); + break; + case OPCODE_MATERIAL: + if (sizeof(Node)==sizeof(GLfloat)) + CALL_Materialfv(ctx->Exec, (n[1].e, n[2].e, &n[3].f)); + else { + GLfloat f[4]; + f[0] = n[3].f; + f[1] = n[4].f; + f[2] = n[5].f; + f[3] = n[6].f; + CALL_Materialfv(ctx->Exec, (n[1].e, n[2].e, f)); + } + break; + case OPCODE_INDEX: + CALL_Indexi(ctx->Exec, (n[1].i)); + break; + case OPCODE_EDGEFLAG: + CALL_EdgeFlag(ctx->Exec, (n[1].b)); + break; + case OPCODE_BEGIN: + CALL_Begin(ctx->Exec, (n[1].e)); + break; + case OPCODE_END: + CALL_End(ctx->Exec, ()); + break; + case OPCODE_RECTF: + CALL_Rectf(ctx->Exec, (n[1].f, n[2].f, n[3].f, n[4].f)); + break; + case OPCODE_EVAL_C1: + CALL_EvalCoord1f(ctx->Exec, (n[1].f)); + break; + case OPCODE_EVAL_C2: + CALL_EvalCoord2f(ctx->Exec, (n[1].f, n[2].f)); + break; + case OPCODE_EVAL_P1: + CALL_EvalPoint1(ctx->Exec, (n[1].i)); + break; + case OPCODE_EVAL_P2: + CALL_EvalPoint2(ctx->Exec, (n[1].i, n[2].i)); + break; + + + + + case OPCODE_CONTINUE: + n = (Node *) n[1].next; + break; + case OPCODE_END_OF_LIST: + done = GL_TRUE; + break; + default: + { + char msg[1000]; + _mesa_sprintf(msg, "Error in execute_list: opcode=%d", (int) opcode); + _mesa_problem(ctx, msg); + } + done = GL_TRUE; + } + + /* increment n to point to next compiled command */ + if (opcode!=OPCODE_CONTINUE) { + n += InstSize[opcode]; + } + } + } + + if (ctx->Driver.EndCallList) + ctx->Driver.EndCallList( ctx ); + + ctx->ListState.CallStack[ctx->ListState.CallDepth--] = NULL; +} + + + + + +/**********************************************************************/ +/* GL functions */ +/**********************************************************************/ + + + + +/* + * Test if a display list number is valid. + */ +GLboolean GLAPIENTRY +_mesa_IsList( GLuint list ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); /* must be called before assert */ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + return islist(ctx, list); +} + + +/* + * Delete a sequence of consecutive display lists. + */ +void GLAPIENTRY +_mesa_DeleteLists( GLuint list, GLsizei range ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint i; + FLUSH_VERTICES(ctx, 0); /* must be called before assert */ + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (range<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteLists" ); + return; + } + for (i=list;i<list+range;i++) { + _mesa_destroy_list( ctx, i ); + } +} + + + +/* + * Return a display list number, n, such that lists n through n+range-1 + * are free. + */ +GLuint GLAPIENTRY +_mesa_GenLists(GLsizei range ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint base; + FLUSH_VERTICES(ctx, 0); /* must be called before assert */ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); + + if (range<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glGenLists" ); + return 0; + } + if (range==0) { + return 0; + } + + /* + * Make this an atomic operation + */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + + base = _mesa_HashFindFreeKeyBlock(ctx->Shared->DisplayList, range); + if (base) { + /* reserve the list IDs by with empty/dummy lists */ + GLint i; + for (i=0; i<range; i++) { + _mesa_HashInsert(ctx->Shared->DisplayList, base+i, make_list(base+i, 1)); + } + } + + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + return base; +} + + + +/* + * Begin a new display list. + */ +void GLAPIENTRY +_mesa_NewList( GLuint list, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + FLUSH_CURRENT(ctx, 0); /* must be called before assert */ + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glNewList %u %s\n", list, + _mesa_lookup_enum_by_nr(mode)); + + if (list==0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glNewList" ); + return; + } + + if (mode!=GL_COMPILE && mode!=GL_COMPILE_AND_EXECUTE) { + _mesa_error( ctx, GL_INVALID_ENUM, "glNewList" ); + return; + } + + if (ctx->ListState.CurrentListPtr) { + /* already compiling a display list */ + _mesa_error( ctx, GL_INVALID_OPERATION, "glNewList" ); + return; + } + + ctx->CompileFlag = GL_TRUE; + ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE); + + /* Allocate new display list */ + ctx->ListState.CurrentListNum = list; + ctx->ListState.CurrentList = make_list( list, BLOCK_SIZE ); + ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->node; + ctx->ListState.CurrentListPtr = ctx->ListState.CurrentBlock; + ctx->ListState.CurrentPos = 0; + + /* Reset acumulated list state: + */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) + ctx->ListState.ActiveAttribSize[i] = 0; + + for (i = 0; i < MAT_ATTRIB_MAX; i++) + ctx->ListState.ActiveMaterialSize[i] = 0; + + ctx->ListState.ActiveIndex = 0; + ctx->ListState.ActiveEdgeFlag = 0; + + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; + ctx->Driver.NewList( ctx, list, mode ); + + ctx->CurrentDispatch = ctx->Save; + _glapi_set_dispatch( ctx->CurrentDispatch ); +} + + + +/* + * End definition of current display list. + */ +void GLAPIENTRY +_mesa_EndList( void ) +{ + GET_CURRENT_CONTEXT(ctx); + SAVE_FLUSH_VERTICES(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glEndList\n"); + + /* Check that a list is under construction */ + if (!ctx->ListState.CurrentListPtr) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glEndList" ); + return; + } + + (void) ALLOC_INSTRUCTION( ctx, OPCODE_END_OF_LIST, 0 ); + + /* Destroy old list, if any */ + _mesa_destroy_list(ctx, ctx->ListState.CurrentListNum); + /* Install the list */ + _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum, ctx->ListState.CurrentList); + + + if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) + mesa_print_display_list(ctx->ListState.CurrentListNum); + + ctx->Driver.EndList( ctx ); + + ctx->ListState.CurrentList = NULL; + ctx->ListState.CurrentListNum = 0; + ctx->ListState.CurrentListPtr = NULL; + ctx->ExecuteFlag = GL_TRUE; + ctx->CompileFlag = GL_FALSE; + + ctx->CurrentDispatch = ctx->Exec; + _glapi_set_dispatch( ctx->CurrentDispatch ); +} + + + +void GLAPIENTRY +_mesa_CallList( GLuint list ) +{ + GLboolean save_compile_flag; + GET_CURRENT_CONTEXT(ctx); + FLUSH_CURRENT(ctx, 0); + /* VERY IMPORTANT: Save the CompileFlag status, turn it off, */ + /* execute the display list, and restore the CompileFlag. */ + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCallList %d\n", list); + + if (list == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCallList(list==0)"); + return; + } + +/* mesa_print_display_list( list ); */ + + save_compile_flag = ctx->CompileFlag; + if (save_compile_flag) { + ctx->CompileFlag = GL_FALSE; + } + + execute_list( ctx, list ); + ctx->CompileFlag = save_compile_flag; + + /* also restore API function pointers to point to "save" versions */ + if (save_compile_flag) { + ctx->CurrentDispatch = ctx->Save; + _glapi_set_dispatch( ctx->CurrentDispatch ); + } +} + + + +/* + * Execute glCallLists: call multiple display lists. + */ +void GLAPIENTRY +_mesa_CallLists( GLsizei n, GLenum type, const GLvoid *lists ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint list; + GLint i; + GLboolean save_compile_flag; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glCallLists %d\n", n); + + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_2_BYTES: + case GL_3_BYTES: + case GL_4_BYTES: + /* OK */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)"); + return; + } + + /* Save the CompileFlag status, turn it off, execute display list, + * and restore the CompileFlag. + */ + save_compile_flag = ctx->CompileFlag; + ctx->CompileFlag = GL_FALSE; + + for (i=0;i<n;i++) { + list = translate_id( i, type, lists ); + execute_list( ctx, ctx->List.ListBase + list ); + } + + ctx->CompileFlag = save_compile_flag; + + /* also restore API function pointers to point to "save" versions */ + if (save_compile_flag) { + ctx->CurrentDispatch = ctx->Save; + _glapi_set_dispatch( ctx->CurrentDispatch ); + } +} + + + +/* + * Set the offset added to list numbers in glCallLists. + */ +void GLAPIENTRY +_mesa_ListBase( GLuint base ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); /* must be called before assert */ + ASSERT_OUTSIDE_BEGIN_END(ctx); + ctx->List.ListBase = base; +} + + +/* Can no longer assume ctx->Exec->Func is equal to _mesa_Func. + */ +static void GLAPIENTRY exec_Finish( void ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_Finish(ctx->Exec, ()); +} + +static void GLAPIENTRY exec_Flush( void ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_Flush(ctx->Exec, ( )); +} + +static void GLAPIENTRY exec_GetBooleanv( GLenum pname, GLboolean *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetBooleanv(ctx->Exec, ( pname, params )); +} + +static void GLAPIENTRY exec_GetClipPlane( GLenum plane, GLdouble *equation ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetClipPlane(ctx->Exec, ( plane, equation )); +} + +static void GLAPIENTRY exec_GetDoublev( GLenum pname, GLdouble *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetDoublev(ctx->Exec, ( pname, params )); +} + +static GLenum GLAPIENTRY exec_GetError( void ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + return CALL_GetError(ctx->Exec, ( )); +} + +static void GLAPIENTRY exec_GetFloatv( GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetFloatv(ctx->Exec, ( pname, params )); +} + +static void GLAPIENTRY exec_GetIntegerv( GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetIntegerv(ctx->Exec, ( pname, params )); +} + +static void GLAPIENTRY exec_GetLightfv( GLenum light, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetLightfv(ctx->Exec, ( light, pname, params )); +} + +static void GLAPIENTRY exec_GetLightiv( GLenum light, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetLightiv(ctx->Exec, ( light, pname, params )); +} + +static void GLAPIENTRY exec_GetMapdv( GLenum target, GLenum query, GLdouble *v ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMapdv(ctx->Exec, ( target, query, v )); +} + +static void GLAPIENTRY exec_GetMapfv( GLenum target, GLenum query, GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMapfv(ctx->Exec, ( target, query, v )); +} + +static void GLAPIENTRY exec_GetMapiv( GLenum target, GLenum query, GLint *v ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMapiv(ctx->Exec, ( target, query, v )); +} + +static void GLAPIENTRY exec_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMaterialfv(ctx->Exec, ( face, pname, params )); +} + +static void GLAPIENTRY exec_GetMaterialiv( GLenum face, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMaterialiv(ctx->Exec, ( face, pname, params )); +} + +static void GLAPIENTRY exec_GetPixelMapfv( GLenum map, GLfloat *values ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPixelMapfv(ctx->Exec, ( map, values )); +} + +static void GLAPIENTRY exec_GetPixelMapuiv( GLenum map, GLuint *values ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPixelMapuiv(ctx->Exec, ( map, values )); +} + +static void GLAPIENTRY exec_GetPixelMapusv( GLenum map, GLushort *values ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPixelMapusv(ctx->Exec, ( map, values )); +} + +static void GLAPIENTRY exec_GetPolygonStipple( GLubyte *dest ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPolygonStipple(ctx->Exec, ( dest )); +} + +static const GLubyte * GLAPIENTRY exec_GetString( GLenum name ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + return CALL_GetString(ctx->Exec, ( name )); +} + +static void GLAPIENTRY exec_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexEnvfv(ctx->Exec, ( target, pname, params )); +} + +static void GLAPIENTRY exec_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexEnviv(ctx->Exec, ( target, pname, params )); +} + +static void GLAPIENTRY exec_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexGendv(ctx->Exec, ( coord, pname, params )); +} + +static void GLAPIENTRY exec_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexGenfv(ctx->Exec, ( coord, pname, params )); +} + +static void GLAPIENTRY exec_GetTexGeniv( GLenum coord, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexGeniv(ctx->Exec, ( coord, pname, params )); +} + +static void GLAPIENTRY exec_GetTexImage( GLenum target, GLint level, GLenum format, + GLenum type, GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexImage(ctx->Exec, ( target, level, format, type, pixels )); +} + +static void GLAPIENTRY exec_GetTexLevelParameterfv( GLenum target, GLint level, + GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexLevelParameterfv(ctx->Exec, ( target, level, pname, params )); +} + +static void GLAPIENTRY exec_GetTexLevelParameteriv( GLenum target, GLint level, + GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexLevelParameteriv(ctx->Exec, ( target, level, pname, params )); +} + +static void GLAPIENTRY exec_GetTexParameterfv( GLenum target, GLenum pname, + GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexParameterfv(ctx->Exec, ( target, pname, params )); +} + +static void GLAPIENTRY exec_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetTexParameteriv(ctx->Exec, ( target, pname, params )); +} + +static GLboolean GLAPIENTRY exec_IsEnabled( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + return CALL_IsEnabled(ctx->Exec, ( cap )); +} + +static void GLAPIENTRY exec_PixelStoref( GLenum pname, GLfloat param ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_PixelStoref(ctx->Exec, ( pname, param )); +} + +static void GLAPIENTRY exec_PixelStorei( GLenum pname, GLint param ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_PixelStorei(ctx->Exec, ( pname, param )); +} + +static void GLAPIENTRY exec_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_ReadPixels(ctx->Exec, ( x, y, width, height, format, type, pixels )); +} + +static GLint GLAPIENTRY exec_RenderMode( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + return CALL_RenderMode(ctx->Exec, ( mode )); +} + +static void GLAPIENTRY exec_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_FeedbackBuffer(ctx->Exec, ( size, type, buffer )); +} + +static void GLAPIENTRY exec_SelectBuffer( GLsizei size, GLuint *buffer ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_SelectBuffer(ctx->Exec, ( size, buffer )); +} + +static GLboolean GLAPIENTRY exec_AreTexturesResident(GLsizei n, const GLuint *texName, + GLboolean *residences) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + return CALL_AreTexturesResident(ctx->Exec, ( n, texName, residences)); +} + +static void GLAPIENTRY exec_ColorPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_ColorPointer(ctx->Exec, ( size, type, stride, ptr)); +} + +static void GLAPIENTRY exec_DeleteTextures( GLsizei n, const GLuint *texName) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_DeleteTextures(ctx->Exec, ( n, texName)); +} + +static void GLAPIENTRY exec_DisableClientState( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_DisableClientState(ctx->Exec, ( cap )); +} + +static void GLAPIENTRY exec_EdgeFlagPointer(GLsizei stride, const GLvoid *vptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_EdgeFlagPointer(ctx->Exec, ( stride, vptr)); +} + +static void GLAPIENTRY exec_EnableClientState( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_EnableClientState(ctx->Exec, ( cap )); +} + +static void GLAPIENTRY exec_GenTextures( GLsizei n, GLuint *texName ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GenTextures(ctx->Exec, ( n, texName )); +} + +static void GLAPIENTRY exec_GetPointerv( GLenum pname, GLvoid **params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPointerv(ctx->Exec, ( pname, params )); +} + +static void GLAPIENTRY exec_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_IndexPointer(ctx->Exec, ( type, stride, ptr)); +} + +static void GLAPIENTRY exec_InterleavedArrays(GLenum format, GLsizei stride, + const GLvoid *pointer) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_InterleavedArrays(ctx->Exec, ( format, stride, pointer)); +} + +static GLboolean GLAPIENTRY exec_IsTexture( GLuint texture ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + return CALL_IsTexture(ctx->Exec, ( texture )); +} + +static void GLAPIENTRY exec_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_NormalPointer(ctx->Exec, ( type, stride, ptr )); +} + +static void GLAPIENTRY exec_PopClientAttrib(void) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_PopClientAttrib(ctx->Exec, ()); +} + +static void GLAPIENTRY exec_PushClientAttrib(GLbitfield mask) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_PushClientAttrib(ctx->Exec, ( mask)); +} + +static void GLAPIENTRY exec_TexCoordPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_TexCoordPointer(ctx->Exec, ( size, type, stride, ptr)); +} + +static void GLAPIENTRY exec_GetCompressedTexImageARB(GLenum target, GLint level, + GLvoid *img) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetCompressedTexImageARB(ctx->Exec, ( target, level, img)); +} + +static void GLAPIENTRY exec_VertexPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_VertexPointer(ctx->Exec, ( size, type, stride, ptr)); +} + +static void GLAPIENTRY exec_CopyConvolutionFilter1D(GLenum target, GLenum internalFormat, + GLint x, GLint y, GLsizei width) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_CopyConvolutionFilter1D(ctx->Exec, ( target, internalFormat, x, y, width)); +} + +static void GLAPIENTRY exec_CopyConvolutionFilter2D(GLenum target, GLenum internalFormat, + GLint x, GLint y, GLsizei width, + GLsizei height) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_CopyConvolutionFilter2D(ctx->Exec, ( target, internalFormat, x, y, width, + height)); +} + +static void GLAPIENTRY exec_GetColorTable( GLenum target, GLenum format, + GLenum type, GLvoid *data ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetColorTable(ctx->Exec, ( target, format, type, data )); +} + +static void GLAPIENTRY exec_GetColorTableParameterfv( GLenum target, GLenum pname, + GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetColorTableParameterfv(ctx->Exec, ( target, pname, params )); +} + +static void GLAPIENTRY exec_GetColorTableParameteriv( GLenum target, GLenum pname, + GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetColorTableParameteriv(ctx->Exec, ( target, pname, params )); +} + +static void GLAPIENTRY exec_GetConvolutionFilter(GLenum target, GLenum format, GLenum type, + GLvoid *image) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetConvolutionFilter(ctx->Exec, ( target, format, type, image)); +} + +static void GLAPIENTRY exec_GetConvolutionParameterfv(GLenum target, GLenum pname, + GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetConvolutionParameterfv(ctx->Exec, ( target, pname, params)); +} + +static void GLAPIENTRY exec_GetConvolutionParameteriv(GLenum target, GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetConvolutionParameteriv(ctx->Exec, ( target, pname, params)); +} + +static void GLAPIENTRY exec_GetHistogram(GLenum target, GLboolean reset, GLenum format, + GLenum type, GLvoid *values) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetHistogram(ctx->Exec, ( target, reset, format, type, values)); +} + +static void GLAPIENTRY exec_GetHistogramParameterfv(GLenum target, GLenum pname, + GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetHistogramParameterfv(ctx->Exec, ( target, pname, params)); +} + +static void GLAPIENTRY exec_GetHistogramParameteriv(GLenum target, GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetHistogramParameteriv(ctx->Exec, ( target, pname, params)); +} + +static void GLAPIENTRY exec_GetMinmax(GLenum target, GLboolean reset, GLenum format, + GLenum type, GLvoid *values) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMinmax(ctx->Exec, ( target, reset, format, type, values)); +} + +static void GLAPIENTRY exec_GetMinmaxParameterfv(GLenum target, GLenum pname, + GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMinmaxParameterfv(ctx->Exec, ( target, pname, params)); +} + +static void GLAPIENTRY exec_GetMinmaxParameteriv(GLenum target, GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetMinmaxParameteriv(ctx->Exec, ( target, pname, params)); +} + +static void GLAPIENTRY exec_GetSeparableFilter(GLenum target, GLenum format, GLenum type, + GLvoid *row, GLvoid *column, GLvoid *span) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetSeparableFilter(ctx->Exec, ( target, format, type, row, column, span)); +} + +static void GLAPIENTRY exec_SeparableFilter2D(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid *row, + const GLvoid *column) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_SeparableFilter2D(ctx->Exec, ( target, internalFormat, width, height, format, + type, row, column)); +} + +static void GLAPIENTRY exec_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPixelTexGenParameterivSGIS(ctx->Exec, ( target, value)); +} + +static void GLAPIENTRY exec_GetPixelTexGenParameterfvSGIS(GLenum target, GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_GetPixelTexGenParameterfvSGIS(ctx->Exec, ( target, value)); +} + +static void GLAPIENTRY exec_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_ColorPointerEXT(ctx->Exec, ( size, type, stride, count, ptr)); +} + +static void GLAPIENTRY exec_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, + const GLboolean *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_EdgeFlagPointerEXT(ctx->Exec, ( stride, count, ptr)); +} + +static void GLAPIENTRY exec_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_IndexPointerEXT(ctx->Exec, ( type, stride, count, ptr)); +} + +static void GLAPIENTRY exec_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_NormalPointerEXT(ctx->Exec, ( type, stride, count, ptr)); +} + +static void GLAPIENTRY exec_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_TexCoordPointerEXT(ctx->Exec, ( size, type, stride, count, ptr)); +} + +static void GLAPIENTRY exec_VertexPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_VertexPointerEXT(ctx->Exec, ( size, type, stride, count, ptr)); +} + +static void GLAPIENTRY exec_LockArraysEXT(GLint first, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_LockArraysEXT(ctx->Exec, ( first, count)); +} + +static void GLAPIENTRY exec_UnlockArraysEXT( void ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_UnlockArraysEXT(ctx->Exec, ( )); +} + +static void GLAPIENTRY exec_ClientActiveTextureARB( GLenum target ) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_ClientActiveTextureARB(ctx->Exec, (target)); +} + +static void GLAPIENTRY exec_SecondaryColorPointerEXT(GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_SecondaryColorPointerEXT(ctx->Exec, ( size, type, stride, ptr)); +} + +static void GLAPIENTRY exec_FogCoordPointerEXT(GLenum type, GLsizei stride, + const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_FogCoordPointerEXT(ctx->Exec, ( type, stride, ptr)); +} + +/* GL_EXT_multi_draw_arrays */ +static void GLAPIENTRY exec_MultiDrawArraysEXT(GLenum mode, GLint *first, + GLsizei *count, GLsizei primcount) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_MultiDrawArraysEXT(ctx->Exec, ( mode, first, count, primcount )); +} + +/* GL_EXT_multi_draw_arrays */ +static void GLAPIENTRY exec_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, + GLenum type, const GLvoid **indices, + GLsizei primcount) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_MultiDrawElementsEXT(ctx->Exec, (mode, count, type, indices, primcount)); +} + +/* GL_IBM_multimode_draw_arrays */ +static void GLAPIENTRY exec_MultiModeDrawArraysIBM(const GLenum *mode, const GLint *first, + const GLsizei *count, GLsizei primcount, + GLint modestride) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_MultiModeDrawArraysIBM(ctx->Exec, (mode, first, count, primcount, modestride)); +} + +/* GL_IBM_multimode_draw_arrays */ +static void GLAPIENTRY exec_MultiModeDrawElementsIBM(const GLenum *mode, + const GLsizei *count, + GLenum type, + const GLvoid * const *indices, + GLsizei primcount, GLint modestride) +{ + GET_CURRENT_CONTEXT(ctx); + FLUSH_VERTICES(ctx, 0); + CALL_MultiModeDrawElementsIBM(ctx->Exec, (mode, count, type, indices, primcount, + modestride)); +} + + + + +/** + * Setup the given dispatch table to point to Mesa's display list + * building functions. + * + * This does not include any of the tnl functions - they are + * initialized from _mesa_init_api_defaults and from the active vtxfmt + * struct. + */ +void +_mesa_init_dlist_table( struct _glapi_table *table ) +{ + _mesa_loopback_init_api_table( table ); + + /* GL 1.0 */ + SET_Accum(table, save_Accum); + SET_AlphaFunc(table, save_AlphaFunc); + SET_Bitmap(table, save_Bitmap); + SET_BlendFunc(table, _mesa_BlendFunc); /* loops-back to BlendFuncSeparate */ + SET_CallList(table, _mesa_save_CallList); + SET_CallLists(table, _mesa_save_CallLists); + SET_Clear(table, save_Clear); + SET_ClearAccum(table, save_ClearAccum); + SET_ClearColor(table, save_ClearColor); + SET_ClearDepth(table, save_ClearDepth); + SET_ClearIndex(table, save_ClearIndex); + SET_ClearStencil(table, save_ClearStencil); + SET_ClipPlane(table, save_ClipPlane); + SET_ColorMask(table, save_ColorMask); + SET_ColorMaterial(table, save_ColorMaterial); + SET_CopyPixels(table, save_CopyPixels); + SET_CullFace(table, save_CullFace); + SET_DeleteLists(table, _mesa_DeleteLists); + SET_DepthFunc(table, save_DepthFunc); + SET_DepthMask(table, save_DepthMask); + SET_DepthRange(table, save_DepthRange); + SET_Disable(table, save_Disable); + SET_DrawBuffer(table, save_DrawBuffer); + SET_DrawPixels(table, save_DrawPixels); + SET_Enable(table, save_Enable); + SET_EndList(table, _mesa_EndList); + SET_EvalMesh1(table, _mesa_save_EvalMesh1); + SET_EvalMesh2(table, _mesa_save_EvalMesh2); + SET_Finish(table, exec_Finish); + SET_Flush(table, exec_Flush); + SET_Fogf(table, save_Fogf); + SET_Fogfv(table, save_Fogfv); + SET_Fogi(table, save_Fogi); + SET_Fogiv(table, save_Fogiv); + SET_FrontFace(table, save_FrontFace); + SET_Frustum(table, save_Frustum); + SET_GenLists(table, _mesa_GenLists); + SET_GetBooleanv(table, exec_GetBooleanv); + SET_GetClipPlane(table, exec_GetClipPlane); + SET_GetDoublev(table, exec_GetDoublev); + SET_GetError(table, exec_GetError); + SET_GetFloatv(table, exec_GetFloatv); + SET_GetIntegerv(table, exec_GetIntegerv); + SET_GetLightfv(table, exec_GetLightfv); + SET_GetLightiv(table, exec_GetLightiv); + SET_GetMapdv(table, exec_GetMapdv); + SET_GetMapfv(table, exec_GetMapfv); + SET_GetMapiv(table, exec_GetMapiv); + SET_GetMaterialfv(table, exec_GetMaterialfv); + SET_GetMaterialiv(table, exec_GetMaterialiv); + SET_GetPixelMapfv(table, exec_GetPixelMapfv); + SET_GetPixelMapuiv(table, exec_GetPixelMapuiv); + SET_GetPixelMapusv(table, exec_GetPixelMapusv); + SET_GetPolygonStipple(table, exec_GetPolygonStipple); + SET_GetString(table, exec_GetString); + SET_GetTexEnvfv(table, exec_GetTexEnvfv); + SET_GetTexEnviv(table, exec_GetTexEnviv); + SET_GetTexGendv(table, exec_GetTexGendv); + SET_GetTexGenfv(table, exec_GetTexGenfv); + SET_GetTexGeniv(table, exec_GetTexGeniv); + SET_GetTexImage(table, exec_GetTexImage); + SET_GetTexLevelParameterfv(table, exec_GetTexLevelParameterfv); + SET_GetTexLevelParameteriv(table, exec_GetTexLevelParameteriv); + SET_GetTexParameterfv(table, exec_GetTexParameterfv); + SET_GetTexParameteriv(table, exec_GetTexParameteriv); + SET_Hint(table, save_Hint); + SET_IndexMask(table, save_IndexMask); + SET_InitNames(table, save_InitNames); + SET_IsEnabled(table, exec_IsEnabled); + SET_IsList(table, _mesa_IsList); + SET_LightModelf(table, save_LightModelf); + SET_LightModelfv(table, save_LightModelfv); + SET_LightModeli(table, save_LightModeli); + SET_LightModeliv(table, save_LightModeliv); + SET_Lightf(table, save_Lightf); + SET_Lightfv(table, save_Lightfv); + SET_Lighti(table, save_Lighti); + SET_Lightiv(table, save_Lightiv); + SET_LineStipple(table, save_LineStipple); + SET_LineWidth(table, save_LineWidth); + SET_ListBase(table, save_ListBase); + SET_LoadIdentity(table, save_LoadIdentity); + SET_LoadMatrixd(table, save_LoadMatrixd); + SET_LoadMatrixf(table, save_LoadMatrixf); + SET_LoadName(table, save_LoadName); + SET_LogicOp(table, save_LogicOp); + SET_Map1d(table, save_Map1d); + SET_Map1f(table, save_Map1f); + SET_Map2d(table, save_Map2d); + SET_Map2f(table, save_Map2f); + SET_MapGrid1d(table, save_MapGrid1d); + SET_MapGrid1f(table, save_MapGrid1f); + SET_MapGrid2d(table, save_MapGrid2d); + SET_MapGrid2f(table, save_MapGrid2f); + SET_MatrixMode(table, save_MatrixMode); + SET_MultMatrixd(table, save_MultMatrixd); + SET_MultMatrixf(table, save_MultMatrixf); + SET_NewList(table, save_NewList); + SET_Ortho(table, save_Ortho); + SET_PassThrough(table, save_PassThrough); + SET_PixelMapfv(table, save_PixelMapfv); + SET_PixelMapuiv(table, save_PixelMapuiv); + SET_PixelMapusv(table, save_PixelMapusv); + SET_PixelStoref(table, exec_PixelStoref); + SET_PixelStorei(table, exec_PixelStorei); + SET_PixelTransferf(table, save_PixelTransferf); + SET_PixelTransferi(table, save_PixelTransferi); + SET_PixelZoom(table, save_PixelZoom); + SET_PointSize(table, save_PointSize); + SET_PolygonMode(table, save_PolygonMode); + SET_PolygonOffset(table, save_PolygonOffset); + SET_PolygonStipple(table, save_PolygonStipple); + SET_PopAttrib(table, save_PopAttrib); + SET_PopMatrix(table, save_PopMatrix); + SET_PopName(table, save_PopName); + SET_PushAttrib(table, save_PushAttrib); + SET_PushMatrix(table, save_PushMatrix); + SET_PushName(table, save_PushName); + SET_RasterPos2d(table, save_RasterPos2d); + SET_RasterPos2dv(table, save_RasterPos2dv); + SET_RasterPos2f(table, save_RasterPos2f); + SET_RasterPos2fv(table, save_RasterPos2fv); + SET_RasterPos2i(table, save_RasterPos2i); + SET_RasterPos2iv(table, save_RasterPos2iv); + SET_RasterPos2s(table, save_RasterPos2s); + SET_RasterPos2sv(table, save_RasterPos2sv); + SET_RasterPos3d(table, save_RasterPos3d); + SET_RasterPos3dv(table, save_RasterPos3dv); + SET_RasterPos3f(table, save_RasterPos3f); + SET_RasterPos3fv(table, save_RasterPos3fv); + SET_RasterPos3i(table, save_RasterPos3i); + SET_RasterPos3iv(table, save_RasterPos3iv); + SET_RasterPos3s(table, save_RasterPos3s); + SET_RasterPos3sv(table, save_RasterPos3sv); + SET_RasterPos4d(table, save_RasterPos4d); + SET_RasterPos4dv(table, save_RasterPos4dv); + SET_RasterPos4f(table, save_RasterPos4f); + SET_RasterPos4fv(table, save_RasterPos4fv); + SET_RasterPos4i(table, save_RasterPos4i); + SET_RasterPos4iv(table, save_RasterPos4iv); + SET_RasterPos4s(table, save_RasterPos4s); + SET_RasterPos4sv(table, save_RasterPos4sv); + SET_ReadBuffer(table, save_ReadBuffer); + SET_ReadPixels(table, exec_ReadPixels); + SET_RenderMode(table, exec_RenderMode); + SET_Rotated(table, save_Rotated); + SET_Rotatef(table, save_Rotatef); + SET_Scaled(table, save_Scaled); + SET_Scalef(table, save_Scalef); + SET_Scissor(table, save_Scissor); + SET_FeedbackBuffer(table, exec_FeedbackBuffer); + SET_SelectBuffer(table, exec_SelectBuffer); + SET_ShadeModel(table, save_ShadeModel); + SET_StencilFunc(table, save_StencilFunc); + SET_StencilMask(table, save_StencilMask); + SET_StencilOp(table, save_StencilOp); + SET_TexEnvf(table, save_TexEnvf); + SET_TexEnvfv(table, save_TexEnvfv); + SET_TexEnvi(table, save_TexEnvi); + SET_TexEnviv(table, save_TexEnviv); + SET_TexGend(table, save_TexGend); + SET_TexGendv(table, save_TexGendv); + SET_TexGenf(table, save_TexGenf); + SET_TexGenfv(table, save_TexGenfv); + SET_TexGeni(table, save_TexGeni); + SET_TexGeniv(table, save_TexGeniv); + SET_TexImage1D(table, save_TexImage1D); + SET_TexImage2D(table, save_TexImage2D); + SET_TexParameterf(table, save_TexParameterf); + SET_TexParameterfv(table, save_TexParameterfv); + SET_TexParameteri(table, save_TexParameteri); + SET_TexParameteriv(table, save_TexParameteriv); + SET_Translated(table, save_Translated); + SET_Translatef(table, save_Translatef); + SET_Viewport(table, save_Viewport); + + /* GL 1.1 */ + SET_AreTexturesResident(table, exec_AreTexturesResident); + SET_AreTexturesResidentEXT(table, exec_AreTexturesResident); + SET_BindTexture(table, save_BindTexture); + SET_ColorPointer(table, exec_ColorPointer); + SET_CopyTexImage1D(table, save_CopyTexImage1D); + SET_CopyTexImage2D(table, save_CopyTexImage2D); + SET_CopyTexSubImage1D(table, save_CopyTexSubImage1D); + SET_CopyTexSubImage2D(table, save_CopyTexSubImage2D); + SET_DeleteTextures(table, exec_DeleteTextures); + SET_DisableClientState(table, exec_DisableClientState); + SET_EdgeFlagPointer(table, exec_EdgeFlagPointer); + SET_EnableClientState(table, exec_EnableClientState); + SET_GenTextures(table, exec_GenTextures); + SET_GenTexturesEXT(table, exec_GenTextures); + SET_GetPointerv(table, exec_GetPointerv); + SET_IndexPointer(table, exec_IndexPointer); + SET_InterleavedArrays(table, exec_InterleavedArrays); + SET_IsTexture(table, exec_IsTexture); + SET_IsTextureEXT(table, exec_IsTexture); + SET_NormalPointer(table, exec_NormalPointer); + SET_PopClientAttrib(table, exec_PopClientAttrib); + SET_PrioritizeTextures(table, save_PrioritizeTextures); + SET_PushClientAttrib(table, exec_PushClientAttrib); + SET_TexCoordPointer(table, exec_TexCoordPointer); + SET_TexSubImage1D(table, save_TexSubImage1D); + SET_TexSubImage2D(table, save_TexSubImage2D); + SET_VertexPointer(table, exec_VertexPointer); + + /* GL 1.2 */ + SET_CopyTexSubImage3D(table, save_CopyTexSubImage3D); + SET_TexImage3D(table, save_TexImage3D); + SET_TexSubImage3D(table, save_TexSubImage3D); + + /* GL 2.0 */ + SET_StencilFuncSeparate(table, save_StencilFuncSeparate); + SET_StencilMaskSeparate(table, save_StencilMaskSeparate); + SET_StencilOpSeparate(table, save_StencilOpSeparate); + + /* GL_ARB_imaging */ + /* Not all are supported */ + SET_BlendColor(table, save_BlendColor); + SET_BlendEquation(table, save_BlendEquation); + SET_ColorSubTable(table, save_ColorSubTable); + SET_ColorTable(table, save_ColorTable); + SET_ColorTableParameterfv(table, save_ColorTableParameterfv); + SET_ColorTableParameteriv(table, save_ColorTableParameteriv); + SET_ConvolutionFilter1D(table, save_ConvolutionFilter1D); + SET_ConvolutionFilter2D(table, save_ConvolutionFilter2D); + SET_ConvolutionParameterf(table, save_ConvolutionParameterf); + SET_ConvolutionParameterfv(table, save_ConvolutionParameterfv); + SET_ConvolutionParameteri(table, save_ConvolutionParameteri); + SET_ConvolutionParameteriv(table, save_ConvolutionParameteriv); + SET_CopyColorSubTable(table, save_CopyColorSubTable); + SET_CopyColorTable(table, save_CopyColorTable); + SET_CopyConvolutionFilter1D(table, exec_CopyConvolutionFilter1D); + SET_CopyConvolutionFilter2D(table, exec_CopyConvolutionFilter2D); + SET_GetColorTable(table, exec_GetColorTable); + SET_GetColorTableEXT(table, exec_GetColorTable); + SET_GetColorTableParameterfv(table, exec_GetColorTableParameterfv); + SET_GetColorTableParameterfvEXT(table, exec_GetColorTableParameterfv); + SET_GetColorTableParameteriv(table, exec_GetColorTableParameteriv); + SET_GetColorTableParameterivEXT(table, exec_GetColorTableParameteriv); + SET_GetConvolutionFilter(table, exec_GetConvolutionFilter); + SET_GetConvolutionFilterEXT(table, exec_GetConvolutionFilter); + SET_GetConvolutionParameterfv(table, exec_GetConvolutionParameterfv); + SET_GetConvolutionParameterfvEXT(table, exec_GetConvolutionParameterfv); + SET_GetConvolutionParameteriv(table, exec_GetConvolutionParameteriv); + SET_GetConvolutionParameterivEXT(table, exec_GetConvolutionParameteriv); + SET_GetHistogram(table, exec_GetHistogram); + SET_GetHistogramEXT(table, exec_GetHistogram); + SET_GetHistogramParameterfv(table, exec_GetHistogramParameterfv); + SET_GetHistogramParameterfvEXT(table, exec_GetHistogramParameterfv); + SET_GetHistogramParameteriv(table, exec_GetHistogramParameteriv); + SET_GetHistogramParameterivEXT(table, exec_GetHistogramParameteriv); + SET_GetMinmax(table, exec_GetMinmax); + SET_GetMinmaxEXT(table, exec_GetMinmax); + SET_GetMinmaxParameterfv(table, exec_GetMinmaxParameterfv); + SET_GetMinmaxParameterfvEXT(table, exec_GetMinmaxParameterfv); + SET_GetMinmaxParameteriv(table, exec_GetMinmaxParameteriv); + SET_GetMinmaxParameterivEXT(table, exec_GetMinmaxParameteriv); + SET_GetSeparableFilter(table, exec_GetSeparableFilter); + SET_GetSeparableFilterEXT(table, exec_GetSeparableFilter); + SET_Histogram(table, save_Histogram); + SET_Minmax(table, save_Minmax); + SET_ResetHistogram(table, save_ResetHistogram); + SET_ResetMinmax(table, save_ResetMinmax); + SET_SeparableFilter2D(table, exec_SeparableFilter2D); + + /* 2. GL_EXT_blend_color */ +#if 0 + SET_BlendColorEXT(table, save_BlendColorEXT); +#endif + + /* 3. GL_EXT_polygon_offset */ + SET_PolygonOffsetEXT(table, save_PolygonOffsetEXT); + + /* 6. GL_EXT_texture3d */ +#if 0 + SET_CopyTexSubImage3DEXT(table, save_CopyTexSubImage3D); + SET_TexImage3DEXT(table, save_TexImage3DEXT); + SET_TexSubImage3DEXT(table, save_TexSubImage3D); +#endif + + /* 15. GL_SGIX_pixel_texture */ + SET_PixelTexGenSGIX(table, save_PixelTexGenSGIX); + + /* 15. GL_SGIS_pixel_texture */ + SET_PixelTexGenParameteriSGIS(table, save_PixelTexGenParameteriSGIS); + SET_PixelTexGenParameterfSGIS(table, save_PixelTexGenParameterfSGIS); + SET_PixelTexGenParameterivSGIS(table, save_PixelTexGenParameterivSGIS); + SET_PixelTexGenParameterfvSGIS(table, save_PixelTexGenParameterfvSGIS); + SET_GetPixelTexGenParameterivSGIS(table, exec_GetPixelTexGenParameterivSGIS); + SET_GetPixelTexGenParameterfvSGIS(table, exec_GetPixelTexGenParameterfvSGIS); + + /* 30. GL_EXT_vertex_array */ + SET_ColorPointerEXT(table, exec_ColorPointerEXT); + SET_EdgeFlagPointerEXT(table, exec_EdgeFlagPointerEXT); + SET_IndexPointerEXT(table, exec_IndexPointerEXT); + SET_NormalPointerEXT(table, exec_NormalPointerEXT); + SET_TexCoordPointerEXT(table, exec_TexCoordPointerEXT); + SET_VertexPointerEXT(table, exec_VertexPointerEXT); + + /* 37. GL_EXT_blend_minmax */ +#if 0 + SET_BlendEquationEXT(table, save_BlendEquationEXT); +#endif + + /* 54. GL_EXT_point_parameters */ + SET_PointParameterfEXT(table, save_PointParameterfEXT); + SET_PointParameterfvEXT(table, save_PointParameterfvEXT); + + /* 78. GL_EXT_paletted_texture */ +#if 0 + SET_ColorTableEXT(table, save_ColorTable); + SET_ColorSubTableEXT(table, save_ColorSubTable); +#endif + SET_GetColorTableEXT(table, exec_GetColorTable); + SET_GetColorTableParameterfvEXT(table, exec_GetColorTableParameterfv); + SET_GetColorTableParameterivEXT(table, exec_GetColorTableParameteriv); + + /* 97. GL_EXT_compiled_vertex_array */ + SET_LockArraysEXT(table, exec_LockArraysEXT); + SET_UnlockArraysEXT(table, exec_UnlockArraysEXT); + + /* 145. GL_EXT_secondary_color */ + SET_SecondaryColorPointerEXT(table, exec_SecondaryColorPointerEXT); + + /* 148. GL_EXT_multi_draw_arrays */ + SET_MultiDrawArraysEXT(table, exec_MultiDrawArraysEXT); + SET_MultiDrawElementsEXT(table, exec_MultiDrawElementsEXT); + + /* 149. GL_EXT_fog_coord */ + SET_FogCoordPointerEXT(table, exec_FogCoordPointerEXT); + + /* 173. GL_EXT_blend_func_separate */ + SET_BlendFuncSeparateEXT(table, save_BlendFuncSeparateEXT); + + /* 196. GL_MESA_resize_buffers */ + SET_ResizeBuffersMESA(table, _mesa_ResizeBuffersMESA); + + /* 197. GL_MESA_window_pos */ + SET_WindowPos2dMESA(table, save_WindowPos2dMESA); + SET_WindowPos2dvMESA(table, save_WindowPos2dvMESA); + SET_WindowPos2fMESA(table, save_WindowPos2fMESA); + SET_WindowPos2fvMESA(table, save_WindowPos2fvMESA); + SET_WindowPos2iMESA(table, save_WindowPos2iMESA); + SET_WindowPos2ivMESA(table, save_WindowPos2ivMESA); + SET_WindowPos2sMESA(table, save_WindowPos2sMESA); + SET_WindowPos2svMESA(table, save_WindowPos2svMESA); + SET_WindowPos3dMESA(table, save_WindowPos3dMESA); + SET_WindowPos3dvMESA(table, save_WindowPos3dvMESA); + SET_WindowPos3fMESA(table, save_WindowPos3fMESA); + SET_WindowPos3fvMESA(table, save_WindowPos3fvMESA); + SET_WindowPos3iMESA(table, save_WindowPos3iMESA); + SET_WindowPos3ivMESA(table, save_WindowPos3ivMESA); + SET_WindowPos3sMESA(table, save_WindowPos3sMESA); + SET_WindowPos3svMESA(table, save_WindowPos3svMESA); + SET_WindowPos4dMESA(table, save_WindowPos4dMESA); + SET_WindowPos4dvMESA(table, save_WindowPos4dvMESA); + SET_WindowPos4fMESA(table, save_WindowPos4fMESA); + SET_WindowPos4fvMESA(table, save_WindowPos4fvMESA); + SET_WindowPos4iMESA(table, save_WindowPos4iMESA); + SET_WindowPos4ivMESA(table, save_WindowPos4ivMESA); + SET_WindowPos4sMESA(table, save_WindowPos4sMESA); + SET_WindowPos4svMESA(table, save_WindowPos4svMESA); + + /* 200. GL_IBM_multimode_draw_arrays */ + SET_MultiModeDrawArraysIBM(table, exec_MultiModeDrawArraysIBM); + SET_MultiModeDrawElementsIBM(table, exec_MultiModeDrawElementsIBM); + +#if FEATURE_NV_vertex_program + /* 233. GL_NV_vertex_program */ + /* The following commands DO NOT go into display lists: + * AreProgramsResidentNV, IsProgramNV, GenProgramsNV, DeleteProgramsNV, + * VertexAttribPointerNV, GetProgram*, GetVertexAttrib* + */ + SET_BindProgramNV(table, save_BindProgramNV); + SET_DeleteProgramsNV(table, _mesa_DeletePrograms); + SET_ExecuteProgramNV(table, save_ExecuteProgramNV); + SET_GenProgramsNV(table, _mesa_GenPrograms); + SET_AreProgramsResidentNV(table, _mesa_AreProgramsResidentNV); + SET_RequestResidentProgramsNV(table, save_RequestResidentProgramsNV); + SET_GetProgramParameterfvNV(table, _mesa_GetProgramParameterfvNV); + SET_GetProgramParameterdvNV(table, _mesa_GetProgramParameterdvNV); + SET_GetProgramivNV(table, _mesa_GetProgramivNV); + SET_GetProgramStringNV(table, _mesa_GetProgramStringNV); + SET_GetTrackMatrixivNV(table, _mesa_GetTrackMatrixivNV); + SET_GetVertexAttribdvNV(table, _mesa_GetVertexAttribdvNV); + SET_GetVertexAttribfvNV(table, _mesa_GetVertexAttribfvNV); + SET_GetVertexAttribivNV(table, _mesa_GetVertexAttribivNV); + SET_GetVertexAttribPointervNV(table, _mesa_GetVertexAttribPointervNV); + SET_IsProgramNV(table, _mesa_IsProgram); + SET_LoadProgramNV(table, save_LoadProgramNV); + SET_ProgramParameter4dNV(table, save_ProgramParameter4dNV); + SET_ProgramParameter4dvNV(table, save_ProgramParameter4dvNV); + SET_ProgramParameter4fNV(table, save_ProgramParameter4fNV); + SET_ProgramParameter4fvNV(table, save_ProgramParameter4fvNV); + SET_ProgramParameters4dvNV(table, save_ProgramParameters4dvNV); + SET_ProgramParameters4fvNV(table, save_ProgramParameters4fvNV); + SET_TrackMatrixNV(table, save_TrackMatrixNV); + SET_VertexAttribPointerNV(table, _mesa_VertexAttribPointerNV); +#endif + + /* 245. GL_ATI_fragment_shader */ +#if FEATURE_ATI_fragment_shader + SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI); + SET_SetFragmentShaderConstantATI(table, save_SetFragmentShaderConstantATI); +#endif + + /* 282. GL_NV_fragment_program */ +#if FEATURE_NV_fragment_program + SET_ProgramNamedParameter4fNV(table, save_ProgramNamedParameter4fNV); + SET_ProgramNamedParameter4dNV(table, save_ProgramNamedParameter4dNV); + SET_ProgramNamedParameter4fvNV(table, save_ProgramNamedParameter4fvNV); + SET_ProgramNamedParameter4dvNV(table, save_ProgramNamedParameter4dvNV); + SET_GetProgramNamedParameterfvNV(table, _mesa_GetProgramNamedParameterfvNV); + SET_GetProgramNamedParameterdvNV(table, _mesa_GetProgramNamedParameterdvNV); + SET_ProgramLocalParameter4dARB(table, save_ProgramLocalParameter4dARB); + SET_ProgramLocalParameter4dvARB(table, save_ProgramLocalParameter4dvARB); + SET_ProgramLocalParameter4fARB(table, save_ProgramLocalParameter4fARB); + SET_ProgramLocalParameter4fvARB(table, save_ProgramLocalParameter4fvARB); + SET_GetProgramLocalParameterdvARB(table, _mesa_GetProgramLocalParameterdvARB); + SET_GetProgramLocalParameterfvARB(table, _mesa_GetProgramLocalParameterfvARB); +#endif + + /* 262. GL_NV_point_sprite */ + SET_PointParameteriNV(table, save_PointParameteriNV); + SET_PointParameterivNV(table, save_PointParameterivNV); + + /* 268. GL_EXT_stencil_two_side */ + SET_ActiveStencilFaceEXT(table, save_ActiveStencilFaceEXT); + + /* ???. GL_EXT_depth_bounds_test */ + SET_DepthBoundsEXT(table, save_DepthBoundsEXT); + + /* ARB 1. GL_ARB_multitexture */ + SET_ActiveTextureARB(table, save_ActiveTextureARB); + SET_ClientActiveTextureARB(table, exec_ClientActiveTextureARB); + + /* ARB 3. GL_ARB_transpose_matrix */ + SET_LoadTransposeMatrixdARB(table, save_LoadTransposeMatrixdARB); + SET_LoadTransposeMatrixfARB(table, save_LoadTransposeMatrixfARB); + SET_MultTransposeMatrixdARB(table, save_MultTransposeMatrixdARB); + SET_MultTransposeMatrixfARB(table, save_MultTransposeMatrixfARB); + + /* ARB 5. GL_ARB_multisample */ + SET_SampleCoverageARB(table, save_SampleCoverageARB); + + /* ARB 12. GL_ARB_texture_compression */ + SET_CompressedTexImage3DARB(table, save_CompressedTexImage3DARB); + SET_CompressedTexImage2DARB(table, save_CompressedTexImage2DARB); + SET_CompressedTexImage1DARB(table, save_CompressedTexImage1DARB); + SET_CompressedTexSubImage3DARB(table, save_CompressedTexSubImage3DARB); + SET_CompressedTexSubImage2DARB(table, save_CompressedTexSubImage2DARB); + SET_CompressedTexSubImage1DARB(table, save_CompressedTexSubImage1DARB); + SET_GetCompressedTexImageARB(table, exec_GetCompressedTexImageARB); + + /* ARB 14. GL_ARB_point_parameters */ + /* aliased with EXT_point_parameters functions */ + + /* ARB 25. GL_ARB_window_pos */ + /* aliased with MESA_window_pos functions */ + + /* ARB 26. GL_ARB_vertex_program */ + /* ARB 27. GL_ARB_fragment_program */ +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + /* glVertexAttrib* functions alias the NV ones, handled elsewhere */ + SET_VertexAttribPointerARB(table, _mesa_VertexAttribPointerARB); + SET_EnableVertexAttribArrayARB(table, _mesa_EnableVertexAttribArrayARB); + SET_DisableVertexAttribArrayARB(table, _mesa_DisableVertexAttribArrayARB); + SET_ProgramStringARB(table, save_ProgramStringARB); + SET_BindProgramNV(table, save_BindProgramNV); + SET_DeleteProgramsNV(table, _mesa_DeletePrograms); + SET_GenProgramsNV(table, _mesa_GenPrograms); + SET_IsProgramNV(table, _mesa_IsProgram); + SET_GetVertexAttribdvNV(table, _mesa_GetVertexAttribdvNV); + SET_GetVertexAttribfvNV(table, _mesa_GetVertexAttribfvNV); + SET_GetVertexAttribivNV(table, _mesa_GetVertexAttribivNV); + SET_GetVertexAttribPointervNV(table, _mesa_GetVertexAttribPointervNV); + SET_ProgramEnvParameter4dARB(table, save_ProgramEnvParameter4dARB); + SET_ProgramEnvParameter4dvARB(table, save_ProgramEnvParameter4dvARB); + SET_ProgramEnvParameter4fARB(table, save_ProgramEnvParameter4fARB); + SET_ProgramEnvParameter4fvARB(table, save_ProgramEnvParameter4fvARB); + SET_ProgramLocalParameter4dARB(table, save_ProgramLocalParameter4dARB); + SET_ProgramLocalParameter4dvARB(table, save_ProgramLocalParameter4dvARB); + SET_ProgramLocalParameter4fARB(table, save_ProgramLocalParameter4fARB); + SET_ProgramLocalParameter4fvARB(table, save_ProgramLocalParameter4fvARB); + SET_GetProgramEnvParameterdvARB(table, _mesa_GetProgramEnvParameterdvARB); + SET_GetProgramEnvParameterfvARB(table, _mesa_GetProgramEnvParameterfvARB); + SET_GetProgramLocalParameterdvARB(table, _mesa_GetProgramLocalParameterdvARB); + SET_GetProgramLocalParameterfvARB(table, _mesa_GetProgramLocalParameterfvARB); + SET_GetProgramivARB(table, _mesa_GetProgramivARB); + SET_GetProgramStringARB(table, _mesa_GetProgramStringARB); +#endif + + /* ARB 28. GL_ARB_vertex_buffer_object */ +#if FEATURE_ARB_vertex_buffer_object + /* None of the extension's functions get compiled */ + SET_BindBufferARB(table, _mesa_BindBufferARB); + SET_BufferDataARB(table, _mesa_BufferDataARB); + SET_BufferSubDataARB(table, _mesa_BufferSubDataARB); + SET_DeleteBuffersARB(table, _mesa_DeleteBuffersARB); + SET_GenBuffersARB(table, _mesa_GenBuffersARB); + SET_GetBufferParameterivARB(table, _mesa_GetBufferParameterivARB); + SET_GetBufferPointervARB(table, _mesa_GetBufferPointervARB); + SET_GetBufferSubDataARB(table, _mesa_GetBufferSubDataARB); + SET_IsBufferARB(table, _mesa_IsBufferARB); + SET_MapBufferARB(table, _mesa_MapBufferARB); + SET_UnmapBufferARB(table, _mesa_UnmapBufferARB); +#endif + +#if FEATURE_ARB_occlusion_query + SET_BeginQueryARB(table, save_BeginQueryARB); + SET_EndQueryARB(table, save_EndQueryARB); + SET_GenQueriesARB(table, _mesa_GenQueriesARB); + SET_DeleteQueriesARB(table, _mesa_DeleteQueriesARB); + SET_IsQueryARB(table, _mesa_IsQueryARB); + SET_GetQueryivARB(table, _mesa_GetQueryivARB); + SET_GetQueryObjectivARB(table, _mesa_GetQueryObjectivARB); + SET_GetQueryObjectuivARB(table, _mesa_GetQueryObjectuivARB); +#endif + SET_DrawBuffersARB(table, save_DrawBuffersARB); + + /* 299. GL_EXT_blend_equation_separate */ + SET_BlendEquationSeparateEXT(table, save_BlendEquationSeparateEXT); +} + + + +/*** + *** Debugging code + ***/ +static const char *enum_string( GLenum k ) +{ + return _mesa_lookup_enum_by_nr( k ); +} + + +/* + * Print the commands in a display list. For debugging only. + * TODO: many commands aren't handled yet. + */ +static void GLAPIENTRY print_list( GLcontext *ctx, GLuint list ) +{ + struct mesa_display_list *dlist; + Node *n; + GLboolean done; + + if (!CALL_IsList(GET_DISPATCH(), (list))) { + _mesa_printf("%u is not a display list ID\n", list); + return; + } + + dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); + if (!dlist) + return; + + n = dlist->node; + + _mesa_printf("START-LIST %u, address %p\n", list, (void*)n ); + + done = n ? GL_FALSE : GL_TRUE; + while (!done) { + OpCode opcode = n[0].opcode; + GLint i = (GLint) n[0].opcode - (GLint) OPCODE_EXT_0; + + if (i >= 0 && i < (GLint) ctx->ListExt.NumOpcodes) { + /* this is a driver-extended opcode */ + ctx->ListExt.Opcode[i].Print(ctx, &n[1]); + n += ctx->ListExt.Opcode[i].Size; + } + else { + switch (opcode) { + case OPCODE_ACCUM: + _mesa_printf("accum %s %g\n", enum_string(n[1].e), n[2].f ); + break; + case OPCODE_BITMAP: + _mesa_printf("Bitmap %d %d %g %g %g %g %p\n", n[1].i, n[2].i, + n[3].f, n[4].f, n[5].f, n[6].f, (void *) n[7].data ); + break; + case OPCODE_CALL_LIST: + _mesa_printf("CallList %d\n", (int) n[1].ui ); + break; + case OPCODE_CALL_LIST_OFFSET: + _mesa_printf("CallList %d + offset %u = %u\n", (int) n[1].ui, + ctx->List.ListBase, ctx->List.ListBase + n[1].ui ); + break; + case OPCODE_COLOR_TABLE_PARAMETER_FV: + _mesa_printf("ColorTableParameterfv %s %s %f %f %f %f\n", + enum_string(n[1].e), enum_string(n[2].e), + n[3].f, n[4].f, n[5].f, n[6].f); + break; + case OPCODE_COLOR_TABLE_PARAMETER_IV: + _mesa_printf("ColorTableParameteriv %s %s %d %d %d %d\n", + enum_string(n[1].e), enum_string(n[2].e), + n[3].i, n[4].i, n[5].i, n[6].i); + break; + case OPCODE_DISABLE: + _mesa_printf("Disable %s\n", enum_string(n[1].e)); + break; + case OPCODE_ENABLE: + _mesa_printf("Enable %s\n", enum_string(n[1].e)); + break; + case OPCODE_FRUSTUM: + _mesa_printf("Frustum %g %g %g %g %g %g\n", + n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f ); + break; + case OPCODE_LINE_STIPPLE: + _mesa_printf("LineStipple %d %x\n", n[1].i, (int) n[2].us ); + break; + case OPCODE_LOAD_IDENTITY: + _mesa_printf("LoadIdentity\n"); + break; + case OPCODE_LOAD_MATRIX: + _mesa_printf("LoadMatrix\n"); + _mesa_printf(" %8f %8f %8f %8f\n", + n[1].f, n[5].f, n[9].f, n[13].f); + _mesa_printf(" %8f %8f %8f %8f\n", + n[2].f, n[6].f, n[10].f, n[14].f); + _mesa_printf(" %8f %8f %8f %8f\n", + n[3].f, n[7].f, n[11].f, n[15].f); + _mesa_printf(" %8f %8f %8f %8f\n", + n[4].f, n[8].f, n[12].f, n[16].f); + break; + case OPCODE_MULT_MATRIX: + _mesa_printf("MultMatrix (or Rotate)\n"); + _mesa_printf(" %8f %8f %8f %8f\n", + n[1].f, n[5].f, n[9].f, n[13].f); + _mesa_printf(" %8f %8f %8f %8f\n", + n[2].f, n[6].f, n[10].f, n[14].f); + _mesa_printf(" %8f %8f %8f %8f\n", + n[3].f, n[7].f, n[11].f, n[15].f); + _mesa_printf(" %8f %8f %8f %8f\n", + n[4].f, n[8].f, n[12].f, n[16].f); + break; + case OPCODE_ORTHO: + _mesa_printf("Ortho %g %g %g %g %g %g\n", + n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f ); + break; + case OPCODE_POP_ATTRIB: + _mesa_printf("PopAttrib\n"); + break; + case OPCODE_POP_MATRIX: + _mesa_printf("PopMatrix\n"); + break; + case OPCODE_POP_NAME: + _mesa_printf("PopName\n"); + break; + case OPCODE_PUSH_ATTRIB: + _mesa_printf("PushAttrib %x\n", n[1].bf ); + break; + case OPCODE_PUSH_MATRIX: + _mesa_printf("PushMatrix\n"); + break; + case OPCODE_PUSH_NAME: + _mesa_printf("PushName %d\n", (int) n[1].ui ); + break; + case OPCODE_RASTER_POS: + _mesa_printf("RasterPos %g %g %g %g\n", + n[1].f, n[2].f,n[3].f,n[4].f); + break; + case OPCODE_ROTATE: + _mesa_printf("Rotate %g %g %g %g\n", + n[1].f, n[2].f, n[3].f, n[4].f ); + break; + case OPCODE_SCALE: + _mesa_printf("Scale %g %g %g\n", n[1].f, n[2].f, n[3].f ); + break; + case OPCODE_TRANSLATE: + _mesa_printf("Translate %g %g %g\n", n[1].f, n[2].f, n[3].f ); + break; + case OPCODE_BIND_TEXTURE: + _mesa_printf("BindTexture %s %d\n", + _mesa_lookup_enum_by_nr(n[1].ui), n[2].ui); + break; + case OPCODE_SHADE_MODEL: + _mesa_printf("ShadeModel %s\n", + _mesa_lookup_enum_by_nr(n[1].ui)); + break; + case OPCODE_MAP1: + _mesa_printf("Map1 %s %.3f %.3f %d %d\n", + _mesa_lookup_enum_by_nr(n[1].ui), + n[2].f, n[3].f, n[4].i, n[5].i); + break; + case OPCODE_MAP2: + _mesa_printf("Map2 %s %.3f %.3f %.3f %.3f %d %d %d %d\n", + _mesa_lookup_enum_by_nr(n[1].ui), + n[2].f, n[3].f, n[4].f, n[5].f, + n[6].i, n[7].i, n[8].i, n[9].i); + break; + case OPCODE_MAPGRID1: + _mesa_printf("MapGrid1 %d %.3f %.3f\n", + n[1].i, n[2].f, n[3].f); + break; + case OPCODE_MAPGRID2: + _mesa_printf("MapGrid2 %d %.3f %.3f, %d %.3f %.3f\n", + n[1].i, n[2].f, n[3].f, + n[4].i, n[5].f, n[6].f); + break; + case OPCODE_EVALMESH1: + _mesa_printf("EvalMesh1 %d %d\n", n[1].i, n[2].i); + break; + case OPCODE_EVALMESH2: + _mesa_printf("EvalMesh2 %d %d %d %d\n", + n[1].i, n[2].i, n[3].i, n[4].i); + break; + + case OPCODE_ATTR_1F_NV: + _mesa_printf("ATTR_1F_NV attr %d: %f\n", + n[1].i, n[2].f); + break; + case OPCODE_ATTR_2F_NV: + _mesa_printf("ATTR_2F_NV attr %d: %f %f\n", + n[1].i, n[2].f, n[3].f); + break; + case OPCODE_ATTR_3F_NV: + _mesa_printf("ATTR_3F_NV attr %d: %f %f %f\n", + n[1].i, n[2].f, n[3].f, n[4].f); + break; + case OPCODE_ATTR_4F_NV: + _mesa_printf("ATTR_4F_NV attr %d: %f %f %f %f\n", + n[1].i, n[2].f, n[3].f, n[4].f, n[5].f); + break; + case OPCODE_ATTR_1F_ARB: + _mesa_printf("ATTR_1F_ARB attr %d: %f\n", + n[1].i, n[2].f); + break; + case OPCODE_ATTR_2F_ARB: + _mesa_printf("ATTR_2F_ARB attr %d: %f %f\n", + n[1].i, n[2].f, n[3].f); + break; + case OPCODE_ATTR_3F_ARB: + _mesa_printf("ATTR_3F_ARB attr %d: %f %f %f\n", + n[1].i, n[2].f, n[3].f, n[4].f); + break; + case OPCODE_ATTR_4F_ARB: + _mesa_printf("ATTR_4F_ARB attr %d: %f %f %f %f\n", + n[1].i, n[2].f, n[3].f, n[4].f, n[5].f); + break; + + case OPCODE_MATERIAL: + _mesa_printf("MATERIAL %x %x: %f %f %f %f\n", + n[1].i, n[2].i, n[3].f, n[4].f, n[5].f, n[6].f); + break; + case OPCODE_INDEX: + _mesa_printf("INDEX: %f\n", n[1].f); + break; + case OPCODE_EDGEFLAG: + _mesa_printf("EDGEFLAG: %d\n", n[1].i); + break; + case OPCODE_BEGIN: + _mesa_printf("BEGIN %x\n", n[1].i); + break; + case OPCODE_END: + _mesa_printf("END\n"); + break; + case OPCODE_RECTF: + _mesa_printf("RECTF %f %f %f %f\n", n[1].f, n[2].f, n[3].f, n[4].f); + break; + case OPCODE_EVAL_C1: + _mesa_printf("EVAL_C1 %f\n", n[1].f); + break; + case OPCODE_EVAL_C2: + _mesa_printf("EVAL_C2 %f %f\n", n[1].f, n[2].f); + break; + case OPCODE_EVAL_P1: + _mesa_printf("EVAL_P1 %d\n", n[1].i); + break; + case OPCODE_EVAL_P2: + _mesa_printf("EVAL_P2 %d %d\n", n[1].i, n[2].i); + break; + + + + /* + * meta opcodes/commands + */ + case OPCODE_ERROR: + _mesa_printf("Error: %s %s\n", + enum_string(n[1].e), (const char *)n[2].data ); + break; + case OPCODE_CONTINUE: + _mesa_printf("DISPLAY-LIST-CONTINUE\n"); + n = (Node *) n[1].next; + break; + case OPCODE_END_OF_LIST: + _mesa_printf("END-LIST %u\n", list); + done = GL_TRUE; + break; + default: + if (opcode < 0 || opcode > OPCODE_END_OF_LIST) { + _mesa_printf("ERROR IN DISPLAY LIST: opcode = %d, address = %p\n", + opcode, (void*) n); + return; + } + else { + _mesa_printf("command %d, %u operands\n", opcode, InstSize[opcode]); + } + } + /* increment n to point to next compiled command */ + if (opcode!=OPCODE_CONTINUE) { + n += InstSize[opcode]; + } + } + } +} + + + +/* + * Clients may call this function to help debug display list problems. + * This function is _ONLY_FOR_DEBUGGING_PURPOSES_. It may be removed, + * changed, or break in the future without notice. + */ +void mesa_print_display_list( GLuint list ) +{ + GET_CURRENT_CONTEXT(ctx); + print_list( ctx, list ); +} + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + + +void _mesa_save_vtxfmt_init( GLvertexformat *vfmt ) +{ + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = save_Begin; + vfmt->CallList = _mesa_save_CallList; + vfmt->CallLists = _mesa_save_CallLists; + vfmt->Color3f = save_Color3f; + vfmt->Color3fv = save_Color3fv; + vfmt->Color4f = save_Color4f; + vfmt->Color4fv = save_Color4fv; + vfmt->EdgeFlag = save_EdgeFlag; + vfmt->EdgeFlagv = save_EdgeFlagv; + vfmt->End = save_End; + vfmt->EvalCoord1f = save_EvalCoord1f; + vfmt->EvalCoord1fv = save_EvalCoord1fv; + vfmt->EvalCoord2f = save_EvalCoord2f; + vfmt->EvalCoord2fv = save_EvalCoord2fv; + vfmt->EvalPoint1 = save_EvalPoint1; + vfmt->EvalPoint2 = save_EvalPoint2; + vfmt->FogCoordfEXT = save_FogCoordfEXT; + vfmt->FogCoordfvEXT = save_FogCoordfvEXT; + vfmt->Indexf = save_Indexf; + vfmt->Indexfv = save_Indexfv; + vfmt->Materialfv = save_Materialfv; + vfmt->MultiTexCoord1fARB = save_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = save_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = save_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = save_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = save_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = save_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = save_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = save_MultiTexCoord4fv; + vfmt->Normal3f = save_Normal3f; + vfmt->Normal3fv = save_Normal3fv; + vfmt->SecondaryColor3fEXT = save_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = save_SecondaryColor3fvEXT; + vfmt->TexCoord1f = save_TexCoord1f; + vfmt->TexCoord1fv = save_TexCoord1fv; + vfmt->TexCoord2f = save_TexCoord2f; + vfmt->TexCoord2fv = save_TexCoord2fv; + vfmt->TexCoord3f = save_TexCoord3f; + vfmt->TexCoord3fv = save_TexCoord3fv; + vfmt->TexCoord4f = save_TexCoord4f; + vfmt->TexCoord4fv = save_TexCoord4fv; + vfmt->Vertex2f = save_Vertex2f; + vfmt->Vertex2fv = save_Vertex2fv; + vfmt->Vertex3f = save_Vertex3f; + vfmt->Vertex3fv = save_Vertex3fv; + vfmt->Vertex4f = save_Vertex4f; + vfmt->Vertex4fv = save_Vertex4fv; + vfmt->VertexAttrib1fNV = save_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = save_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = save_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = save_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = save_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = save_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = save_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = save_VertexAttrib4fvNV; + vfmt->VertexAttrib1fARB = save_VertexAttrib1fARB; + vfmt->VertexAttrib1fvARB = save_VertexAttrib1fvARB; + vfmt->VertexAttrib2fARB = save_VertexAttrib2fARB; + vfmt->VertexAttrib2fvARB = save_VertexAttrib2fvARB; + vfmt->VertexAttrib3fARB = save_VertexAttrib3fARB; + vfmt->VertexAttrib3fvARB = save_VertexAttrib3fvARB; + vfmt->VertexAttrib4fARB = save_VertexAttrib4fARB; + vfmt->VertexAttrib4fvARB = save_VertexAttrib4fvARB; + + vfmt->EvalMesh1 = _mesa_save_EvalMesh1; + vfmt->EvalMesh2 = _mesa_save_EvalMesh2; + vfmt->Rectf = save_Rectf; + + /* The driver is required to implement these as + * 1) They can probably do a better job. + * 2) A lot of new mechanisms would have to be added to this module + * to support it. That code would probably never get used, + * because of (1). + */ +#if 0 + vfmt->DrawArrays = 0; + vfmt->DrawElements = 0; + vfmt->DrawRangeElements = 0; +#endif +} + + + +void _mesa_init_display_list( GLcontext * ctx ) +{ + /* Display list */ + ctx->ListState.CallDepth = 0; + ctx->ExecuteFlag = GL_TRUE; + ctx->CompileFlag = GL_FALSE; + ctx->ListState.CurrentListPtr = NULL; + ctx->ListState.CurrentBlock = NULL; + ctx->ListState.CurrentListNum = 0; + ctx->ListState.CurrentPos = 0; + + /* Display List group */ + ctx->List.ListBase = 0; + + _mesa_save_vtxfmt_init( &ctx->ListState.ListVtxfmt ); +} diff --git a/src/mesa/main/dlist.h b/src/mesa/main/dlist.h new file mode 100644 index 00000000000..1a5b391e760 --- /dev/null +++ b/src/mesa/main/dlist.h @@ -0,0 +1,103 @@ +/** + * \file dlist.h + * Display lists management. + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef DLIST_H +#define DLIST_H + + +#include "mtypes.h" + + +#if _HAVE_FULL_GL + +extern void _mesa_init_lists( void ); + +extern void _mesa_destroy_list( GLcontext *ctx, GLuint list ); + +extern void GLAPIENTRY _mesa_CallList( GLuint list ); + +extern void GLAPIENTRY _mesa_CallLists( GLsizei n, GLenum type, const GLvoid *lists ); + +extern void GLAPIENTRY _mesa_DeleteLists( GLuint list, GLsizei range ); + +extern void GLAPIENTRY _mesa_EndList( void ); + +extern GLuint GLAPIENTRY _mesa_GenLists( GLsizei range ); + +extern GLboolean GLAPIENTRY _mesa_IsList( GLuint list ); + +extern void GLAPIENTRY _mesa_ListBase( GLuint base ); + +extern void GLAPIENTRY _mesa_NewList( GLuint list, GLenum mode ); + +extern void _mesa_init_dlist_table( struct _glapi_table *table ); + +extern void _mesa_save_error( GLcontext *ctx, GLenum error, const char *s ); + +extern void _mesa_compile_error( GLcontext *ctx, GLenum error, const char *s ); + + +extern void *_mesa_alloc_instruction( GLcontext *ctx, int opcode, GLint sz ); + +extern GLint _mesa_alloc_opcode( GLcontext *ctx, GLuint sz, + void (*execute)( GLcontext *, void * ), + void (*destroy)( GLcontext *, void * ), + void (*print)( GLcontext *, void * ) ); + +extern void GLAPIENTRY _mesa_save_EvalMesh2(GLenum mode, GLint i1, GLint i2, + GLint j1, GLint j2 ); +extern void GLAPIENTRY _mesa_save_EvalMesh1( GLenum mode, GLint i1, GLint i2 ); +extern void GLAPIENTRY _mesa_save_CallLists( GLsizei n, GLenum type, const GLvoid *lists ); +extern void GLAPIENTRY _mesa_save_CallList( GLuint list ); +extern void _mesa_init_display_list( GLcontext * ctx ); +extern void _mesa_save_vtxfmt_init( GLvertexformat *vfmt ); + + +#else + +/** No-op */ +#define _mesa_init_lists() ((void)0) + +/** No-op */ +#define _mesa_destroy_list(c,l) ((void)0) + +/** No-op */ +#define _mesa_init_dlist_table(t,ts) ((void)0) + +/** No-op */ +#define _mesa_init_display_list(c) ((void)0) + +/** No-op */ +#define _mesa_save_vtxfmt_init(v) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c new file mode 100644 index 00000000000..4f7e24a1ec4 --- /dev/null +++ b/src/mesa/main/drawpix.c @@ -0,0 +1,317 @@ +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "imports.h" +#include "colormac.h" +#include "context.h" +#include "drawpix.h" +#include "feedback.h" +#include "macros.h" +#include "state.h" +#include "mtypes.h" + + +#if _HAVE_FULL_GL + +/* + * Execute glDrawPixels + */ +void GLAPIENTRY +_mesa_DrawPixels( GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawPixels (invalid fragment program)"); + return; + } + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" ); + return; + } + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glDrawPixels(incomplete framebuffer)" ); + return; + } + + if (!ctx->Current.RasterPosValid) { + return; + } + + if (ctx->RenderMode == GL_RENDER) { + /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ + GLint x = IROUND(ctx->Current.RasterPos[0]); + GLint y = IROUND(ctx->Current.RasterPos[1]); + ctx->OcclusionResult = GL_TRUE; + ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type, + &ctx->Unpack, pixels); + } + else if (ctx->RenderMode == GL_FEEDBACK) { + /* Feedback the current raster pos info */ + FLUSH_CURRENT( ctx, 0 ); + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); + _mesa_feedback_vertex( ctx, + ctx->Current.RasterPos, + ctx->Current.RasterColor, + ctx->Current.RasterIndex, + ctx->Current.RasterTexCoords[0] ); + } + else { + ASSERT(ctx->RenderMode == GL_SELECT); + /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ + } +} + + +void GLAPIENTRY +_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, + GLenum type ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyPixels (invalid fragment program)"); + return; + } + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)" ); + return; + } + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || + ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glCopyPixels(incomplete framebuffer)" ); + return; + } + + if (!ctx->Current.RasterPosValid) { + return; + } + + if (ctx->RenderMode == GL_RENDER) { + /* Round to satisfy conformance tests (matches SGI's OpenGL) */ + GLint destx = IROUND(ctx->Current.RasterPos[0]); + GLint desty = IROUND(ctx->Current.RasterPos[1]); + ctx->OcclusionResult = GL_TRUE; + ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty, + type ); + } + else if (ctx->RenderMode == GL_FEEDBACK) { + FLUSH_CURRENT( ctx, 0 ); + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN ); + _mesa_feedback_vertex( ctx, + ctx->Current.RasterPos, + ctx->Current.RasterColor, + ctx->Current.RasterIndex, + ctx->Current.RasterTexCoords[0] ); + } + else { + ASSERT(ctx->RenderMode == GL_SELECT); + /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ + } +} + +#endif /* _HAVE_FULL_GL */ + + + +void GLAPIENTRY +_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, + "glReadPixels(width=%d height=%d)", width, height ); + return; + } + + if (ctx->NewState) + _mesa_update_state(ctx); + + if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glReadPixels(incomplete framebuffer)" ); + return; + } + + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); + return; + } + + ctx->Driver.ReadPixels(ctx, x, y, width, height, + format, type, &ctx->Pack, pixels); +} + + + +void GLAPIENTRY +_mesa_Bitmap( GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBitmap (invalid fragment program)"); + return; + } + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" ); + return; + } + + if (!ctx->Current.RasterPosValid) { + return; /* do nothing */ + } + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glBitmap(incomplete framebuffer)"); + return; + } + + if (ctx->RenderMode == GL_RENDER) { + /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */ + GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig); + GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig); + ctx->OcclusionResult = GL_TRUE; + ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap ); + } +#if _HAVE_FULL_GL + else if (ctx->RenderMode == GL_FEEDBACK) { + FLUSH_CURRENT(ctx, 0); + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN ); + _mesa_feedback_vertex( ctx, + ctx->Current.RasterPos, + ctx->Current.RasterColor, + ctx->Current.RasterIndex, + ctx->Current.RasterTexCoords[0] ); + } + else { + ASSERT(ctx->RenderMode == GL_SELECT); + /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ + } +#endif + + /* update raster position */ + ctx->Current.RasterPos[0] += xmove; + ctx->Current.RasterPos[1] += ymove; +} + + + +#if 0 /* experimental */ +/* + * Execute glDrawDepthPixelsMESA(). This function accepts both a color + * image and depth (Z) image. Rasterization produces fragments with + * color and Z taken from these images. This function is intended for + * Z-compositing. Normally, this operation requires two glDrawPixels + * calls with stencil testing. + */ +void GLAPIENTRY +_mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height, + GLenum colorFormat, GLenum colorType, + const GLvoid *colors, + GLenum depthType, const GLvoid *depths ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, + "glDrawDepthPixelsMESA(width or height < 0" ); + return; + } + + if (!ctx->Current.RasterPosValid) { + return; + } + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glDrawDepthPixelsMESA(incomplete framebuffer)"); + return; + } + + if (ctx->RenderMode == GL_RENDER) { + /* Round, to satisfy conformance tests (matches SGI's OpenGL) */ + GLint x = IROUND(ctx->Current.RasterPos[0]); + GLint y = IROUND(ctx->Current.RasterPos[1]); + ctx->OcclusionResult = GL_TRUE; + ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height, + colorFormat, colorType, colors, + depthType, depths, &ctx->Unpack); + } + else if (ctx->RenderMode == GL_FEEDBACK) { + /* Feedback the current raster pos info */ + FLUSH_CURRENT( ctx, 0 ); + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN ); + _mesa_feedback_vertex( ctx, + ctx->Current.RasterPos, + ctx->Current.RasterColor, + ctx->Current.RasterIndex, + ctx->Current.RasterTexCoords[0] ); + } + else { + ASSERT(ctx->RenderMode == GL_SELECT); + /* Do nothing. See OpenGL Spec, Appendix B, Corollary 6. */ + } +} + +#endif diff --git a/src/mesa/main/drawpix.h b/src/mesa/main/drawpix.h new file mode 100644 index 00000000000..2a2d7de8d81 --- /dev/null +++ b/src/mesa/main/drawpix.h @@ -0,0 +1,55 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef DRAWPIXELS_H +#define DRAWPIXELS_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_DrawPixels( GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height, + GLenum type ); + + +extern void GLAPIENTRY +_mesa_Bitmap( GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap ); + + +#endif diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c new file mode 100644 index 00000000000..67fd083ca82 --- /dev/null +++ b/src/mesa/main/enable.c @@ -0,0 +1,1456 @@ +/** + * \file enable.c + * Enable/disable/query GL capabilities. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "enable.h" +#include "light.h" +#include "macros.h" +#include "simple_list.h" +#include "mtypes.h" +#include "enums.h" +#include "math/m_matrix.h" +#include "math/m_xform.h" + + + +#define CHECK_EXTENSION(EXTNAME, CAP) \ + if (!ctx->Extensions.EXTNAME) { \ + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(0x%x)", \ + state ? "Enable" : "Disable", CAP); \ + return; \ + } + + +static void +client_state( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + GLuint flag; + GLuint *var; + + switch (cap) { + case GL_VERTEX_ARRAY: + var = &ctx->Array.Vertex.Enabled; + flag = _NEW_ARRAY_VERTEX; + break; + case GL_NORMAL_ARRAY: + var = &ctx->Array.Normal.Enabled; + flag = _NEW_ARRAY_NORMAL; + break; + case GL_COLOR_ARRAY: + var = &ctx->Array.Color.Enabled; + flag = _NEW_ARRAY_COLOR0; + break; + case GL_INDEX_ARRAY: + var = &ctx->Array.Index.Enabled; + flag = _NEW_ARRAY_INDEX; + break; + case GL_TEXTURE_COORD_ARRAY: + var = &ctx->Array.TexCoord[ctx->Array.ActiveTexture].Enabled; + flag = _NEW_ARRAY_TEXCOORD(ctx->Array.ActiveTexture); + break; + case GL_EDGE_FLAG_ARRAY: + var = &ctx->Array.EdgeFlag.Enabled; + flag = _NEW_ARRAY_EDGEFLAG; + break; + case GL_FOG_COORDINATE_ARRAY_EXT: + var = &ctx->Array.FogCoord.Enabled; + flag = _NEW_ARRAY_FOGCOORD; + break; + case GL_SECONDARY_COLOR_ARRAY_EXT: + var = &ctx->Array.SecondaryColor.Enabled; + flag = _NEW_ARRAY_COLOR1; + break; + +#if FEATURE_NV_vertex_program + case GL_VERTEX_ATTRIB_ARRAY0_NV: + case GL_VERTEX_ATTRIB_ARRAY1_NV: + case GL_VERTEX_ATTRIB_ARRAY2_NV: + case GL_VERTEX_ATTRIB_ARRAY3_NV: + case GL_VERTEX_ATTRIB_ARRAY4_NV: + case GL_VERTEX_ATTRIB_ARRAY5_NV: + case GL_VERTEX_ATTRIB_ARRAY6_NV: + case GL_VERTEX_ATTRIB_ARRAY7_NV: + case GL_VERTEX_ATTRIB_ARRAY8_NV: + case GL_VERTEX_ATTRIB_ARRAY9_NV: + case GL_VERTEX_ATTRIB_ARRAY10_NV: + case GL_VERTEX_ATTRIB_ARRAY11_NV: + case GL_VERTEX_ATTRIB_ARRAY12_NV: + case GL_VERTEX_ATTRIB_ARRAY13_NV: + case GL_VERTEX_ATTRIB_ARRAY14_NV: + case GL_VERTEX_ATTRIB_ARRAY15_NV: + CHECK_EXTENSION(NV_vertex_program, cap); + { + GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV; + var = &ctx->Array.VertexAttrib[n].Enabled; + flag = _NEW_ARRAY_ATTRIB(n); + } + break; +#endif /* FEATURE_NV_vertex_program */ + + default: + _mesa_error( ctx, GL_INVALID_ENUM, + "glEnable/DisableClientState(0x%x)", cap); + return; + } + + if (*var == state) + return; + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + ctx->Array.NewState |= flag; + *var = state; + + if (state) + ctx->Array._Enabled |= flag; + else + ctx->Array._Enabled &= ~flag; + + if (ctx->Driver.Enable) { + (*ctx->Driver.Enable)( ctx, cap, state ); + } +} + + +/** + * Enable GL capability. + * + * \param cap capability. + * + * \sa glEnable(). + * + * Get's the current context, assures that we're outside glBegin()/glEnd() and + * calls client_state(). + */ +void GLAPIENTRY +_mesa_EnableClientState( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + client_state( ctx, cap, GL_TRUE ); +} + + +/** + * Disable GL capability. + * + * \param cap capability. + * + * \sa glDisable(). + * + * Get's the current context, assures that we're outside glBegin()/glEnd() and + * calls client_state(). + */ +void GLAPIENTRY +_mesa_DisableClientState( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + client_state( ctx, cap, GL_FALSE ); +} + + +#undef CHECK_EXTENSION +#define CHECK_EXTENSION(EXTNAME, CAP) \ + if (!ctx->Extensions.EXTNAME) { \ + _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)", \ + state ? "Enable" : "Disable", CAP); \ + return; \ + } + +#define CHECK_EXTENSION2(EXT1, EXT2, CAP) \ + if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \ + _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)", \ + state ? "Enable" : "Disable", CAP); \ + return; \ + } + + + +/** + * Perform glEnable() and glDisable() calls. + * + * \param ctx GL context. + * \param cap capability. + * \param state whether to enable or disable the specified capability. + * + * Updates the current context and flushes the vertices as needed. For + * capabilities associated with extensions it verifies that those extensions + * are effectivly present before updating. Notifies the driver via + * dd_function_table::Enable. + */ +void _mesa_set_enable( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "%s %s (newstate is %x)\n", + state ? "glEnable" : "glDisable", + _mesa_lookup_enum_by_nr(cap), + ctx->NewState); + + switch (cap) { + case GL_ALPHA_TEST: + if (ctx->Color.AlphaEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.AlphaEnabled = state; + break; + case GL_AUTO_NORMAL: + if (ctx->Eval.AutoNormal == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.AutoNormal = state; + break; + case GL_BLEND: + if (ctx->Color.BlendEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.BlendEnabled = state; + /* This is needed to support 1.1's RGB logic ops AND + * 1.0's blending logicops. + */ + ctx->Color._LogicOpEnabled = + (ctx->Color.ColorLogicOpEnabled || + (state && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)); + break; +#if FEATURE_userclip + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + { + const GLuint p = cap - GL_CLIP_PLANE0; + + if ((ctx->Transform.ClipPlanesEnabled & (1 << p)) == ((GLuint) state << p)) + return; + + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + + if (state) { + ctx->Transform.ClipPlanesEnabled |= (1 << p); + + if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top)) + _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); + + /* This derived state also calculated in clip.c and + * from _mesa_update_state() on changes to EyeUserPlane + * and ctx->ProjectionMatrix respectively. + */ + _mesa_transform_vector( ctx->Transform._ClipUserPlane[p], + ctx->Transform.EyeUserPlane[p], + ctx->ProjectionMatrixStack.Top->inv ); + } + else { + ctx->Transform.ClipPlanesEnabled &= ~(1 << p); + } + } + break; +#endif + case GL_COLOR_MATERIAL: + if (ctx->Light.ColorMaterialEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + FLUSH_CURRENT(ctx, 0); + ctx->Light.ColorMaterialEnabled = state; + if (state) { + _mesa_update_color_material( ctx, + ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); + } + break; + case GL_CULL_FACE: + if (ctx->Polygon.CullFlag == state) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.CullFlag = state; + break; + + case GL_CULL_VERTEX_EXT: + CHECK_EXTENSION(EXT_cull_vertex, cap); + if (ctx->Transform.CullVertexFlag == state) + return; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + ctx->Transform.CullVertexFlag = state; + break; + + case GL_DEPTH_TEST: + if (state && ctx->DrawBuffer->Visual.depthBits == 0) { + _mesa_warning(ctx,"glEnable(GL_DEPTH_TEST) but no depth buffer"); + return; + } + if (ctx->Depth.Test==state) + return; + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.Test = state; + break; + case GL_DITHER: + if (ctx->NoDither) { + state = GL_FALSE; /* MESA_NO_DITHER env var */ + } + if (ctx->Color.DitherFlag==state) + return; + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.DitherFlag = state; + break; + case GL_FOG: + if (ctx->Fog.Enabled==state) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.Enabled = state; + break; + case GL_HISTOGRAM: + CHECK_EXTENSION(EXT_histogram, cap); + if (ctx->Pixel.HistogramEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.HistogramEnabled = state; + break; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + if (ctx->Light.Light[cap-GL_LIGHT0].Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.Light[cap-GL_LIGHT0].Enabled = state; + if (state) { + insert_at_tail(&ctx->Light.EnabledList, + &ctx->Light.Light[cap-GL_LIGHT0]); + } + else { + remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]); + } + break; + case GL_LIGHTING: + if (ctx->Light.Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.Enabled = state; + + if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) + ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; + else + ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE; + + break; + case GL_LINE_SMOOTH: + if (ctx->Line.SmoothFlag == state) + return; + FLUSH_VERTICES(ctx, _NEW_LINE); + ctx->Line.SmoothFlag = state; + ctx->_TriangleCaps ^= DD_LINE_SMOOTH; + break; + case GL_LINE_STIPPLE: + if (ctx->Line.StippleFlag == state) + return; + FLUSH_VERTICES(ctx, _NEW_LINE); + ctx->Line.StippleFlag = state; + ctx->_TriangleCaps ^= DD_LINE_STIPPLE; + break; + case GL_INDEX_LOGIC_OP: + if (ctx->Color.IndexLogicOpEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.IndexLogicOpEnabled = state; + break; + case GL_COLOR_LOGIC_OP: + if (ctx->Color.ColorLogicOpEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.ColorLogicOpEnabled = state; + /* This is needed to support 1.1's RGB logic ops AND + * 1.0's blending logicops. + */ + ctx->Color._LogicOpEnabled = + (state || (ctx->Color.BlendEnabled && + ctx->Color.BlendEquationRGB == GL_LOGIC_OP)); + break; + case GL_MAP1_COLOR_4: + if (ctx->Eval.Map1Color4 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1Color4 = state; + break; + case GL_MAP1_INDEX: + if (ctx->Eval.Map1Index == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1Index = state; + break; + case GL_MAP1_NORMAL: + if (ctx->Eval.Map1Normal == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1Normal = state; + break; + case GL_MAP1_TEXTURE_COORD_1: + if (ctx->Eval.Map1TextureCoord1 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1TextureCoord1 = state; + break; + case GL_MAP1_TEXTURE_COORD_2: + if (ctx->Eval.Map1TextureCoord2 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1TextureCoord2 = state; + break; + case GL_MAP1_TEXTURE_COORD_3: + if (ctx->Eval.Map1TextureCoord3 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1TextureCoord3 = state; + break; + case GL_MAP1_TEXTURE_COORD_4: + if (ctx->Eval.Map1TextureCoord4 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1TextureCoord4 = state; + break; + case GL_MAP1_VERTEX_3: + if (ctx->Eval.Map1Vertex3 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1Vertex3 = state; + break; + case GL_MAP1_VERTEX_4: + if (ctx->Eval.Map1Vertex4 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1Vertex4 = state; + break; + case GL_MAP2_COLOR_4: + if (ctx->Eval.Map2Color4 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2Color4 = state; + break; + case GL_MAP2_INDEX: + if (ctx->Eval.Map2Index == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2Index = state; + break; + case GL_MAP2_NORMAL: + if (ctx->Eval.Map2Normal == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2Normal = state; + break; + case GL_MAP2_TEXTURE_COORD_1: + if (ctx->Eval.Map2TextureCoord1 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2TextureCoord1 = state; + break; + case GL_MAP2_TEXTURE_COORD_2: + if (ctx->Eval.Map2TextureCoord2 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2TextureCoord2 = state; + break; + case GL_MAP2_TEXTURE_COORD_3: + if (ctx->Eval.Map2TextureCoord3 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2TextureCoord3 = state; + break; + case GL_MAP2_TEXTURE_COORD_4: + if (ctx->Eval.Map2TextureCoord4 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2TextureCoord4 = state; + break; + case GL_MAP2_VERTEX_3: + if (ctx->Eval.Map2Vertex3 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2Vertex3 = state; + break; + case GL_MAP2_VERTEX_4: + if (ctx->Eval.Map2Vertex4 == state) + return; + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2Vertex4 = state; + break; + case GL_MINMAX: + if (ctx->Pixel.MinMaxEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.MinMaxEnabled = state; + break; + case GL_NORMALIZE: + if (ctx->Transform.Normalize == state) + return; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + ctx->Transform.Normalize = state; + break; + case GL_POINT_SMOOTH: + if (ctx->Point.SmoothFlag==state) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.SmoothFlag = state; + ctx->_TriangleCaps ^= DD_POINT_SMOOTH; + break; + case GL_POLYGON_SMOOTH: + if (ctx->Polygon.SmoothFlag==state) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.SmoothFlag = state; + ctx->_TriangleCaps ^= DD_TRI_SMOOTH; + break; + case GL_POLYGON_STIPPLE: + if (ctx->Polygon.StippleFlag==state) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.StippleFlag = state; + ctx->_TriangleCaps ^= DD_TRI_STIPPLE; + break; + case GL_POLYGON_OFFSET_POINT: + if (ctx->Polygon.OffsetPoint==state) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.OffsetPoint = state; + break; + case GL_POLYGON_OFFSET_LINE: + if (ctx->Polygon.OffsetLine==state) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.OffsetLine = state; + break; + case GL_POLYGON_OFFSET_FILL: + /*case GL_POLYGON_OFFSET_EXT:*/ + if (ctx->Polygon.OffsetFill==state) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.OffsetFill = state; + break; + case GL_RESCALE_NORMAL_EXT: + if (ctx->Transform.RescaleNormals == state) + return; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + ctx->Transform.RescaleNormals = state; + break; + case GL_SCISSOR_TEST: + if (ctx->Scissor.Enabled==state) + return; + FLUSH_VERTICES(ctx, _NEW_SCISSOR); + ctx->Scissor.Enabled = state; + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + if (ctx->Texture.SharedPalette == state) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ctx->Texture.SharedPalette = state; + break; + case GL_STENCIL_TEST: + if (state && ctx->DrawBuffer->Visual.stencilBits == 0) { + _mesa_warning(ctx, + "glEnable(GL_STENCIL_TEST) but no stencil buffer"); + return; + } + if (ctx->Stencil.Enabled==state) + return; + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.Enabled = state; + break; + case GL_TEXTURE_1D: { + const GLuint curr = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + GLuint newenabled = texUnit->Enabled & ~TEXTURE_1D_BIT; + if (state) + newenabled |= TEXTURE_1D_BIT; + if (!ctx->DrawBuffer->Visual.rgbMode + || texUnit->Enabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Enabled = newenabled; + break; + } + case GL_TEXTURE_2D: { + const GLuint curr = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + GLuint newenabled = texUnit->Enabled & ~TEXTURE_2D_BIT; + if (state) + newenabled |= TEXTURE_2D_BIT; + if (!ctx->DrawBuffer->Visual.rgbMode + || texUnit->Enabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Enabled = newenabled; + break; + } + case GL_TEXTURE_3D: { + const GLuint curr = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + GLuint newenabled = texUnit->Enabled & ~TEXTURE_3D_BIT; + if (state) + newenabled |= TEXTURE_3D_BIT; + if (!ctx->DrawBuffer->Visual.rgbMode + || texUnit->Enabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Enabled = newenabled; + break; + } + case GL_TEXTURE_GEN_Q: { + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint newenabled = texUnit->TexGenEnabled & ~Q_BIT; + if (state) + newenabled |= Q_BIT; + if (texUnit->TexGenEnabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->TexGenEnabled = newenabled; + break; + } + case GL_TEXTURE_GEN_R: { + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint newenabled = texUnit->TexGenEnabled & ~R_BIT; + if (state) + newenabled |= R_BIT; + if (texUnit->TexGenEnabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->TexGenEnabled = newenabled; + break; + } + case GL_TEXTURE_GEN_S: { + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint newenabled = texUnit->TexGenEnabled & ~S_BIT; + if (state) + newenabled |= S_BIT; + if (texUnit->TexGenEnabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->TexGenEnabled = newenabled; + break; + } + case GL_TEXTURE_GEN_T: { + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint newenabled = texUnit->TexGenEnabled & ~T_BIT; + if (state) + newenabled |= T_BIT; + if (texUnit->TexGenEnabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->TexGenEnabled = newenabled; + break; + } + + /* + * CLIENT STATE!!! + */ + case GL_VERTEX_ARRAY: + case GL_NORMAL_ARRAY: + case GL_COLOR_ARRAY: + case GL_INDEX_ARRAY: + case GL_TEXTURE_COORD_ARRAY: + case GL_EDGE_FLAG_ARRAY: + case GL_FOG_COORDINATE_ARRAY_EXT: + case GL_SECONDARY_COLOR_ARRAY_EXT: + client_state( ctx, cap, state ); + return; + + /* GL_HP_occlusion_test */ + case GL_OCCLUSION_TEST_HP: + CHECK_EXTENSION(HP_occlusion_test, cap); + if (ctx->Depth.OcclusionTest == state) + return; + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.OcclusionTest = state; + if (state) + ctx->OcclusionResult = ctx->OcclusionResultSaved; + else + ctx->OcclusionResultSaved = ctx->OcclusionResult; + break; + + /* GL_SGIS_pixel_texture */ + case GL_PIXEL_TEXTURE_SGIS: + CHECK_EXTENSION(SGIS_pixel_texture, cap); + if (ctx->Pixel.PixelTextureEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PixelTextureEnabled = state; + break; + + /* GL_SGIX_pixel_texture */ + case GL_PIXEL_TEX_GEN_SGIX: + CHECK_EXTENSION(SGIX_pixel_texture, cap); + if (ctx->Pixel.PixelTextureEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PixelTextureEnabled = state; + break; + + /* GL_SGI_color_table */ + case GL_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_color_table, cap); + if (ctx->Pixel.ColorTableEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.ColorTableEnabled = state; + break; + case GL_POST_CONVOLUTION_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_color_table, cap); + if (ctx->Pixel.PostConvolutionColorTableEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionColorTableEnabled = state; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_color_table, cap); + if (ctx->Pixel.PostColorMatrixColorTableEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixColorTableEnabled = state; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_texture_color_table, cap); + if (ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled = state; + break; + + /* GL_EXT_convolution */ + case GL_CONVOLUTION_1D: + CHECK_EXTENSION(EXT_convolution, cap); + if (ctx->Pixel.Convolution1DEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.Convolution1DEnabled = state; + break; + case GL_CONVOLUTION_2D: + CHECK_EXTENSION(EXT_convolution, cap); + if (ctx->Pixel.Convolution2DEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.Convolution2DEnabled = state; + break; + case GL_SEPARABLE_2D: + CHECK_EXTENSION(EXT_convolution, cap); + if (ctx->Pixel.Separable2DEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.Separable2DEnabled = state; + break; + + /* GL_ARB_texture_cube_map */ + case GL_TEXTURE_CUBE_MAP_ARB: + { + const GLuint curr = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + GLuint newenabled = texUnit->Enabled & ~TEXTURE_CUBE_BIT; + CHECK_EXTENSION(ARB_texture_cube_map, cap); + if (state) + newenabled |= TEXTURE_CUBE_BIT; + if (!ctx->DrawBuffer->Visual.rgbMode + || texUnit->Enabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Enabled = newenabled; + } + break; + + /* GL_EXT_secondary_color */ + case GL_COLOR_SUM_EXT: + CHECK_EXTENSION(EXT_secondary_color, cap); + if (ctx->Fog.ColorSumEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.ColorSumEnabled = state; + break; + + /* GL_ARB_multisample */ + case GL_MULTISAMPLE_ARB: + CHECK_EXTENSION(ARB_multisample, cap); + if (ctx->Multisample.Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); + ctx->Multisample.Enabled = state; + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: + CHECK_EXTENSION(ARB_multisample, cap); + if (ctx->Multisample.SampleAlphaToCoverage == state) + return; + FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); + ctx->Multisample.SampleAlphaToCoverage = state; + break; + case GL_SAMPLE_ALPHA_TO_ONE_ARB: + CHECK_EXTENSION(ARB_multisample, cap); + if (ctx->Multisample.SampleAlphaToOne == state) + return; + FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); + ctx->Multisample.SampleAlphaToOne = state; + break; + case GL_SAMPLE_COVERAGE_ARB: + CHECK_EXTENSION(ARB_multisample, cap); + if (ctx->Multisample.SampleCoverage == state) + return; + FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); + ctx->Multisample.SampleCoverage = state; + break; + case GL_SAMPLE_COVERAGE_INVERT_ARB: + CHECK_EXTENSION(ARB_multisample, cap); + if (ctx->Multisample.SampleCoverageInvert == state) + return; + FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); + ctx->Multisample.SampleCoverageInvert = state; + break; + + /* GL_IBM_rasterpos_clip */ + case GL_RASTER_POSITION_UNCLIPPED_IBM: + CHECK_EXTENSION(IBM_rasterpos_clip, cap); + if (ctx->Transform.RasterPositionUnclipped == state) + return; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + ctx->Transform.RasterPositionUnclipped = state; + break; + + /* GL_NV_point_sprite */ + case GL_POINT_SPRITE_NV: + CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite, cap); + if (ctx->Point.PointSprite == state) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.PointSprite = state; + break; + +#if FEATURE_NV_vertex_program + case GL_VERTEX_PROGRAM_NV: + CHECK_EXTENSION2(NV_vertex_program, ARB_vertex_program, cap); + if (ctx->VertexProgram.Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->VertexProgram.Enabled = state; + break; + case GL_VERTEX_PROGRAM_POINT_SIZE_NV: + CHECK_EXTENSION2(NV_vertex_program, ARB_vertex_program, cap); + if (ctx->VertexProgram.PointSizeEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->VertexProgram.PointSizeEnabled = state; + break; + case GL_VERTEX_PROGRAM_TWO_SIDE_NV: + CHECK_EXTENSION2(NV_vertex_program, ARB_vertex_program, cap); + if (ctx->VertexProgram.TwoSideEnabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->VertexProgram.TwoSideEnabled = state; + break; + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION(NV_vertex_program, cap); + { + const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV); + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map1Attrib[map] = state; + } + break; + case GL_MAP2_VERTEX_ATTRIB0_4_NV: + case GL_MAP2_VERTEX_ATTRIB1_4_NV: + case GL_MAP2_VERTEX_ATTRIB2_4_NV: + case GL_MAP2_VERTEX_ATTRIB3_4_NV: + case GL_MAP2_VERTEX_ATTRIB4_4_NV: + case GL_MAP2_VERTEX_ATTRIB5_4_NV: + case GL_MAP2_VERTEX_ATTRIB6_4_NV: + case GL_MAP2_VERTEX_ATTRIB7_4_NV: + case GL_MAP2_VERTEX_ATTRIB8_4_NV: + case GL_MAP2_VERTEX_ATTRIB9_4_NV: + case GL_MAP2_VERTEX_ATTRIB10_4_NV: + case GL_MAP2_VERTEX_ATTRIB11_4_NV: + case GL_MAP2_VERTEX_ATTRIB12_4_NV: + case GL_MAP2_VERTEX_ATTRIB13_4_NV: + case GL_MAP2_VERTEX_ATTRIB14_4_NV: + case GL_MAP2_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION(NV_vertex_program, cap); + { + const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV); + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.Map2Attrib[map] = state; + } + break; +#endif /* FEATURE_NV_vertex_program */ + +#if FEATURE_NV_fragment_program + case GL_FRAGMENT_PROGRAM_NV: + CHECK_EXTENSION(NV_fragment_program, cap); + if (ctx->FragmentProgram.Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->FragmentProgram.Enabled = state; + break; +#endif /* FEATURE_NV_fragment_program */ + + /* GL_NV_texture_rectangle */ + case GL_TEXTURE_RECTANGLE_NV: + CHECK_EXTENSION(NV_texture_rectangle, cap); + { + const GLuint curr = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr]; + GLuint newenabled = texUnit->Enabled & ~TEXTURE_RECT_BIT; + CHECK_EXTENSION(NV_texture_rectangle, cap); + if (state) + newenabled |= TEXTURE_RECT_BIT; + if (!ctx->DrawBuffer->Visual.rgbMode + || texUnit->Enabled == newenabled) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Enabled = newenabled; + } + break; + + /* GL_EXT_stencil_two_side */ + case GL_STENCIL_TEST_TWO_SIDE_EXT: + CHECK_EXTENSION(EXT_stencil_two_side, cap); + if (ctx->Stencil.TestTwoSide == state) + return; + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.TestTwoSide = state; + if (state) { + ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL; + } else { + ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL; + } + break; + +#if FEATURE_ARB_fragment_program + case GL_FRAGMENT_PROGRAM_ARB: + CHECK_EXTENSION(ARB_fragment_program, cap); + if (ctx->FragmentProgram.Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->FragmentProgram.Enabled = state; + break; +#endif /* FEATURE_ARB_fragment_program */ + + /* GL_EXT_depth_bounds_test */ + case GL_DEPTH_BOUNDS_TEST_EXT: + CHECK_EXTENSION(EXT_depth_bounds_test, cap); + if (state && ctx->DrawBuffer->Visual.depthBits == 0) { + _mesa_warning(ctx, + "glEnable(GL_DEPTH_BOUNDS_TEST_EXT) but no depth buffer"); + return; + } + if (ctx->Depth.BoundsTest == state) + return; + FLUSH_VERTICES(ctx, _NEW_DEPTH); + ctx->Depth.BoundsTest = state; + break; + + /* GL_MESA_program_debug */ + case GL_FRAGMENT_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION(MESA_program_debug, cap); + ctx->FragmentProgram.CallbackEnabled = state; + break; + case GL_VERTEX_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION(MESA_program_debug, cap); + ctx->VertexProgram.CallbackEnabled = state; + break; + +#if FEATURE_ATI_fragment_shader + case GL_FRAGMENT_SHADER_ATI: + CHECK_EXTENSION(ATI_fragment_shader, cap); + if (ctx->ATIFragmentShader.Enabled == state) + return; + FLUSH_VERTICES(ctx, _NEW_PROGRAM); + ctx->ATIFragmentShader.Enabled = state; + break; +#endif + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(0x%x)", state ? "glEnable" : "glDisable", cap); + return; + } + + if (ctx->Driver.Enable) { + (*ctx->Driver.Enable)( ctx, cap, state ); + } +} + + +/** + * Enable GL capability. + * + * \param cap capability. + * + * \sa glEnable(). + * + * Get's the current context, assures that we're outside glBegin()/glEnd() and + * calls _mesa_set_enable(). + */ +void GLAPIENTRY +_mesa_Enable( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + _mesa_set_enable( ctx, cap, GL_TRUE ); +} + + +/** + * Disable GL capability. + * + * \param cap capability. + * + * \sa glDisable(). + * + * Get's the current context, assures that we're outside glBegin()/glEnd() and + * calls _mesa_set_enable(). + */ +void GLAPIENTRY +_mesa_Disable( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + _mesa_set_enable( ctx, cap, GL_FALSE ); +} + + +#undef CHECK_EXTENSION +#define CHECK_EXTENSION(EXTNAME) \ + if (!ctx->Extensions.EXTNAME) { \ + _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled"); \ + return GL_FALSE; \ + } + + +/** + * Test whether a capability is enabled. + * + * \param cap capability. + * + * Returns the state of the specified capability from the current GL context. + * For the capabilities associated with extensions verifies that those + * extensions are effectively present before reporting. + */ +GLboolean GLAPIENTRY +_mesa_IsEnabled( GLenum cap ) +{ + GET_CURRENT_CONTEXT(ctx); + switch (cap) { + case GL_ALPHA_TEST: + return ctx->Color.AlphaEnabled; + case GL_AUTO_NORMAL: + return ctx->Eval.AutoNormal; + case GL_BLEND: + return ctx->Color.BlendEnabled; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + return (ctx->Transform.ClipPlanesEnabled >> (cap - GL_CLIP_PLANE0)) & 1; + case GL_COLOR_MATERIAL: + return ctx->Light.ColorMaterialEnabled; + case GL_CULL_FACE: + return ctx->Polygon.CullFlag; + case GL_DEPTH_TEST: + return ctx->Depth.Test; + case GL_DITHER: + return ctx->Color.DitherFlag; + case GL_FOG: + return ctx->Fog.Enabled; + case GL_LIGHTING: + return ctx->Light.Enabled; + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + return ctx->Light.Light[cap-GL_LIGHT0].Enabled; + case GL_LINE_SMOOTH: + return ctx->Line.SmoothFlag; + case GL_LINE_STIPPLE: + return ctx->Line.StippleFlag; + case GL_INDEX_LOGIC_OP: + return ctx->Color.IndexLogicOpEnabled; + case GL_COLOR_LOGIC_OP: + return ctx->Color.ColorLogicOpEnabled; + case GL_MAP1_COLOR_4: + return ctx->Eval.Map1Color4; + case GL_MAP1_INDEX: + return ctx->Eval.Map1Index; + case GL_MAP1_NORMAL: + return ctx->Eval.Map1Normal; + case GL_MAP1_TEXTURE_COORD_1: + return ctx->Eval.Map1TextureCoord1; + case GL_MAP1_TEXTURE_COORD_2: + return ctx->Eval.Map1TextureCoord2; + case GL_MAP1_TEXTURE_COORD_3: + return ctx->Eval.Map1TextureCoord3; + case GL_MAP1_TEXTURE_COORD_4: + return ctx->Eval.Map1TextureCoord4; + case GL_MAP1_VERTEX_3: + return ctx->Eval.Map1Vertex3; + case GL_MAP1_VERTEX_4: + return ctx->Eval.Map1Vertex4; + case GL_MAP2_COLOR_4: + return ctx->Eval.Map2Color4; + case GL_MAP2_INDEX: + return ctx->Eval.Map2Index; + case GL_MAP2_NORMAL: + return ctx->Eval.Map2Normal; + case GL_MAP2_TEXTURE_COORD_1: + return ctx->Eval.Map2TextureCoord1; + case GL_MAP2_TEXTURE_COORD_2: + return ctx->Eval.Map2TextureCoord2; + case GL_MAP2_TEXTURE_COORD_3: + return ctx->Eval.Map2TextureCoord3; + case GL_MAP2_TEXTURE_COORD_4: + return ctx->Eval.Map2TextureCoord4; + case GL_MAP2_VERTEX_3: + return ctx->Eval.Map2Vertex3; + case GL_MAP2_VERTEX_4: + return ctx->Eval.Map2Vertex4; + case GL_NORMALIZE: + return ctx->Transform.Normalize; + case GL_POINT_SMOOTH: + return ctx->Point.SmoothFlag; + case GL_POLYGON_SMOOTH: + return ctx->Polygon.SmoothFlag; + case GL_POLYGON_STIPPLE: + return ctx->Polygon.StippleFlag; + case GL_POLYGON_OFFSET_POINT: + return ctx->Polygon.OffsetPoint; + case GL_POLYGON_OFFSET_LINE: + return ctx->Polygon.OffsetLine; + case GL_POLYGON_OFFSET_FILL: + /*case GL_POLYGON_OFFSET_EXT:*/ + return ctx->Polygon.OffsetFill; + case GL_RESCALE_NORMAL_EXT: + return ctx->Transform.RescaleNormals; + case GL_SCISSOR_TEST: + return ctx->Scissor.Enabled; + case GL_SHARED_TEXTURE_PALETTE_EXT: + return ctx->Texture.SharedPalette; + case GL_STENCIL_TEST: + return ctx->Stencil.Enabled; + case GL_TEXTURE_1D: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE_1D_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_2D: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE_2D_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_3D: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE_3D_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_Q: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_R: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_S: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE; + } + case GL_TEXTURE_GEN_T: + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE; + } + + /* + * CLIENT STATE!!! + */ + case GL_VERTEX_ARRAY: + return (ctx->Array.Vertex.Enabled != 0); + case GL_NORMAL_ARRAY: + return (ctx->Array.Normal.Enabled != 0); + case GL_COLOR_ARRAY: + return (ctx->Array.Color.Enabled != 0); + case GL_INDEX_ARRAY: + return (ctx->Array.Index.Enabled != 0); + case GL_TEXTURE_COORD_ARRAY: + return (ctx->Array.TexCoord[ctx->Array.ActiveTexture].Enabled != 0); + case GL_EDGE_FLAG_ARRAY: + return (ctx->Array.EdgeFlag.Enabled != 0); + case GL_FOG_COORDINATE_ARRAY_EXT: + CHECK_EXTENSION(EXT_fog_coord); + return (ctx->Array.FogCoord.Enabled != 0); + case GL_SECONDARY_COLOR_ARRAY_EXT: + CHECK_EXTENSION(EXT_secondary_color); + return (ctx->Array.SecondaryColor.Enabled != 0); + + /* GL_EXT_histogram */ + case GL_HISTOGRAM: + CHECK_EXTENSION(EXT_histogram); + return ctx->Pixel.HistogramEnabled; + case GL_MINMAX: + CHECK_EXTENSION(EXT_histogram); + return ctx->Pixel.MinMaxEnabled; + + /* GL_HP_occlusion_test */ + case GL_OCCLUSION_TEST_HP: + CHECK_EXTENSION(HP_occlusion_test); + return ctx->Depth.OcclusionTest; + + /* GL_SGIS_pixel_texture */ + case GL_PIXEL_TEXTURE_SGIS: + CHECK_EXTENSION(SGIS_pixel_texture); + return ctx->Pixel.PixelTextureEnabled; + + /* GL_SGIX_pixel_texture */ + case GL_PIXEL_TEX_GEN_SGIX: + CHECK_EXTENSION(SGIX_pixel_texture); + return ctx->Pixel.PixelTextureEnabled; + + /* GL_SGI_color_table */ + case GL_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_color_table); + return ctx->Pixel.ColorTableEnabled; + case GL_POST_CONVOLUTION_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_color_table); + return ctx->Pixel.PostConvolutionColorTableEnabled; + case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_color_table); + return ctx->Pixel.PostColorMatrixColorTableEnabled; + + /* GL_SGI_texture_color_table */ + case GL_TEXTURE_COLOR_TABLE_SGI: + CHECK_EXTENSION(SGI_texture_color_table); + return ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled; + + /* GL_EXT_convolution */ + case GL_CONVOLUTION_1D: + CHECK_EXTENSION(EXT_convolution); + return ctx->Pixel.Convolution1DEnabled; + case GL_CONVOLUTION_2D: + CHECK_EXTENSION(EXT_convolution); + return ctx->Pixel.Convolution2DEnabled; + case GL_SEPARABLE_2D: + CHECK_EXTENSION(EXT_convolution); + return ctx->Pixel.Separable2DEnabled; + + /* GL_ARB_texture_cube_map */ + case GL_TEXTURE_CUBE_MAP_ARB: + CHECK_EXTENSION(ARB_texture_cube_map); + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE_CUBE_BIT) ? GL_TRUE : GL_FALSE; + } + + /* GL_ARB_multisample */ + case GL_MULTISAMPLE_ARB: + CHECK_EXTENSION(ARB_multisample); + return ctx->Multisample.Enabled; + case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: + CHECK_EXTENSION(ARB_multisample); + return ctx->Multisample.SampleAlphaToCoverage; + case GL_SAMPLE_ALPHA_TO_ONE_ARB: + CHECK_EXTENSION(ARB_multisample); + return ctx->Multisample.SampleAlphaToOne; + case GL_SAMPLE_COVERAGE_ARB: + CHECK_EXTENSION(ARB_multisample); + return ctx->Multisample.SampleCoverage; + case GL_SAMPLE_COVERAGE_INVERT_ARB: + CHECK_EXTENSION(ARB_multisample); + return ctx->Multisample.SampleCoverageInvert; + + /* GL_IBM_rasterpos_clip */ + case GL_RASTER_POSITION_UNCLIPPED_IBM: + CHECK_EXTENSION(IBM_rasterpos_clip); + return ctx->Transform.RasterPositionUnclipped; + + /* GL_NV_point_sprite */ + case GL_POINT_SPRITE_NV: + return ctx->Point.PointSprite; + +#if FEATURE_NV_vertex_program + case GL_VERTEX_PROGRAM_NV: + CHECK_EXTENSION(NV_vertex_program); + return ctx->VertexProgram.Enabled; + case GL_VERTEX_PROGRAM_POINT_SIZE_NV: + CHECK_EXTENSION(NV_vertex_program); + return ctx->VertexProgram.PointSizeEnabled; + case GL_VERTEX_PROGRAM_TWO_SIDE_NV: + CHECK_EXTENSION(NV_vertex_program); + return ctx->VertexProgram.TwoSideEnabled; + case GL_VERTEX_ATTRIB_ARRAY0_NV: + case GL_VERTEX_ATTRIB_ARRAY1_NV: + case GL_VERTEX_ATTRIB_ARRAY2_NV: + case GL_VERTEX_ATTRIB_ARRAY3_NV: + case GL_VERTEX_ATTRIB_ARRAY4_NV: + case GL_VERTEX_ATTRIB_ARRAY5_NV: + case GL_VERTEX_ATTRIB_ARRAY6_NV: + case GL_VERTEX_ATTRIB_ARRAY7_NV: + case GL_VERTEX_ATTRIB_ARRAY8_NV: + case GL_VERTEX_ATTRIB_ARRAY9_NV: + case GL_VERTEX_ATTRIB_ARRAY10_NV: + case GL_VERTEX_ATTRIB_ARRAY11_NV: + case GL_VERTEX_ATTRIB_ARRAY12_NV: + case GL_VERTEX_ATTRIB_ARRAY13_NV: + case GL_VERTEX_ATTRIB_ARRAY14_NV: + case GL_VERTEX_ATTRIB_ARRAY15_NV: + CHECK_EXTENSION(NV_vertex_program); + { + GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV; + return (ctx->Array.VertexAttrib[n].Enabled != 0); + } + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION(NV_vertex_program); + { + const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV); + return ctx->Eval.Map1Attrib[map]; + } + case GL_MAP2_VERTEX_ATTRIB0_4_NV: + case GL_MAP2_VERTEX_ATTRIB1_4_NV: + case GL_MAP2_VERTEX_ATTRIB2_4_NV: + case GL_MAP2_VERTEX_ATTRIB3_4_NV: + case GL_MAP2_VERTEX_ATTRIB4_4_NV: + case GL_MAP2_VERTEX_ATTRIB5_4_NV: + case GL_MAP2_VERTEX_ATTRIB6_4_NV: + case GL_MAP2_VERTEX_ATTRIB7_4_NV: + case GL_MAP2_VERTEX_ATTRIB8_4_NV: + case GL_MAP2_VERTEX_ATTRIB9_4_NV: + case GL_MAP2_VERTEX_ATTRIB10_4_NV: + case GL_MAP2_VERTEX_ATTRIB11_4_NV: + case GL_MAP2_VERTEX_ATTRIB12_4_NV: + case GL_MAP2_VERTEX_ATTRIB13_4_NV: + case GL_MAP2_VERTEX_ATTRIB14_4_NV: + case GL_MAP2_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION(NV_vertex_program); + { + const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV); + return ctx->Eval.Map2Attrib[map]; + } +#endif /* FEATURE_NV_vertex_program */ + +#if FEATURE_NV_fragment_program + case GL_FRAGMENT_PROGRAM_NV: + CHECK_EXTENSION(NV_fragment_program); + return ctx->FragmentProgram.Enabled; +#endif /* FEATURE_NV_fragment_program */ + + /* GL_NV_texture_rectangle */ + case GL_TEXTURE_RECTANGLE_NV: + CHECK_EXTENSION(NV_texture_rectangle); + { + const struct gl_texture_unit *texUnit; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + return (texUnit->Enabled & TEXTURE_RECT_BIT) ? GL_TRUE : GL_FALSE; + } + + /* GL_EXT_stencil_two_side */ + case GL_STENCIL_TEST_TWO_SIDE_EXT: + CHECK_EXTENSION(EXT_stencil_two_side); + return ctx->Stencil.TestTwoSide; + +#if FEATURE_ARB_fragment_program + case GL_FRAGMENT_PROGRAM_ARB: + return ctx->FragmentProgram.Enabled; +#endif /* FEATURE_ARB_fragment_program */ + + /* GL_EXT_depth_bounds_test */ + case GL_DEPTH_BOUNDS_TEST_EXT: + CHECK_EXTENSION(EXT_depth_bounds_test); + return ctx->Depth.BoundsTest; + + /* GL_MESA_program_debug */ + case GL_FRAGMENT_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION(MESA_program_debug); + return ctx->FragmentProgram.CallbackEnabled; + case GL_VERTEX_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION(MESA_program_debug); + return ctx->VertexProgram.CallbackEnabled; +#if FEATURE_ATI_fragment_shader + case GL_FRAGMENT_SHADER_ATI: + CHECK_EXTENSION(ATI_fragment_shader); + return ctx->ATIFragmentShader.Enabled; +#endif /* FEATURE_ATI_fragment_shader */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap); + return GL_FALSE; + } +} diff --git a/src/mesa/main/enable.h b/src/mesa/main/enable.h new file mode 100644 index 00000000000..25c90b0275a --- /dev/null +++ b/src/mesa/main/enable.h @@ -0,0 +1,57 @@ +/** + * \file enable.h + * Enable/disable/query GL capabilities. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef ENABLE_H +#define ENABLE_H + + +#include "mtypes.h" + + +extern void +_mesa_set_enable( GLcontext* ctx, GLenum cap, GLboolean state ); + +extern void GLAPIENTRY +_mesa_Disable( GLenum cap ); + +extern void GLAPIENTRY +_mesa_Enable( GLenum cap ); + +extern GLboolean GLAPIENTRY +_mesa_IsEnabled( GLenum cap ); + +extern void GLAPIENTRY +_mesa_EnableClientState( GLenum cap ); + +extern void GLAPIENTRY +_mesa_DisableClientState( GLenum cap ); + + +#endif diff --git a/src/mesa/main/enums.c b/src/mesa/main/enums.c new file mode 100644 index 00000000000..837618cd74a --- /dev/null +++ b/src/mesa/main/enums.c @@ -0,0 +1,4570 @@ +/* DO NOT EDIT - This file generated automatically by gl_enums.py (from Mesa) script */ + +/* + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL, + * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "glheader.h" +#include "enums.h" +#include "imports.h" + +typedef struct { + size_t offset; + int n; +} enum_elt; + +static const char enum_string_table[] = + "GL_2D\0" + "GL_2_BYTES\0" + "GL_3D\0" + "GL_3D_COLOR\0" + "GL_3D_COLOR_TEXTURE\0" + "GL_3_BYTES\0" + "GL_4D_COLOR_TEXTURE\0" + "GL_4_BYTES\0" + "GL_ACCUM\0" + "GL_ACCUM_ALPHA_BITS\0" + "GL_ACCUM_BLUE_BITS\0" + "GL_ACCUM_BUFFER_BIT\0" + "GL_ACCUM_CLEAR_VALUE\0" + "GL_ACCUM_GREEN_BITS\0" + "GL_ACCUM_RED_BITS\0" + "GL_ACTIVE_STENCIL_FACE_EXT\0" + "GL_ACTIVE_TEXTURE\0" + "GL_ACTIVE_TEXTURE_ARB\0" + "GL_ACTIVE_VERTEX_UNITS_ARB\0" + "GL_ADD\0" + "GL_ADD_SIGNED\0" + "GL_ADD_SIGNED_ARB\0" + "GL_ADD_SIGNED_EXT\0" + "GL_ALIASED_LINE_WIDTH_RANGE\0" + "GL_ALIASED_POINT_SIZE_RANGE\0" + "GL_ALL_ATTRIB_BITS\0" + "GL_ALL_CLIENT_ATTRIB_BITS\0" + "GL_ALPHA\0" + "GL_ALPHA12\0" + "GL_ALPHA12_EXT\0" + "GL_ALPHA16\0" + "GL_ALPHA16_EXT\0" + "GL_ALPHA4\0" + "GL_ALPHA4_EXT\0" + "GL_ALPHA8\0" + "GL_ALPHA8_EXT\0" + "GL_ALPHA_BIAS\0" + "GL_ALPHA_BITS\0" + "GL_ALPHA_SCALE\0" + "GL_ALPHA_TEST\0" + "GL_ALPHA_TEST_FUNC\0" + "GL_ALPHA_TEST_REF\0" + "GL_ALWAYS\0" + "GL_AMBIENT\0" + "GL_AMBIENT_AND_DIFFUSE\0" + "GL_AND\0" + "GL_AND_INVERTED\0" + "GL_AND_REVERSE\0" + "GL_ARRAY_BUFFER\0" + "GL_ARRAY_BUFFER_ARB\0" + "GL_ARRAY_BUFFER_BINDING\0" + "GL_ARRAY_BUFFER_BINDING_ARB\0" + "GL_ATTRIB_ARRAY_POINTER_NV\0" + "GL_ATTRIB_ARRAY_SIZE_NV\0" + "GL_ATTRIB_ARRAY_STRIDE_NV\0" + "GL_ATTRIB_ARRAY_TYPE_NV\0" + "GL_ATTRIB_STACK_DEPTH\0" + "GL_AUTO_NORMAL\0" + "GL_AUX0\0" + "GL_AUX1\0" + "GL_AUX2\0" + "GL_AUX3\0" + "GL_AUX_BUFFERS\0" + "GL_BACK\0" + "GL_BACK_LEFT\0" + "GL_BACK_RIGHT\0" + "GL_BGR\0" + "GL_BGRA\0" + "GL_BITMAP\0" + "GL_BITMAP_TOKEN\0" + "GL_BLEND\0" + "GL_BLEND_COLOR\0" + "GL_BLEND_COLOR_EXT\0" + "GL_BLEND_DST\0" + "GL_BLEND_DST_ALPHA\0" + "GL_BLEND_DST_RGB\0" + "GL_BLEND_EQUATION\0" + "GL_BLEND_EQUATION_ALPHA_EXT\0" + "GL_BLEND_EQUATION_EXT\0" + "GL_BLEND_EQUATION_RGB_EXT\0" + "GL_BLEND_SRC\0" + "GL_BLEND_SRC_ALPHA\0" + "GL_BLEND_SRC_RGB\0" + "GL_BLUE\0" + "GL_BLUE_BIAS\0" + "GL_BLUE_BITS\0" + "GL_BLUE_SCALE\0" + "GL_BOOL_ARB\0" + "GL_BOOL_VEC2_ARB\0" + "GL_BOOL_VEC3_ARB\0" + "GL_BOOL_VEC4_ARB\0" + "GL_BUFFER_ACCESS\0" + "GL_BUFFER_ACCESS_ARB\0" + "GL_BUFFER_MAPPED\0" + "GL_BUFFER_MAPPED_ARB\0" + "GL_BUFFER_MAP_POINTER\0" + "GL_BUFFER_MAP_POINTER_ARB\0" + "GL_BUFFER_SIZE\0" + "GL_BUFFER_SIZE_ARB\0" + "GL_BUFFER_USAGE\0" + "GL_BUFFER_USAGE_ARB\0" + "GL_BYTE\0" + "GL_C3F_V3F\0" + "GL_C4F_N3F_V3F\0" + "GL_C4UB_V2F\0" + "GL_C4UB_V3F\0" + "GL_CCW\0" + "GL_CLAMP\0" + "GL_CLAMP_TO_BORDER\0" + "GL_CLAMP_TO_BORDER_ARB\0" + "GL_CLAMP_TO_BORDER_SGIS\0" + "GL_CLAMP_TO_EDGE\0" + "GL_CLAMP_TO_EDGE_SGIS\0" + "GL_CLEAR\0" + "GL_CLIENT_ACTIVE_TEXTURE\0" + "GL_CLIENT_ACTIVE_TEXTURE_ARB\0" + "GL_CLIENT_ALL_ATTRIB_BITS\0" + "GL_CLIENT_ATTRIB_STACK_DEPTH\0" + "GL_CLIENT_PIXEL_STORE_BIT\0" + "GL_CLIENT_VERTEX_ARRAY_BIT\0" + "GL_CLIP_PLANE0\0" + "GL_CLIP_PLANE1\0" + "GL_CLIP_PLANE2\0" + "GL_CLIP_PLANE3\0" + "GL_CLIP_PLANE4\0" + "GL_CLIP_PLANE5\0" + "GL_CLIP_VOLUME_CLIPPING_HINT_EXT\0" + "GL_COEFF\0" + "GL_COLOR\0" + "GL_COLOR_ARRAY\0" + "GL_COLOR_ARRAY_BUFFER_BINDING\0" + "GL_COLOR_ARRAY_BUFFER_BINDING_ARB\0" + "GL_COLOR_ARRAY_POINTER\0" + "GL_COLOR_ARRAY_SIZE\0" + "GL_COLOR_ARRAY_STRIDE\0" + "GL_COLOR_ARRAY_TYPE\0" + "GL_COLOR_ATTACHMENT0_EXT\0" + "GL_COLOR_ATTACHMENT10_EXT\0" + "GL_COLOR_ATTACHMENT11_EXT\0" + "GL_COLOR_ATTACHMENT12_EXT\0" + "GL_COLOR_ATTACHMENT13_EXT\0" + "GL_COLOR_ATTACHMENT14_EXT\0" + "GL_COLOR_ATTACHMENT15_EXT\0" + "GL_COLOR_ATTACHMENT1_EXT\0" + "GL_COLOR_ATTACHMENT2_EXT\0" + "GL_COLOR_ATTACHMENT3_EXT\0" + "GL_COLOR_ATTACHMENT4_EXT\0" + "GL_COLOR_ATTACHMENT5_EXT\0" + "GL_COLOR_ATTACHMENT6_EXT\0" + "GL_COLOR_ATTACHMENT7_EXT\0" + "GL_COLOR_ATTACHMENT8_EXT\0" + "GL_COLOR_ATTACHMENT9_EXT\0" + "GL_COLOR_BUFFER_BIT\0" + "GL_COLOR_CLEAR_VALUE\0" + "GL_COLOR_INDEX\0" + "GL_COLOR_INDEXES\0" + "GL_COLOR_LOGIC_OP\0" + "GL_COLOR_MATERIAL\0" + "GL_COLOR_MATERIAL_FACE\0" + "GL_COLOR_MATERIAL_PARAMETER\0" + "GL_COLOR_MATRIX\0" + "GL_COLOR_MATRIX_SGI\0" + "GL_COLOR_MATRIX_STACK_DEPTH\0" + "GL_COLOR_MATRIX_STACK_DEPTH_SGI\0" + "GL_COLOR_SUM\0" + "GL_COLOR_SUM_ARB\0" + "GL_COLOR_TABLE\0" + "GL_COLOR_TABLE_ALPHA_SIZE\0" + "GL_COLOR_TABLE_ALPHA_SIZE_EXT\0" + "GL_COLOR_TABLE_BIAS\0" + "GL_COLOR_TABLE_BLUE_SIZE\0" + "GL_COLOR_TABLE_BLUE_SIZE_EXT\0" + "GL_COLOR_TABLE_FORMAT\0" + "GL_COLOR_TABLE_FORMAT_EXT\0" + "GL_COLOR_TABLE_GREEN_SIZE\0" + "GL_COLOR_TABLE_GREEN_SIZE_EXT\0" + "GL_COLOR_TABLE_INTENSITY_SIZE\0" + "GL_COLOR_TABLE_INTENSITY_SIZE_EXT\0" + "GL_COLOR_TABLE_LUMINANCE_SIZE\0" + "GL_COLOR_TABLE_LUMINANCE_SIZE_EXT\0" + "GL_COLOR_TABLE_RED_SIZE\0" + "GL_COLOR_TABLE_RED_SIZE_EXT\0" + "GL_COLOR_TABLE_SCALE\0" + "GL_COLOR_TABLE_WIDTH\0" + "GL_COLOR_TABLE_WIDTH_EXT\0" + "GL_COLOR_WRITEMASK\0" + "GL_COMBINE\0" + "GL_COMBINE4\0" + "GL_COMBINE_ALPHA\0" + "GL_COMBINE_ALPHA_ARB\0" + "GL_COMBINE_ALPHA_EXT\0" + "GL_COMBINE_ARB\0" + "GL_COMBINE_EXT\0" + "GL_COMBINE_RGB\0" + "GL_COMBINE_RGB_ARB\0" + "GL_COMBINE_RGB_EXT\0" + "GL_COMPARE_R_TO_TEXTURE\0" + "GL_COMPARE_R_TO_TEXTURE_ARB\0" + "GL_COMPILE\0" + "GL_COMPILE_AND_EXECUTE\0" + "GL_COMPRESSED_ALPHA\0" + "GL_COMPRESSED_ALPHA_ARB\0" + "GL_COMPRESSED_INTENSITY\0" + "GL_COMPRESSED_INTENSITY_ARB\0" + "GL_COMPRESSED_LUMINANCE\0" + "GL_COMPRESSED_LUMINANCE_ALPHA\0" + "GL_COMPRESSED_LUMINANCE_ALPHA_ARB\0" + "GL_COMPRESSED_LUMINANCE_ARB\0" + "GL_COMPRESSED_RGB\0" + "GL_COMPRESSED_RGBA\0" + "GL_COMPRESSED_RGBA_ARB\0" + "GL_COMPRESSED_RGBA_FXT1_3DFX\0" + "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT\0" + "GL_COMPRESSED_RGBA_S3TC_DXT3_EXT\0" + "GL_COMPRESSED_RGBA_S3TC_DXT5_EXT\0" + "GL_COMPRESSED_RGB_ARB\0" + "GL_COMPRESSED_RGB_FXT1_3DFX\0" + "GL_COMPRESSED_RGB_S3TC_DXT1_EXT\0" + "GL_COMPRESSED_TEXTURE_FORMATS\0" + "GL_CONSTANT\0" + "GL_CONSTANT_ALPHA\0" + "GL_CONSTANT_ALPHA_EXT\0" + "GL_CONSTANT_ARB\0" + "GL_CONSTANT_ATTENUATION\0" + "GL_CONSTANT_BORDER_HP\0" + "GL_CONSTANT_COLOR\0" + "GL_CONSTANT_COLOR_EXT\0" + "GL_CONSTANT_EXT\0" + "GL_CONVOLUTION_1D\0" + "GL_CONVOLUTION_2D\0" + "GL_CONVOLUTION_BORDER_COLOR\0" + "GL_CONVOLUTION_BORDER_COLOR_HP\0" + "GL_CONVOLUTION_BORDER_MODE\0" + "GL_CONVOLUTION_BORDER_MODE_EXT\0" + "GL_CONVOLUTION_FILTER_BIAS\0" + "GL_CONVOLUTION_FILTER_BIAS_EXT\0" + "GL_CONVOLUTION_FILTER_SCALE\0" + "GL_CONVOLUTION_FILTER_SCALE_EXT\0" + "GL_CONVOLUTION_FORMAT\0" + "GL_CONVOLUTION_FORMAT_EXT\0" + "GL_CONVOLUTION_HEIGHT\0" + "GL_CONVOLUTION_HEIGHT_EXT\0" + "GL_CONVOLUTION_WIDTH\0" + "GL_CONVOLUTION_WIDTH_EXT\0" + "GL_COORD_REPLACE_ARB\0" + "GL_COORD_REPLACE_NV\0" + "GL_COPY\0" + "GL_COPY_INVERTED\0" + "GL_COPY_PIXEL_TOKEN\0" + "GL_CULL_FACE\0" + "GL_CULL_FACE_MODE\0" + "GL_CULL_VERTEX_EXT\0" + "GL_CULL_VERTEX_EYE_POSITION_EXT\0" + "GL_CULL_VERTEX_OBJECT_POSITION_EXT\0" + "GL_CURRENT_ATTRIB_NV\0" + "GL_CURRENT_BIT\0" + "GL_CURRENT_COLOR\0" + "GL_CURRENT_FOG_COORD\0" + "GL_CURRENT_FOG_COORDINATE\0" + "GL_CURRENT_INDEX\0" + "GL_CURRENT_MATRIX_ARB\0" + "GL_CURRENT_MATRIX_INDEX_ARB\0" + "GL_CURRENT_MATRIX_NV\0" + "GL_CURRENT_MATRIX_STACK_DEPTH_ARB\0" + "GL_CURRENT_MATRIX_STACK_DEPTH_NV\0" + "GL_CURRENT_NORMAL\0" + "GL_CURRENT_PALETTE_MATRIX_ARB\0" + "GL_CURRENT_QUERY\0" + "GL_CURRENT_QUERY_ARB\0" + "GL_CURRENT_RASTER_COLOR\0" + "GL_CURRENT_RASTER_DISTANCE\0" + "GL_CURRENT_RASTER_INDEX\0" + "GL_CURRENT_RASTER_POSITION\0" + "GL_CURRENT_RASTER_POSITION_VALID\0" + "GL_CURRENT_RASTER_TEXTURE_COORDS\0" + "GL_CURRENT_SECONDARY_COLOR\0" + "GL_CURRENT_TEXTURE_COORDS\0" + "GL_CURRENT_VERTEX_ATTRIB_ARB\0" + "GL_CURRENT_WEIGHT_ARB\0" + "GL_CW\0" + "GL_DECAL\0" + "GL_DECR\0" + "GL_DECR_WRAP\0" + "GL_DECR_WRAP_EXT\0" + "GL_DEPTH\0" + "GL_DEPTH_ATTACHMENT_EXT\0" + "GL_DEPTH_BIAS\0" + "GL_DEPTH_BITS\0" + "GL_DEPTH_BOUNDS_EXT\0" + "GL_DEPTH_BOUNDS_TEST_EXT\0" + "GL_DEPTH_BUFFER_BIT\0" + "GL_DEPTH_CLAMP_NV\0" + "GL_DEPTH_CLEAR_VALUE\0" + "GL_DEPTH_COMPONENT\0" + "GL_DEPTH_COMPONENT16\0" + "GL_DEPTH_COMPONENT16_ARB\0" + "GL_DEPTH_COMPONENT16_SGIX\0" + "GL_DEPTH_COMPONENT24\0" + "GL_DEPTH_COMPONENT24_ARB\0" + "GL_DEPTH_COMPONENT24_SGIX\0" + "GL_DEPTH_COMPONENT32\0" + "GL_DEPTH_COMPONENT32_ARB\0" + "GL_DEPTH_COMPONENT32_SGIX\0" + "GL_DEPTH_FUNC\0" + "GL_DEPTH_RANGE\0" + "GL_DEPTH_SCALE\0" + "GL_DEPTH_STENCIL_NV\0" + "GL_DEPTH_STENCIL_TO_BGRA_NV\0" + "GL_DEPTH_STENCIL_TO_RGBA_NV\0" + "GL_DEPTH_TEST\0" + "GL_DEPTH_TEXTURE_MODE\0" + "GL_DEPTH_TEXTURE_MODE_ARB\0" + "GL_DEPTH_WRITEMASK\0" + "GL_DIFFUSE\0" + "GL_DITHER\0" + "GL_DOMAIN\0" + "GL_DONT_CARE\0" + "GL_DOT3_RGB\0" + "GL_DOT3_RGBA\0" + "GL_DOT3_RGBA_ARB\0" + "GL_DOT3_RGBA_EXT\0" + "GL_DOT3_RGB_ARB\0" + "GL_DOT3_RGB_EXT\0" + "GL_DOUBLE\0" + "GL_DOUBLEBUFFER\0" + "GL_DRAW_BUFFER\0" + "GL_DRAW_BUFFER0_ARB\0" + "GL_DRAW_BUFFER0_ATI\0" + "GL_DRAW_BUFFER10_ARB\0" + "GL_DRAW_BUFFER10_ATI\0" + "GL_DRAW_BUFFER11_ARB\0" + "GL_DRAW_BUFFER11_ATI\0" + "GL_DRAW_BUFFER12_ARB\0" + "GL_DRAW_BUFFER12_ATI\0" + "GL_DRAW_BUFFER13_ARB\0" + "GL_DRAW_BUFFER13_ATI\0" + "GL_DRAW_BUFFER14_ARB\0" + "GL_DRAW_BUFFER14_ATI\0" + "GL_DRAW_BUFFER15_ARB\0" + "GL_DRAW_BUFFER15_ATI\0" + "GL_DRAW_BUFFER1_ARB\0" + "GL_DRAW_BUFFER1_ATI\0" + "GL_DRAW_BUFFER2_ARB\0" + "GL_DRAW_BUFFER2_ATI\0" + "GL_DRAW_BUFFER3_ARB\0" + "GL_DRAW_BUFFER3_ATI\0" + "GL_DRAW_BUFFER4_ARB\0" + "GL_DRAW_BUFFER4_ATI\0" + "GL_DRAW_BUFFER5_ARB\0" + "GL_DRAW_BUFFER5_ATI\0" + "GL_DRAW_BUFFER6_ARB\0" + "GL_DRAW_BUFFER6_ATI\0" + "GL_DRAW_BUFFER7_ARB\0" + "GL_DRAW_BUFFER7_ATI\0" + "GL_DRAW_BUFFER8_ARB\0" + "GL_DRAW_BUFFER8_ATI\0" + "GL_DRAW_BUFFER9_ARB\0" + "GL_DRAW_BUFFER9_ATI\0" + "GL_DRAW_PIXEL_TOKEN\0" + "GL_DST_ALPHA\0" + "GL_DST_COLOR\0" + "GL_DYNAMIC_COPY\0" + "GL_DYNAMIC_COPY_ARB\0" + "GL_DYNAMIC_DRAW\0" + "GL_DYNAMIC_DRAW_ARB\0" + "GL_DYNAMIC_READ\0" + "GL_DYNAMIC_READ_ARB\0" + "GL_EDGE_FLAG\0" + "GL_EDGE_FLAG_ARRAY\0" + "GL_EDGE_FLAG_ARRAY_BUFFER_BINDING\0" + "GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB\0" + "GL_EDGE_FLAG_ARRAY_POINTER\0" + "GL_EDGE_FLAG_ARRAY_STRIDE\0" + "GL_ELEMENT_ARRAY_BUFFER\0" + "GL_ELEMENT_ARRAY_BUFFER_ARB\0" + "GL_ELEMENT_ARRAY_BUFFER_BINDING\0" + "GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB\0" + "GL_EMISSION\0" + "GL_ENABLE_BIT\0" + "GL_EQUAL\0" + "GL_EQUIV\0" + "GL_EVAL_BIT\0" + "GL_EXP\0" + "GL_EXP2\0" + "GL_EXTENSIONS\0" + "GL_EYE_LINEAR\0" + "GL_EYE_PLANE\0" + "GL_EYE_PLANE_ABSOLUTE_NV\0" + "GL_EYE_RADIAL_NV\0" + "GL_FALSE\0" + "GL_FASTEST\0" + "GL_FEEDBACK\0" + "GL_FEEDBACK_BUFFER_POINTER\0" + "GL_FEEDBACK_BUFFER_SIZE\0" + "GL_FEEDBACK_BUFFER_TYPE\0" + "GL_FILL\0" + "GL_FLAT\0" + "GL_FLOAT\0" + "GL_FLOAT_MAT2_ARB\0" + "GL_FLOAT_MAT3_ARB\0" + "GL_FLOAT_MAT4_ARB\0" + "GL_FLOAT_VEC2_ARB\0" + "GL_FLOAT_VEC3_ARB\0" + "GL_FLOAT_VEC4_ARB\0" + "GL_FOG\0" + "GL_FOG_BIT\0" + "GL_FOG_COLOR\0" + "GL_FOG_COORD\0" + "GL_FOG_COORDINATE\0" + "GL_FOG_COORDINATE_ARRAY\0" + "GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING\0" + "GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB\0" + "GL_FOG_COORDINATE_ARRAY_POINTER\0" + "GL_FOG_COORDINATE_ARRAY_STRIDE\0" + "GL_FOG_COORDINATE_ARRAY_TYPE\0" + "GL_FOG_COORDINATE_SOURCE\0" + "GL_FOG_COORD_ARRAY\0" + "GL_FOG_COORD_ARRAY_BUFFER_BINDING\0" + "GL_FOG_COORD_ARRAY_POINTER\0" + "GL_FOG_COORD_ARRAY_STRIDE\0" + "GL_FOG_COORD_ARRAY_TYPE\0" + "GL_FOG_COORD_SOURCE\0" + "GL_FOG_DENSITY\0" + "GL_FOG_DISTANCE_MODE_NV\0" + "GL_FOG_END\0" + "GL_FOG_HINT\0" + "GL_FOG_INDEX\0" + "GL_FOG_MODE\0" + "GL_FOG_OFFSET_SGIX\0" + "GL_FOG_OFFSET_VALUE_SGIX\0" + "GL_FOG_START\0" + "GL_FRAGMENT_DEPTH\0" + "GL_FRAGMENT_PROGRAM_ARB\0" + "GL_FRAGMENT_SHADER_ARB\0" + "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT\0" + "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT\0" + "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT\0" + "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT\0" + "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT\0" + "GL_FRAMEBUFFER_BINDING_EXT\0" + "GL_FRAMEBUFFER_COMPLETE_EXT\0" + "GL_FRAMEBUFFER_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\0" + "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\0" + "GL_FRAMEBUFFER_STATUS_ERROR_EXT\0" + "GL_FRAMEBUFFER_UNSUPPORTED_EXT\0" + "GL_FRONT\0" + "GL_FRONT_AND_BACK\0" + "GL_FRONT_FACE\0" + "GL_FRONT_LEFT\0" + "GL_FRONT_RIGHT\0" + "GL_FUNC_ADD\0" + "GL_FUNC_ADD_EXT\0" + "GL_FUNC_REVERSE_SUBTRACT\0" + "GL_FUNC_REVERSE_SUBTRACT_EXT\0" + "GL_FUNC_SUBTRACT\0" + "GL_FUNC_SUBTRACT_EXT\0" + "GL_GENERATE_MIPMAP\0" + "GL_GENERATE_MIPMAP_HINT\0" + "GL_GENERATE_MIPMAP_HINT_SGIS\0" + "GL_GENERATE_MIPMAP_SGIS\0" + "GL_GEQUAL\0" + "GL_GREATER\0" + "GL_GREEN\0" + "GL_GREEN_BIAS\0" + "GL_GREEN_BITS\0" + "GL_GREEN_SCALE\0" + "GL_HINT_BIT\0" + "GL_HISTOGRAM\0" + "GL_HISTOGRAM_ALPHA_SIZE\0" + "GL_HISTOGRAM_ALPHA_SIZE_EXT\0" + "GL_HISTOGRAM_BLUE_SIZE\0" + "GL_HISTOGRAM_BLUE_SIZE_EXT\0" + "GL_HISTOGRAM_EXT\0" + "GL_HISTOGRAM_FORMAT\0" + "GL_HISTOGRAM_FORMAT_EXT\0" + "GL_HISTOGRAM_GREEN_SIZE\0" + "GL_HISTOGRAM_GREEN_SIZE_EXT\0" + "GL_HISTOGRAM_LUMINANCE_SIZE\0" + "GL_HISTOGRAM_LUMINANCE_SIZE_EXT\0" + "GL_HISTOGRAM_RED_SIZE\0" + "GL_HISTOGRAM_RED_SIZE_EXT\0" + "GL_HISTOGRAM_SINK\0" + "GL_HISTOGRAM_SINK_EXT\0" + "GL_HISTOGRAM_WIDTH\0" + "GL_HISTOGRAM_WIDTH_EXT\0" + "GL_IDENTITY_NV\0" + "GL_IGNORE_BORDER_HP\0" + "GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES\0" + "GL_IMPLEMENTATION_COLOR_READ_TYPE_OES\0" + "GL_INCR\0" + "GL_INCR_WRAP\0" + "GL_INCR_WRAP_EXT\0" + "GL_INDEX_ARRAY\0" + "GL_INDEX_ARRAY_BUFFER_BINDING\0" + "GL_INDEX_ARRAY_BUFFER_BINDING_ARB\0" + "GL_INDEX_ARRAY_POINTER\0" + "GL_INDEX_ARRAY_STRIDE\0" + "GL_INDEX_ARRAY_TYPE\0" + "GL_INDEX_BITS\0" + "GL_INDEX_CLEAR_VALUE\0" + "GL_INDEX_LOGIC_OP\0" + "GL_INDEX_MODE\0" + "GL_INDEX_OFFSET\0" + "GL_INDEX_SHIFT\0" + "GL_INDEX_WRITEMASK\0" + "GL_INT\0" + "GL_INTENSITY\0" + "GL_INTENSITY12\0" + "GL_INTENSITY12_EXT\0" + "GL_INTENSITY16\0" + "GL_INTENSITY16_EXT\0" + "GL_INTENSITY4\0" + "GL_INTENSITY4_EXT\0" + "GL_INTENSITY8\0" + "GL_INTENSITY8_EXT\0" + "GL_INTENSITY_EXT\0" + "GL_INTERPOLATE\0" + "GL_INTERPOLATE_ARB\0" + "GL_INTERPOLATE_EXT\0" + "GL_INT_VEC2_ARB\0" + "GL_INT_VEC3_ARB\0" + "GL_INT_VEC4_ARB\0" + "GL_INVALID_ENUM\0" + "GL_INVALID_FRAMEBUFFER_OPERATION_EXT\0" + "GL_INVALID_OPERATION\0" + "GL_INVALID_VALUE\0" + "GL_INVERSE_NV\0" + "GL_INVERSE_TRANSPOSE_NV\0" + "GL_INVERT\0" + "GL_KEEP\0" + "GL_LEFT\0" + "GL_LEQUAL\0" + "GL_LESS\0" + "GL_LIGHT0\0" + "GL_LIGHT1\0" + "GL_LIGHT2\0" + "GL_LIGHT3\0" + "GL_LIGHT4\0" + "GL_LIGHT5\0" + "GL_LIGHT6\0" + "GL_LIGHT7\0" + "GL_LIGHTING\0" + "GL_LIGHTING_BIT\0" + "GL_LIGHT_MODEL_AMBIENT\0" + "GL_LIGHT_MODEL_COLOR_CONTROL\0" + "GL_LIGHT_MODEL_COLOR_CONTROL_EXT\0" + "GL_LIGHT_MODEL_LOCAL_VIEWER\0" + "GL_LIGHT_MODEL_TWO_SIDE\0" + "GL_LINE\0" + "GL_LINEAR\0" + "GL_LINEAR_ATTENUATION\0" + "GL_LINEAR_CLIPMAP_LINEAR_SGIX\0" + "GL_LINEAR_CLIPMAP_NEAREST_SGIX\0" + "GL_LINEAR_MIPMAP_LINEAR\0" + "GL_LINEAR_MIPMAP_NEAREST\0" + "GL_LINES\0" + "GL_LINE_BIT\0" + "GL_LINE_LOOP\0" + "GL_LINE_RESET_TOKEN\0" + "GL_LINE_SMOOTH\0" + "GL_LINE_SMOOTH_HINT\0" + "GL_LINE_STIPPLE\0" + "GL_LINE_STIPPLE_PATTERN\0" + "GL_LINE_STIPPLE_REPEAT\0" + "GL_LINE_STRIP\0" + "GL_LINE_TOKEN\0" + "GL_LINE_WIDTH\0" + "GL_LINE_WIDTH_GRANULARITY\0" + "GL_LINE_WIDTH_RANGE\0" + "GL_LIST_BASE\0" + "GL_LIST_BIT\0" + "GL_LIST_INDEX\0" + "GL_LIST_MODE\0" + "GL_LOAD\0" + "GL_LOGIC_OP\0" + "GL_LOGIC_OP_MODE\0" + "GL_LUMINANCE\0" + "GL_LUMINANCE12\0" + "GL_LUMINANCE12_ALPHA12\0" + "GL_LUMINANCE12_ALPHA12_EXT\0" + "GL_LUMINANCE12_ALPHA4\0" + "GL_LUMINANCE12_ALPHA4_EXT\0" + "GL_LUMINANCE12_EXT\0" + "GL_LUMINANCE16\0" + "GL_LUMINANCE16_ALPHA16\0" + "GL_LUMINANCE16_ALPHA16_EXT\0" + "GL_LUMINANCE16_EXT\0" + "GL_LUMINANCE4\0" + "GL_LUMINANCE4_ALPHA4\0" + "GL_LUMINANCE4_ALPHA4_EXT\0" + "GL_LUMINANCE4_EXT\0" + "GL_LUMINANCE6_ALPHA2\0" + "GL_LUMINANCE6_ALPHA2_EXT\0" + "GL_LUMINANCE8\0" + "GL_LUMINANCE8_ALPHA8\0" + "GL_LUMINANCE8_ALPHA8_EXT\0" + "GL_LUMINANCE8_EXT\0" + "GL_LUMINANCE_ALPHA\0" + "GL_MAP1_COLOR_4\0" + "GL_MAP1_GRID_DOMAIN\0" + "GL_MAP1_GRID_SEGMENTS\0" + "GL_MAP1_INDEX\0" + "GL_MAP1_NORMAL\0" + "GL_MAP1_TEXTURE_COORD_1\0" + "GL_MAP1_TEXTURE_COORD_2\0" + "GL_MAP1_TEXTURE_COORD_3\0" + "GL_MAP1_TEXTURE_COORD_4\0" + "GL_MAP1_VERTEX_3\0" + "GL_MAP1_VERTEX_4\0" + "GL_MAP1_VERTEX_ATTRIB0_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB10_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB11_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB12_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB13_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB14_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB15_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB1_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB2_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB3_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB4_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB5_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB6_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB7_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB8_4_NV\0" + "GL_MAP1_VERTEX_ATTRIB9_4_NV\0" + "GL_MAP2_COLOR_4\0" + "GL_MAP2_GRID_DOMAIN\0" + "GL_MAP2_GRID_SEGMENTS\0" + "GL_MAP2_INDEX\0" + "GL_MAP2_NORMAL\0" + "GL_MAP2_TEXTURE_COORD_1\0" + "GL_MAP2_TEXTURE_COORD_2\0" + "GL_MAP2_TEXTURE_COORD_3\0" + "GL_MAP2_TEXTURE_COORD_4\0" + "GL_MAP2_VERTEX_3\0" + "GL_MAP2_VERTEX_4\0" + "GL_MAP2_VERTEX_ATTRIB0_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB10_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB11_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB12_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB13_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB14_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB15_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB1_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB2_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB3_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB4_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB5_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB6_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB7_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB8_4_NV\0" + "GL_MAP2_VERTEX_ATTRIB9_4_NV\0" + "GL_MAP_COLOR\0" + "GL_MAP_STENCIL\0" + "GL_MATRIX0_ARB\0" + "GL_MATRIX0_NV\0" + "GL_MATRIX10_ARB\0" + "GL_MATRIX11_ARB\0" + "GL_MATRIX12_ARB\0" + "GL_MATRIX13_ARB\0" + "GL_MATRIX14_ARB\0" + "GL_MATRIX15_ARB\0" + "GL_MATRIX16_ARB\0" + "GL_MATRIX17_ARB\0" + "GL_MATRIX18_ARB\0" + "GL_MATRIX19_ARB\0" + "GL_MATRIX1_ARB\0" + "GL_MATRIX1_NV\0" + "GL_MATRIX20_ARB\0" + "GL_MATRIX21_ARB\0" + "GL_MATRIX22_ARB\0" + "GL_MATRIX23_ARB\0" + "GL_MATRIX24_ARB\0" + "GL_MATRIX25_ARB\0" + "GL_MATRIX26_ARB\0" + "GL_MATRIX27_ARB\0" + "GL_MATRIX28_ARB\0" + "GL_MATRIX29_ARB\0" + "GL_MATRIX2_ARB\0" + "GL_MATRIX2_NV\0" + "GL_MATRIX30_ARB\0" + "GL_MATRIX31_ARB\0" + "GL_MATRIX3_ARB\0" + "GL_MATRIX3_NV\0" + "GL_MATRIX4_ARB\0" + "GL_MATRIX4_NV\0" + "GL_MATRIX5_ARB\0" + "GL_MATRIX5_NV\0" + "GL_MATRIX6_ARB\0" + "GL_MATRIX6_NV\0" + "GL_MATRIX7_ARB\0" + "GL_MATRIX7_NV\0" + "GL_MATRIX8_ARB\0" + "GL_MATRIX9_ARB\0" + "GL_MATRIX_INDEX_ARRAY_ARB\0" + "GL_MATRIX_INDEX_ARRAY_POINTER_ARB\0" + "GL_MATRIX_INDEX_ARRAY_SIZE_ARB\0" + "GL_MATRIX_INDEX_ARRAY_STRIDE_ARB\0" + "GL_MATRIX_INDEX_ARRAY_TYPE_ARB\0" + "GL_MATRIX_MODE\0" + "GL_MATRIX_PALETTE_ARB\0" + "GL_MAX\0" + "GL_MAX_3D_TEXTURE_SIZE\0" + "GL_MAX_ATTRIB_STACK_DEPTH\0" + "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH\0" + "GL_MAX_CLIPMAP_DEPTH_SGIX\0" + "GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX\0" + "GL_MAX_CLIP_PLANES\0" + "GL_MAX_COLOR_ATTACHMENTS_EXT\0" + "GL_MAX_COLOR_MATRIX_STACK_DEPTH\0" + "GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI\0" + "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB\0" + "GL_MAX_CONVOLUTION_HEIGHT\0" + "GL_MAX_CONVOLUTION_HEIGHT_EXT\0" + "GL_MAX_CONVOLUTION_WIDTH\0" + "GL_MAX_CONVOLUTION_WIDTH_EXT\0" + "GL_MAX_CUBE_MAP_TEXTURE_SIZE\0" + "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB\0" + "GL_MAX_DRAW_BUFFERS_ARB\0" + "GL_MAX_DRAW_BUFFERS_ATI\0" + "GL_MAX_ELEMENTS_INDICES\0" + "GL_MAX_ELEMENTS_VERTICES\0" + "GL_MAX_EVAL_ORDER\0" + "GL_MAX_EXT\0" + "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB\0" + "GL_MAX_LIGHTS\0" + "GL_MAX_LIST_NESTING\0" + "GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB\0" + "GL_MAX_MODELVIEW_STACK_DEPTH\0" + "GL_MAX_NAME_STACK_DEPTH\0" + "GL_MAX_PALETTE_MATRICES_ARB\0" + "GL_MAX_PIXEL_MAP_TABLE\0" + "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB\0" + "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB\0" + "GL_MAX_PROGRAM_ATTRIBS_ARB\0" + "GL_MAX_PROGRAM_CALL_DEPTH_NV\0" + "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB\0" + "GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV\0" + "GL_MAX_PROGRAM_IF_DEPTH_NV\0" + "GL_MAX_PROGRAM_INSTRUCTIONS_ARB\0" + "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB\0" + "GL_MAX_PROGRAM_LOOP_COUNT_NV\0" + "GL_MAX_PROGRAM_LOOP_DEPTH_NV\0" + "GL_MAX_PROGRAM_MATRICES_ARB\0" + "GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB\0" + "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB\0" + "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB\0" + "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB\0" + "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB\0" + "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB\0" + "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB\0" + "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB\0" + "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB\0" + "GL_MAX_PROGRAM_PARAMETERS_ARB\0" + "GL_MAX_PROGRAM_TEMPORARIES_ARB\0" + "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB\0" + "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB\0" + "GL_MAX_PROJECTION_STACK_DEPTH\0" + "GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB\0" + "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV\0" + "GL_MAX_RENDERBUFFER_SIZE_EXT\0" + "GL_MAX_SHININESS_NV\0" + "GL_MAX_SPOT_EXPONENT_NV\0" + "GL_MAX_TEXTURE_COORDS_ARB\0" + "GL_MAX_TEXTURE_IMAGE_UNITS_ARB\0" + "GL_MAX_TEXTURE_LOD_BIAS\0" + "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT\0" + "GL_MAX_TEXTURE_SIZE\0" + "GL_MAX_TEXTURE_STACK_DEPTH\0" + "GL_MAX_TEXTURE_UNITS\0" + "GL_MAX_TEXTURE_UNITS_ARB\0" + "GL_MAX_TRACK_MATRICES_NV\0" + "GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV\0" + "GL_MAX_VARYING_FLOATS_ARB\0" + "GL_MAX_VERTEX_ATTRIBS_ARB\0" + "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB\0" + "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB\0" + "GL_MAX_VERTEX_UNITS_ARB\0" + "GL_MAX_VIEWPORT_DIMS\0" + "GL_MIN\0" + "GL_MINMAX\0" + "GL_MINMAX_EXT\0" + "GL_MINMAX_FORMAT\0" + "GL_MINMAX_FORMAT_EXT\0" + "GL_MINMAX_SINK\0" + "GL_MINMAX_SINK_EXT\0" + "GL_MIN_EXT\0" + "GL_MIRRORED_REPEAT\0" + "GL_MIRRORED_REPEAT_ARB\0" + "GL_MIRRORED_REPEAT_IBM\0" + "GL_MIRROR_CLAMP_ATI\0" + "GL_MIRROR_CLAMP_EXT\0" + "GL_MIRROR_CLAMP_TO_BORDER_EXT\0" + "GL_MIRROR_CLAMP_TO_EDGE_ATI\0" + "GL_MIRROR_CLAMP_TO_EDGE_EXT\0" + "GL_MODELVIEW\0" + "GL_MODELVIEW0_ARB\0" + "GL_MODELVIEW10_ARB\0" + "GL_MODELVIEW11_ARB\0" + "GL_MODELVIEW12_ARB\0" + "GL_MODELVIEW13_ARB\0" + "GL_MODELVIEW14_ARB\0" + "GL_MODELVIEW15_ARB\0" + "GL_MODELVIEW16_ARB\0" + "GL_MODELVIEW17_ARB\0" + "GL_MODELVIEW18_ARB\0" + "GL_MODELVIEW19_ARB\0" + "GL_MODELVIEW1_ARB\0" + "GL_MODELVIEW20_ARB\0" + "GL_MODELVIEW21_ARB\0" + "GL_MODELVIEW22_ARB\0" + "GL_MODELVIEW23_ARB\0" + "GL_MODELVIEW24_ARB\0" + "GL_MODELVIEW25_ARB\0" + "GL_MODELVIEW26_ARB\0" + "GL_MODELVIEW27_ARB\0" + "GL_MODELVIEW28_ARB\0" + "GL_MODELVIEW29_ARB\0" + "GL_MODELVIEW2_ARB\0" + "GL_MODELVIEW30_ARB\0" + "GL_MODELVIEW31_ARB\0" + "GL_MODELVIEW3_ARB\0" + "GL_MODELVIEW4_ARB\0" + "GL_MODELVIEW5_ARB\0" + "GL_MODELVIEW6_ARB\0" + "GL_MODELVIEW7_ARB\0" + "GL_MODELVIEW8_ARB\0" + "GL_MODELVIEW9_ARB\0" + "GL_MODELVIEW_MATRIX\0" + "GL_MODELVIEW_PROJECTION_NV\0" + "GL_MODELVIEW_STACK_DEPTH\0" + "GL_MODULATE\0" + "GL_MODULATE_ADD_ATI\0" + "GL_MODULATE_SIGNED_ADD_ATI\0" + "GL_MODULATE_SUBTRACT_ATI\0" + "GL_MULT\0" + "GL_MULTISAMPLE\0" + "GL_MULTISAMPLE_3DFX\0" + "GL_MULTISAMPLE_ARB\0" + "GL_MULTISAMPLE_BIT\0" + "GL_MULTISAMPLE_BIT_3DFX\0" + "GL_MULTISAMPLE_BIT_ARB\0" + "GL_MULTISAMPLE_FILTER_HINT_NV\0" + "GL_N3F_V3F\0" + "GL_NAME_STACK_DEPTH\0" + "GL_NAND\0" + "GL_NEAREST\0" + "GL_NEAREST_CLIPMAP_LINEAR_SGIX\0" + "GL_NEAREST_CLIPMAP_NEAREST_SGIX\0" + "GL_NEAREST_MIPMAP_LINEAR\0" + "GL_NEAREST_MIPMAP_NEAREST\0" + "GL_NEVER\0" + "GL_NICEST\0" + "GL_NONE\0" + "GL_NOOP\0" + "GL_NOR\0" + "GL_NORMALIZE\0" + "GL_NORMAL_ARRAY\0" + "GL_NORMAL_ARRAY_BUFFER_BINDING\0" + "GL_NORMAL_ARRAY_BUFFER_BINDING_ARB\0" + "GL_NORMAL_ARRAY_POINTER\0" + "GL_NORMAL_ARRAY_STRIDE\0" + "GL_NORMAL_ARRAY_TYPE\0" + "GL_NORMAL_MAP\0" + "GL_NORMAL_MAP_ARB\0" + "GL_NORMAL_MAP_NV\0" + "GL_NOTEQUAL\0" + "GL_NO_ERROR\0" + "GL_NUM_COMPRESSED_TEXTURE_FORMATS\0" + "GL_NUM_TEXTURE_COMPRESSED_FORMATS_ARB\0" + "GL_OBJECT_ACTIVE_ATTRIBUTES_ARB\0" + "GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB\0" + "GL_OBJECT_ACTIVE_UNIFORMS_ARB\0" + "GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB\0" + "GL_OBJECT_ATTACHED_OBJECTS_ARB\0" + "GL_OBJECT_COMPILE_STATUS_ARB\0" + "GL_OBJECT_DELETE_STATUS_ARB\0" + "GL_OBJECT_INFO_LOG_LENGTH_ARB\0" + "GL_OBJECT_LINEAR\0" + "GL_OBJECT_LINK_STATUS_ARB\0" + "GL_OBJECT_PLANE\0" + "GL_OBJECT_SHADER_SOURCE_LENGTH_ARB\0" + "GL_OBJECT_SUBTYPE_ARB\0" + "GL_OBJECT_TYPE_ARB\0" + "GL_OBJECT_VALIDATE_STATUS_ARB\0" + "GL_OCCLUSION_TEST_HP\0" + "GL_OCCLUSION_TEST_RESULT_HP\0" + "GL_ONE\0" + "GL_ONE_MINUS_CONSTANT_ALPHA\0" + "GL_ONE_MINUS_CONSTANT_ALPHA_EXT\0" + "GL_ONE_MINUS_CONSTANT_COLOR\0" + "GL_ONE_MINUS_CONSTANT_COLOR_EXT\0" + "GL_ONE_MINUS_DST_ALPHA\0" + "GL_ONE_MINUS_DST_COLOR\0" + "GL_ONE_MINUS_SRC_ALPHA\0" + "GL_ONE_MINUS_SRC_COLOR\0" + "GL_OPERAND0_ALPHA\0" + "GL_OPERAND0_ALPHA_ARB\0" + "GL_OPERAND0_ALPHA_EXT\0" + "GL_OPERAND0_RGB\0" + "GL_OPERAND0_RGB_ARB\0" + "GL_OPERAND0_RGB_EXT\0" + "GL_OPERAND1_ALPHA\0" + "GL_OPERAND1_ALPHA_ARB\0" + "GL_OPERAND1_ALPHA_EXT\0" + "GL_OPERAND1_RGB\0" + "GL_OPERAND1_RGB_ARB\0" + "GL_OPERAND1_RGB_EXT\0" + "GL_OPERAND2_ALPHA\0" + "GL_OPERAND2_ALPHA_ARB\0" + "GL_OPERAND2_ALPHA_EXT\0" + "GL_OPERAND2_RGB\0" + "GL_OPERAND2_RGB_ARB\0" + "GL_OPERAND2_RGB_EXT\0" + "GL_OPERAND3_ALPHA_NV\0" + "GL_OPERAND3_RGB_NV\0" + "GL_OR\0" + "GL_ORDER\0" + "GL_OR_INVERTED\0" + "GL_OR_REVERSE\0" + "GL_OUT_OF_MEMORY\0" + "GL_PACK_ALIGNMENT\0" + "GL_PACK_IMAGE_HEIGHT\0" + "GL_PACK_INVERT_MESA\0" + "GL_PACK_LSB_FIRST\0" + "GL_PACK_ROW_LENGTH\0" + "GL_PACK_SKIP_IMAGES\0" + "GL_PACK_SKIP_PIXELS\0" + "GL_PACK_SKIP_ROWS\0" + "GL_PACK_SWAP_BYTES\0" + "GL_PALETTE4_R5_G6_B5_OES\0" + "GL_PALETTE4_RGB5_A1_OES\0" + "GL_PALETTE4_RGB8_OES\0" + "GL_PALETTE4_RGBA4_OES\0" + "GL_PALETTE4_RGBA8_OES\0" + "GL_PALETTE8_R5_G6_B5_OES\0" + "GL_PALETTE8_RGB5_A1_OES\0" + "GL_PALETTE8_RGB8_OES\0" + "GL_PALETTE8_RGBA4_OES\0" + "GL_PALETTE8_RGBA8_OES\0" + "GL_PASS_THROUGH_TOKEN\0" + "GL_PERSPECTIVE_CORRECTION_HINT\0" + "GL_PIXEL_MAP_A_TO_A\0" + "GL_PIXEL_MAP_A_TO_A_SIZE\0" + "GL_PIXEL_MAP_B_TO_B\0" + "GL_PIXEL_MAP_B_TO_B_SIZE\0" + "GL_PIXEL_MAP_G_TO_G\0" + "GL_PIXEL_MAP_G_TO_G_SIZE\0" + "GL_PIXEL_MAP_I_TO_A\0" + "GL_PIXEL_MAP_I_TO_A_SIZE\0" + "GL_PIXEL_MAP_I_TO_B\0" + "GL_PIXEL_MAP_I_TO_B_SIZE\0" + "GL_PIXEL_MAP_I_TO_G\0" + "GL_PIXEL_MAP_I_TO_G_SIZE\0" + "GL_PIXEL_MAP_I_TO_I\0" + "GL_PIXEL_MAP_I_TO_I_SIZE\0" + "GL_PIXEL_MAP_I_TO_R\0" + "GL_PIXEL_MAP_I_TO_R_SIZE\0" + "GL_PIXEL_MAP_R_TO_R\0" + "GL_PIXEL_MAP_R_TO_R_SIZE\0" + "GL_PIXEL_MAP_S_TO_S\0" + "GL_PIXEL_MAP_S_TO_S_SIZE\0" + "GL_PIXEL_MODE_BIT\0" + "GL_PIXEL_PACK_BUFFER_BINDING_EXT\0" + "GL_PIXEL_PACK_BUFFER_EXT\0" + "GL_PIXEL_UNPACK_BUFFER_BINDING_EXT\0" + "GL_PIXEL_UNPACK_BUFFER_EXT\0" + "GL_POINT\0" + "GL_POINTS\0" + "GL_POINT_BIT\0" + "GL_POINT_DISTANCE_ATTENUATION\0" + "GL_POINT_DISTANCE_ATTENUATION_ARB\0" + "GL_POINT_DISTANCE_ATTENUATION_EXT\0" + "GL_POINT_DISTANCE_ATTENUATION_SGIS\0" + "GL_POINT_FADE_THRESHOLD_SIZE\0" + "GL_POINT_FADE_THRESHOLD_SIZE_ARB\0" + "GL_POINT_FADE_THRESHOLD_SIZE_EXT\0" + "GL_POINT_FADE_THRESHOLD_SIZE_SGIS\0" + "GL_POINT_SIZE\0" + "GL_POINT_SIZE_GRANULARITY\0" + "GL_POINT_SIZE_MAX\0" + "GL_POINT_SIZE_MAX_ARB\0" + "GL_POINT_SIZE_MAX_EXT\0" + "GL_POINT_SIZE_MAX_SGIS\0" + "GL_POINT_SIZE_MIN\0" + "GL_POINT_SIZE_MIN_ARB\0" + "GL_POINT_SIZE_MIN_EXT\0" + "GL_POINT_SIZE_MIN_SGIS\0" + "GL_POINT_SIZE_RANGE\0" + "GL_POINT_SMOOTH\0" + "GL_POINT_SMOOTH_HINT\0" + "GL_POINT_SPRITE_ARB\0" + "GL_POINT_SPRITE_COORD_ORIGIN\0" + "GL_POINT_SPRITE_NV\0" + "GL_POINT_SPRITE_R_MODE_NV\0" + "GL_POINT_TOKEN\0" + "GL_POLYGON\0" + "GL_POLYGON_BIT\0" + "GL_POLYGON_MODE\0" + "GL_POLYGON_OFFSET_BIAS\0" + "GL_POLYGON_OFFSET_FACTOR\0" + "GL_POLYGON_OFFSET_FILL\0" + "GL_POLYGON_OFFSET_LINE\0" + "GL_POLYGON_OFFSET_POINT\0" + "GL_POLYGON_OFFSET_UNITS\0" + "GL_POLYGON_SMOOTH\0" + "GL_POLYGON_SMOOTH_HINT\0" + "GL_POLYGON_STIPPLE\0" + "GL_POLYGON_STIPPLE_BIT\0" + "GL_POLYGON_TOKEN\0" + "GL_POSITION\0" + "GL_POST_COLOR_MATRIX_ALPHA_BIAS\0" + "GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI\0" + "GL_POST_COLOR_MATRIX_ALPHA_SCALE\0" + "GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI\0" + "GL_POST_COLOR_MATRIX_BLUE_BIAS\0" + "GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI\0" + "GL_POST_COLOR_MATRIX_BLUE_SCALE\0" + "GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI\0" + "GL_POST_COLOR_MATRIX_COLOR_TABLE\0" + "GL_POST_COLOR_MATRIX_GREEN_BIAS\0" + "GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI\0" + "GL_POST_COLOR_MATRIX_GREEN_SCALE\0" + "GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI\0" + "GL_POST_COLOR_MATRIX_RED_BIAS\0" + "GL_POST_COLOR_MATRIX_RED_BIAS_SGI\0" + "GL_POST_COLOR_MATRIX_RED_SCALE\0" + "GL_POST_COLOR_MATRIX_RED_SCALE_SGI\0" + "GL_POST_CONVOLUTION_ALPHA_BIAS\0" + "GL_POST_CONVOLUTION_ALPHA_BIAS_EXT\0" + "GL_POST_CONVOLUTION_ALPHA_SCALE\0" + "GL_POST_CONVOLUTION_ALPHA_SCALE_EXT\0" + "GL_POST_CONVOLUTION_BLUE_BIAS\0" + "GL_POST_CONVOLUTION_BLUE_BIAS_EXT\0" + "GL_POST_CONVOLUTION_BLUE_SCALE\0" + "GL_POST_CONVOLUTION_BLUE_SCALE_EXT\0" + "GL_POST_CONVOLUTION_COLOR_TABLE\0" + "GL_POST_CONVOLUTION_GREEN_BIAS\0" + "GL_POST_CONVOLUTION_GREEN_BIAS_EXT\0" + "GL_POST_CONVOLUTION_GREEN_SCALE\0" + "GL_POST_CONVOLUTION_GREEN_SCALE_EXT\0" + "GL_POST_CONVOLUTION_RED_BIAS\0" + "GL_POST_CONVOLUTION_RED_BIAS_EXT\0" + "GL_POST_CONVOLUTION_RED_SCALE\0" + "GL_POST_CONVOLUTION_RED_SCALE_EXT\0" + "GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX\0" + "GL_POST_TEXTURE_FILTER_BIAS_SGIX\0" + "GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX\0" + "GL_POST_TEXTURE_FILTER_SCALE_SGIX\0" + "GL_PREVIOUS\0" + "GL_PREVIOUS_ARB\0" + "GL_PREVIOUS_EXT\0" + "GL_PRIMARY_COLOR\0" + "GL_PRIMARY_COLOR_ARB\0" + "GL_PRIMARY_COLOR_EXT\0" + "GL_PROGRAM_ADDRESS_REGISTERS_ARB\0" + "GL_PROGRAM_ALU_INSTRUCTIONS_ARB\0" + "GL_PROGRAM_ATTRIBS_ARB\0" + "GL_PROGRAM_BINDING_ARB\0" + "GL_PROGRAM_ERROR_POSITION_ARB\0" + "GL_PROGRAM_ERROR_POSITION_NV\0" + "GL_PROGRAM_ERROR_STRING_ARB\0" + "GL_PROGRAM_FORMAT_ARB\0" + "GL_PROGRAM_FORMAT_ASCII_ARB\0" + "GL_PROGRAM_INSTRUCTIONS_ARB\0" + "GL_PROGRAM_LENGTH_ARB\0" + "GL_PROGRAM_LENGTH_NV\0" + "GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB\0" + "GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB\0" + "GL_PROGRAM_NATIVE_ATTRIBS_ARB\0" + "GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB\0" + "GL_PROGRAM_NATIVE_PARAMETERS_ARB\0" + "GL_PROGRAM_NATIVE_TEMPORARIES_ARB\0" + "GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB\0" + "GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB\0" + "GL_PROGRAM_OBJECT_ARB\0" + "GL_PROGRAM_PARAMETERS_ARB\0" + "GL_PROGRAM_PARAMETER_NV\0" + "GL_PROGRAM_RESIDENT_NV\0" + "GL_PROGRAM_STRING_ARB\0" + "GL_PROGRAM_STRING_NV\0" + "GL_PROGRAM_TARGET_NV\0" + "GL_PROGRAM_TEMPORARIES_ARB\0" + "GL_PROGRAM_TEX_INDIRECTIONS_ARB\0" + "GL_PROGRAM_TEX_INSTRUCTIONS_ARB\0" + "GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB\0" + "GL_PROJECTION\0" + "GL_PROJECTION_MATRIX\0" + "GL_PROJECTION_STACK_DEPTH\0" + "GL_PROXY_COLOR_TABLE\0" + "GL_PROXY_HISTOGRAM\0" + "GL_PROXY_HISTOGRAM_EXT\0" + "GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE\0" + "GL_PROXY_POST_CONVOLUTION_COLOR_TABLE\0" + "GL_PROXY_TEXTURE_1D\0" + "GL_PROXY_TEXTURE_1D_EXT\0" + "GL_PROXY_TEXTURE_2D\0" + "GL_PROXY_TEXTURE_2D_EXT\0" + "GL_PROXY_TEXTURE_3D\0" + "GL_PROXY_TEXTURE_COLOR_TABLE_SGI\0" + "GL_PROXY_TEXTURE_CUBE_MAP\0" + "GL_PROXY_TEXTURE_CUBE_MAP_ARB\0" + "GL_PROXY_TEXTURE_RECTANGLE_ARB\0" + "GL_PROXY_TEXTURE_RECTANGLE_NV\0" + "GL_Q\0" + "GL_QUADRATIC_ATTENUATION\0" + "GL_QUADS\0" + "GL_QUAD_MESH_SUN\0" + "GL_QUAD_STRIP\0" + "GL_QUERY_COUNTER_BITS\0" + "GL_QUERY_COUNTER_BITS_ARB\0" + "GL_QUERY_RESULT\0" + "GL_QUERY_RESULT_ARB\0" + "GL_QUERY_RESULT_AVAILABLE\0" + "GL_QUERY_RESULT_AVAILABLE_ARB\0" + "GL_R\0" + "GL_R3_G3_B2\0" + "GL_RASTER_POSITION_UNCLIPPED_IBM\0" + "GL_READ_BUFFER\0" + "GL_READ_ONLY\0" + "GL_READ_ONLY_ARB\0" + "GL_READ_WRITE\0" + "GL_READ_WRITE_ARB\0" + "GL_RED\0" + "GL_REDUCE\0" + "GL_REDUCE_EXT\0" + "GL_RED_BIAS\0" + "GL_RED_BITS\0" + "GL_RED_SCALE\0" + "GL_REFLECTION_MAP\0" + "GL_REFLECTION_MAP_ARB\0" + "GL_REFLECTION_MAP_NV\0" + "GL_RENDER\0" + "GL_RENDERBUFFER_BINDING_EXT\0" + "GL_RENDERBUFFER_EXT\0" + "GL_RENDERBUFFER_HEIGHT_EXT\0" + "GL_RENDERBUFFER_INTERNAL_FORMAT_EXT\0" + "GL_RENDERBUFFER_WIDTH_EXT\0" + "GL_RENDERER\0" + "GL_RENDER_MODE\0" + "GL_REPEAT\0" + "GL_REPLACE\0" + "GL_REPLACE_EXT\0" + "GL_REPLICATE_BORDER_HP\0" + "GL_RESCALE_NORMAL\0" + "GL_RESCALE_NORMAL_EXT\0" + "GL_RETURN\0" + "GL_RGB\0" + "GL_RGB10\0" + "GL_RGB10_A2\0" + "GL_RGB10_A2_EXT\0" + "GL_RGB10_EXT\0" + "GL_RGB12\0" + "GL_RGB12_EXT\0" + "GL_RGB16\0" + "GL_RGB16_EXT\0" + "GL_RGB2_EXT\0" + "GL_RGB4\0" + "GL_RGB4_EXT\0" + "GL_RGB4_S3TC\0" + "GL_RGB5\0" + "GL_RGB5_A1\0" + "GL_RGB5_A1_EXT\0" + "GL_RGB5_EXT\0" + "GL_RGB8\0" + "GL_RGB8_EXT\0" + "GL_RGBA\0" + "GL_RGBA12\0" + "GL_RGBA12_EXT\0" + "GL_RGBA16\0" + "GL_RGBA16_EXT\0" + "GL_RGBA2\0" + "GL_RGBA2_EXT\0" + "GL_RGBA4\0" + "GL_RGBA4_DXT5_S3TC\0" + "GL_RGBA4_EXT\0" + "GL_RGBA4_S3TC\0" + "GL_RGBA8\0" + "GL_RGBA8_EXT\0" + "GL_RGBA_DXT5_S3TC\0" + "GL_RGBA_MODE\0" + "GL_RGBA_S3TC\0" + "GL_RGB_S3TC\0" + "GL_RGB_SCALE\0" + "GL_RGB_SCALE_ARB\0" + "GL_RGB_SCALE_EXT\0" + "GL_RIGHT\0" + "GL_S\0" + "GL_SAMPLES\0" + "GL_SAMPLES_3DFX\0" + "GL_SAMPLES_ARB\0" + "GL_SAMPLES_PASSED\0" + "GL_SAMPLES_PASSED_ARB\0" + "GL_SAMPLE_ALPHA_TO_COVERAGE\0" + "GL_SAMPLE_ALPHA_TO_COVERAGE_ARB\0" + "GL_SAMPLE_ALPHA_TO_ONE\0" + "GL_SAMPLE_ALPHA_TO_ONE_ARB\0" + "GL_SAMPLE_BUFFERS\0" + "GL_SAMPLE_BUFFERS_3DFX\0" + "GL_SAMPLE_BUFFERS_ARB\0" + "GL_SAMPLE_COVERAGE\0" + "GL_SAMPLE_COVERAGE_ARB\0" + "GL_SAMPLE_COVERAGE_INVERT\0" + "GL_SAMPLE_COVERAGE_INVERT_ARB\0" + "GL_SAMPLE_COVERAGE_VALUE\0" + "GL_SAMPLE_COVERAGE_VALUE_ARB\0" + "GL_SCISSOR_BIT\0" + "GL_SCISSOR_BOX\0" + "GL_SCISSOR_TEST\0" + "GL_SECONDARY_COLOR_ARRAY\0" + "GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING\0" + "GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB\0" + "GL_SECONDARY_COLOR_ARRAY_POINTER\0" + "GL_SECONDARY_COLOR_ARRAY_SIZE\0" + "GL_SECONDARY_COLOR_ARRAY_STRIDE\0" + "GL_SECONDARY_COLOR_ARRAY_TYPE\0" + "GL_SELECT\0" + "GL_SELECTION_BUFFER_POINTER\0" + "GL_SELECTION_BUFFER_SIZE\0" + "GL_SEPARABLE_2D\0" + "GL_SEPARATE_SPECULAR_COLOR\0" + "GL_SEPARATE_SPECULAR_COLOR_EXT\0" + "GL_SET\0" + "GL_SHADER_OBJECT_ARB\0" + "GL_SHADE_MODEL\0" + "GL_SHADOW_AMBIENT_SGIX\0" + "GL_SHARED_TEXTURE_PALETTE_EXT\0" + "GL_SHININESS\0" + "GL_SHORT\0" + "GL_SINGLE_COLOR\0" + "GL_SINGLE_COLOR_EXT\0" + "GL_SLICE_ACCUM_SUN\0" + "GL_SMOOTH\0" + "GL_SMOOTH_LINE_WIDTH_GRANULARITY\0" + "GL_SMOOTH_LINE_WIDTH_RANGE\0" + "GL_SMOOTH_POINT_SIZE_GRANULARITY\0" + "GL_SMOOTH_POINT_SIZE_RANGE\0" + "GL_SOURCE0_ALPHA\0" + "GL_SOURCE0_ALPHA_ARB\0" + "GL_SOURCE0_ALPHA_EXT\0" + "GL_SOURCE0_RGB\0" + "GL_SOURCE0_RGB_ARB\0" + "GL_SOURCE0_RGB_EXT\0" + "GL_SOURCE1_ALPHA\0" + "GL_SOURCE1_ALPHA_ARB\0" + "GL_SOURCE1_ALPHA_EXT\0" + "GL_SOURCE1_RGB\0" + "GL_SOURCE1_RGB_ARB\0" + "GL_SOURCE1_RGB_EXT\0" + "GL_SOURCE2_ALPHA\0" + "GL_SOURCE2_ALPHA_ARB\0" + "GL_SOURCE2_ALPHA_EXT\0" + "GL_SOURCE2_RGB\0" + "GL_SOURCE2_RGB_ARB\0" + "GL_SOURCE2_RGB_EXT\0" + "GL_SOURCE3_ALPHA_NV\0" + "GL_SOURCE3_RGB_NV\0" + "GL_SPECULAR\0" + "GL_SPHERE_MAP\0" + "GL_SPOT_CUTOFF\0" + "GL_SPOT_DIRECTION\0" + "GL_SPOT_EXPONENT\0" + "GL_SRC0_ALPHA\0" + "GL_SRC0_RGB\0" + "GL_SRC1_ALPHA\0" + "GL_SRC1_RGB\0" + "GL_SRC2_ALPHA\0" + "GL_SRC2_RGB\0" + "GL_SRC_ALPHA\0" + "GL_SRC_ALPHA_SATURATE\0" + "GL_SRC_COLOR\0" + "GL_STACK_OVERFLOW\0" + "GL_STACK_UNDERFLOW\0" + "GL_STATIC_COPY\0" + "GL_STATIC_COPY_ARB\0" + "GL_STATIC_DRAW\0" + "GL_STATIC_DRAW_ARB\0" + "GL_STATIC_READ\0" + "GL_STATIC_READ_ARB\0" + "GL_STENCIL\0" + "GL_STENCIL_ATTACHMENT_EXT\0" + "GL_STENCIL_BITS\0" + "GL_STENCIL_BUFFER_BIT\0" + "GL_STENCIL_CLEAR_VALUE\0" + "GL_STENCIL_FAIL\0" + "GL_STENCIL_FUNC\0" + "GL_STENCIL_INDEX\0" + "GL_STENCIL_INDEX16_EXT\0" + "GL_STENCIL_INDEX1_EXT\0" + "GL_STENCIL_INDEX4_EXT\0" + "GL_STENCIL_INDEX8_EXT\0" + "GL_STENCIL_INDEX_EXT\0" + "GL_STENCIL_PASS_DEPTH_FAIL\0" + "GL_STENCIL_PASS_DEPTH_PASS\0" + "GL_STENCIL_REF\0" + "GL_STENCIL_TEST\0" + "GL_STENCIL_TEST_TWO_SIDE_EXT\0" + "GL_STENCIL_VALUE_MASK\0" + "GL_STENCIL_WRITEMASK\0" + "GL_STEREO\0" + "GL_STREAM_COPY\0" + "GL_STREAM_COPY_ARB\0" + "GL_STREAM_DRAW\0" + "GL_STREAM_DRAW_ARB\0" + "GL_STREAM_READ\0" + "GL_STREAM_READ_ARB\0" + "GL_SUBPIXEL_BITS\0" + "GL_SUBTRACT\0" + "GL_SUBTRACT_ARB\0" + "GL_T\0" + "GL_T2F_C3F_V3F\0" + "GL_T2F_C4F_N3F_V3F\0" + "GL_T2F_C4UB_V3F\0" + "GL_T2F_N3F_V3F\0" + "GL_T2F_V3F\0" + "GL_T4F_C4F_N3F_V4F\0" + "GL_T4F_V4F\0" + "GL_TABLE_TOO_LARGE_EXT\0" + "GL_TEXTURE\0" + "GL_TEXTURE0\0" + "GL_TEXTURE0_ARB\0" + "GL_TEXTURE1\0" + "GL_TEXTURE10\0" + "GL_TEXTURE10_ARB\0" + "GL_TEXTURE11\0" + "GL_TEXTURE11_ARB\0" + "GL_TEXTURE12\0" + "GL_TEXTURE12_ARB\0" + "GL_TEXTURE13\0" + "GL_TEXTURE13_ARB\0" + "GL_TEXTURE14\0" + "GL_TEXTURE14_ARB\0" + "GL_TEXTURE15\0" + "GL_TEXTURE15_ARB\0" + "GL_TEXTURE16\0" + "GL_TEXTURE16_ARB\0" + "GL_TEXTURE17\0" + "GL_TEXTURE17_ARB\0" + "GL_TEXTURE18\0" + "GL_TEXTURE18_ARB\0" + "GL_TEXTURE19\0" + "GL_TEXTURE19_ARB\0" + "GL_TEXTURE1_ARB\0" + "GL_TEXTURE2\0" + "GL_TEXTURE20\0" + "GL_TEXTURE20_ARB\0" + "GL_TEXTURE21\0" + "GL_TEXTURE21_ARB\0" + "GL_TEXTURE22\0" + "GL_TEXTURE22_ARB\0" + "GL_TEXTURE23\0" + "GL_TEXTURE23_ARB\0" + "GL_TEXTURE24\0" + "GL_TEXTURE24_ARB\0" + "GL_TEXTURE25\0" + "GL_TEXTURE25_ARB\0" + "GL_TEXTURE26\0" + "GL_TEXTURE26_ARB\0" + "GL_TEXTURE27\0" + "GL_TEXTURE27_ARB\0" + "GL_TEXTURE28\0" + "GL_TEXTURE28_ARB\0" + "GL_TEXTURE29\0" + "GL_TEXTURE29_ARB\0" + "GL_TEXTURE2_ARB\0" + "GL_TEXTURE3\0" + "GL_TEXTURE30\0" + "GL_TEXTURE30_ARB\0" + "GL_TEXTURE31\0" + "GL_TEXTURE31_ARB\0" + "GL_TEXTURE3_ARB\0" + "GL_TEXTURE4\0" + "GL_TEXTURE4_ARB\0" + "GL_TEXTURE5\0" + "GL_TEXTURE5_ARB\0" + "GL_TEXTURE6\0" + "GL_TEXTURE6_ARB\0" + "GL_TEXTURE7\0" + "GL_TEXTURE7_ARB\0" + "GL_TEXTURE8\0" + "GL_TEXTURE8_ARB\0" + "GL_TEXTURE9\0" + "GL_TEXTURE9_ARB\0" + "GL_TEXTURE_1D\0" + "GL_TEXTURE_2D\0" + "GL_TEXTURE_3D\0" + "GL_TEXTURE_ALPHA_SIZE\0" + "GL_TEXTURE_ALPHA_SIZE_EXT\0" + "GL_TEXTURE_BASE_LEVEL\0" + "GL_TEXTURE_BINDING_1D\0" + "GL_TEXTURE_BINDING_2D\0" + "GL_TEXTURE_BINDING_3D\0" + "GL_TEXTURE_BINDING_CUBE_MAP\0" + "GL_TEXTURE_BINDING_CUBE_MAP_ARB\0" + "GL_TEXTURE_BINDING_RECTANGLE_ARB\0" + "GL_TEXTURE_BINDING_RECTANGLE_NV\0" + "GL_TEXTURE_BIT\0" + "GL_TEXTURE_BLUE_SIZE\0" + "GL_TEXTURE_BLUE_SIZE_EXT\0" + "GL_TEXTURE_BORDER\0" + "GL_TEXTURE_BORDER_COLOR\0" + "GL_TEXTURE_CLIPMAP_CENTER_SGIX\0" + "GL_TEXTURE_CLIPMAP_DEPTH_SGIX\0" + "GL_TEXTURE_CLIPMAP_FRAME_SGIX\0" + "GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX\0" + "GL_TEXTURE_CLIPMAP_OFFSET_SGIX\0" + "GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX\0" + "GL_TEXTURE_COLOR_TABLE_SGI\0" + "GL_TEXTURE_COLOR_WRITEMASK_SGIS\0" + "GL_TEXTURE_COMPARE_FAIL_VALUE_ARB\0" + "GL_TEXTURE_COMPARE_FUNC\0" + "GL_TEXTURE_COMPARE_FUNC_ARB\0" + "GL_TEXTURE_COMPARE_MODE\0" + "GL_TEXTURE_COMPARE_MODE_ARB\0" + "GL_TEXTURE_COMPARE_OPERATOR_SGIX\0" + "GL_TEXTURE_COMPARE_SGIX\0" + "GL_TEXTURE_COMPONENTS\0" + "GL_TEXTURE_COMPRESSED\0" + "GL_TEXTURE_COMPRESSED_ARB\0" + "GL_TEXTURE_COMPRESSED_FORMATS_ARB\0" + "GL_TEXTURE_COMPRESSED_IMAGE_SIZE\0" + "GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB\0" + "GL_TEXTURE_COMPRESSION_HINT\0" + "GL_TEXTURE_COMPRESSION_HINT_ARB\0" + "GL_TEXTURE_COORD_ARRAY\0" + "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING\0" + "GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB\0" + "GL_TEXTURE_COORD_ARRAY_POINTER\0" + "GL_TEXTURE_COORD_ARRAY_SIZE\0" + "GL_TEXTURE_COORD_ARRAY_STRIDE\0" + "GL_TEXTURE_COORD_ARRAY_TYPE\0" + "GL_TEXTURE_CUBE_MAP\0" + "GL_TEXTURE_CUBE_MAP_ARB\0" + "GL_TEXTURE_CUBE_MAP_NEGATIVE_X\0" + "GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB\0" + "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y\0" + "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB\0" + "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z\0" + "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB\0" + "GL_TEXTURE_CUBE_MAP_POSITIVE_X\0" + "GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB\0" + "GL_TEXTURE_CUBE_MAP_POSITIVE_Y\0" + "GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB\0" + "GL_TEXTURE_CUBE_MAP_POSITIVE_Z\0" + "GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB\0" + "GL_TEXTURE_DEPTH\0" + "GL_TEXTURE_DEPTH_SIZE\0" + "GL_TEXTURE_DEPTH_SIZE_ARB\0" + "GL_TEXTURE_ENV\0" + "GL_TEXTURE_ENV_COLOR\0" + "GL_TEXTURE_ENV_MODE\0" + "GL_TEXTURE_FILTER_CONTROL\0" + "GL_TEXTURE_GEN_MODE\0" + "GL_TEXTURE_GEN_Q\0" + "GL_TEXTURE_GEN_R\0" + "GL_TEXTURE_GEN_S\0" + "GL_TEXTURE_GEN_T\0" + "GL_TEXTURE_GEQUAL_R_SGIX\0" + "GL_TEXTURE_GREEN_SIZE\0" + "GL_TEXTURE_GREEN_SIZE_EXT\0" + "GL_TEXTURE_HEIGHT\0" + "GL_TEXTURE_INDEX_SIZE_EXT\0" + "GL_TEXTURE_INTENSITY_SIZE\0" + "GL_TEXTURE_INTENSITY_SIZE_EXT\0" + "GL_TEXTURE_INTERNAL_FORMAT\0" + "GL_TEXTURE_LEQUAL_R_SGIX\0" + "GL_TEXTURE_LOD_BIAS\0" + "GL_TEXTURE_LOD_BIAS_EXT\0" + "GL_TEXTURE_LOD_BIAS_R_SGIX\0" + "GL_TEXTURE_LOD_BIAS_S_SGIX\0" + "GL_TEXTURE_LOD_BIAS_T_SGIX\0" + "GL_TEXTURE_LUMINANCE_SIZE\0" + "GL_TEXTURE_LUMINANCE_SIZE_EXT\0" + "GL_TEXTURE_MAG_FILTER\0" + "GL_TEXTURE_MATRIX\0" + "GL_TEXTURE_MAX_ANISOTROPY_EXT\0" + "GL_TEXTURE_MAX_CLAMP_R_SGIX\0" + "GL_TEXTURE_MAX_CLAMP_S_SGIX\0" + "GL_TEXTURE_MAX_CLAMP_T_SGIX\0" + "GL_TEXTURE_MAX_LEVEL\0" + "GL_TEXTURE_MAX_LOD\0" + "GL_TEXTURE_MIN_FILTER\0" + "GL_TEXTURE_MIN_LOD\0" + "GL_TEXTURE_PRIORITY\0" + "GL_TEXTURE_RECTANGLE_ARB\0" + "GL_TEXTURE_RECTANGLE_NV\0" + "GL_TEXTURE_RED_SIZE\0" + "GL_TEXTURE_RED_SIZE_EXT\0" + "GL_TEXTURE_RESIDENT\0" + "GL_TEXTURE_STACK_DEPTH\0" + "GL_TEXTURE_TOO_LARGE_EXT\0" + "GL_TEXTURE_UNSIGNED_REMAP_MODE_NV\0" + "GL_TEXTURE_WIDTH\0" + "GL_TEXTURE_WRAP_R\0" + "GL_TEXTURE_WRAP_S\0" + "GL_TEXTURE_WRAP_T\0" + "GL_TRACK_MATRIX_NV\0" + "GL_TRACK_MATRIX_TRANSFORM_NV\0" + "GL_TRANSFORM_BIT\0" + "GL_TRANSPOSE_COLOR_MATRIX\0" + "GL_TRANSPOSE_COLOR_MATRIX_ARB\0" + "GL_TRANSPOSE_CURRENT_MATRIX_ARB\0" + "GL_TRANSPOSE_MODELVIEW_MATRIX\0" + "GL_TRANSPOSE_MODELVIEW_MATRIX_ARB\0" + "GL_TRANSPOSE_NV\0" + "GL_TRANSPOSE_PROJECTION_MATRIX\0" + "GL_TRANSPOSE_PROJECTION_MATRIX_ARB\0" + "GL_TRANSPOSE_TEXTURE_MATRIX\0" + "GL_TRANSPOSE_TEXTURE_MATRIX_ARB\0" + "GL_TRIANGLES\0" + "GL_TRIANGLE_FAN\0" + "GL_TRIANGLE_MESH_SUN\0" + "GL_TRIANGLE_STRIP\0" + "GL_TRUE\0" + "GL_UNPACK_ALIGNMENT\0" + "GL_UNPACK_IMAGE_HEIGHT\0" + "GL_UNPACK_LSB_FIRST\0" + "GL_UNPACK_ROW_LENGTH\0" + "GL_UNPACK_SKIP_IMAGES\0" + "GL_UNPACK_SKIP_PIXELS\0" + "GL_UNPACK_SKIP_ROWS\0" + "GL_UNPACK_SWAP_BYTES\0" + "GL_UNSIGNED_BYTE\0" + "GL_UNSIGNED_BYTE_2_3_3_REV\0" + "GL_UNSIGNED_BYTE_3_3_2\0" + "GL_UNSIGNED_INT\0" + "GL_UNSIGNED_INT_10_10_10_2\0" + "GL_UNSIGNED_INT_24_8_NV\0" + "GL_UNSIGNED_INT_2_10_10_10_REV\0" + "GL_UNSIGNED_INT_8_8_8_8\0" + "GL_UNSIGNED_INT_8_8_8_8_REV\0" + "GL_UNSIGNED_SHORT\0" + "GL_UNSIGNED_SHORT_1_5_5_5_REV\0" + "GL_UNSIGNED_SHORT_4_4_4_4\0" + "GL_UNSIGNED_SHORT_4_4_4_4_REV\0" + "GL_UNSIGNED_SHORT_5_5_5_1\0" + "GL_UNSIGNED_SHORT_5_6_5\0" + "GL_UNSIGNED_SHORT_5_6_5_REV\0" + "GL_UNSIGNED_SHORT_8_8_APPLE\0" + "GL_UNSIGNED_SHORT_8_8_MESA\0" + "GL_UNSIGNED_SHORT_8_8_REV_APPLE\0" + "GL_UNSIGNED_SHORT_8_8_REV_MESA\0" + "GL_V2F\0" + "GL_V3F\0" + "GL_VENDOR\0" + "GL_VERSION\0" + "GL_VERTEX_ARRAY\0" + "GL_VERTEX_ARRAY_BUFFER_BINDING\0" + "GL_VERTEX_ARRAY_BUFFER_BINDING_ARB\0" + "GL_VERTEX_ARRAY_POINTER\0" + "GL_VERTEX_ARRAY_SIZE\0" + "GL_VERTEX_ARRAY_STRIDE\0" + "GL_VERTEX_ARRAY_TYPE\0" + "GL_VERTEX_ATTRIB_ARRAY0_NV\0" + "GL_VERTEX_ATTRIB_ARRAY10_NV\0" + "GL_VERTEX_ATTRIB_ARRAY11_NV\0" + "GL_VERTEX_ATTRIB_ARRAY12_NV\0" + "GL_VERTEX_ATTRIB_ARRAY13_NV\0" + "GL_VERTEX_ATTRIB_ARRAY14_NV\0" + "GL_VERTEX_ATTRIB_ARRAY15_NV\0" + "GL_VERTEX_ATTRIB_ARRAY1_NV\0" + "GL_VERTEX_ATTRIB_ARRAY2_NV\0" + "GL_VERTEX_ATTRIB_ARRAY3_NV\0" + "GL_VERTEX_ATTRIB_ARRAY4_NV\0" + "GL_VERTEX_ATTRIB_ARRAY5_NV\0" + "GL_VERTEX_ATTRIB_ARRAY6_NV\0" + "GL_VERTEX_ATTRIB_ARRAY7_NV\0" + "GL_VERTEX_ATTRIB_ARRAY8_NV\0" + "GL_VERTEX_ATTRIB_ARRAY9_NV\0" + "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING\0" + "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB\0" + "GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB\0" + "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB\0" + "GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB\0" + "GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB\0" + "GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB\0" + "GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB\0" + "GL_VERTEX_BLEND_ARB\0" + "GL_VERTEX_PROGRAM_ARB\0" + "GL_VERTEX_PROGRAM_BINDING_NV\0" + "GL_VERTEX_PROGRAM_NV\0" + "GL_VERTEX_PROGRAM_POINT_SIZE_ARB\0" + "GL_VERTEX_PROGRAM_POINT_SIZE_NV\0" + "GL_VERTEX_PROGRAM_TWO_SIDE_ARB\0" + "GL_VERTEX_PROGRAM_TWO_SIDE_NV\0" + "GL_VERTEX_SHADER_ARB\0" + "GL_VERTEX_STATE_PROGRAM_NV\0" + "GL_VIEWPORT\0" + "GL_VIEWPORT_BIT\0" + "GL_WEIGHT_ARRAY_ARB\0" + "GL_WEIGHT_ARRAY_BUFFER_BINDING\0" + "GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB\0" + "GL_WEIGHT_ARRAY_POINTER_ARB\0" + "GL_WEIGHT_ARRAY_SIZE_ARB\0" + "GL_WEIGHT_ARRAY_STRIDE_ARB\0" + "GL_WEIGHT_ARRAY_TYPE_ARB\0" + "GL_WEIGHT_SUM_UNITY_ARB\0" + "GL_WRAP_BORDER_SUN\0" + "GL_WRITE_ONLY\0" + "GL_WRITE_ONLY_ARB\0" + "GL_XOR\0" + "GL_YCBCR_422_APPLE\0" + "GL_YCBCR_MESA\0" + "GL_ZERO\0" + "GL_ZOOM_X\0" + "GL_ZOOM_Y\0" + ; + +static const enum_elt all_enums[1612] = +{ + { 0, 0x00000600 }, /* GL_2D */ + { 6, 0x00001407 }, /* GL_2_BYTES */ + { 17, 0x00000601 }, /* GL_3D */ + { 23, 0x00000602 }, /* GL_3D_COLOR */ + { 35, 0x00000603 }, /* GL_3D_COLOR_TEXTURE */ + { 55, 0x00001408 }, /* GL_3_BYTES */ + { 66, 0x00000604 }, /* GL_4D_COLOR_TEXTURE */ + { 86, 0x00001409 }, /* GL_4_BYTES */ + { 97, 0x00000100 }, /* GL_ACCUM */ + { 106, 0x00000D5B }, /* GL_ACCUM_ALPHA_BITS */ + { 126, 0x00000D5A }, /* GL_ACCUM_BLUE_BITS */ + { 145, 0x00000200 }, /* GL_ACCUM_BUFFER_BIT */ + { 165, 0x00000B80 }, /* GL_ACCUM_CLEAR_VALUE */ + { 186, 0x00000D59 }, /* GL_ACCUM_GREEN_BITS */ + { 206, 0x00000D58 }, /* GL_ACCUM_RED_BITS */ + { 224, 0x00008911 }, /* GL_ACTIVE_STENCIL_FACE_EXT */ + { 251, 0x000084E0 }, /* GL_ACTIVE_TEXTURE */ + { 269, 0x000084E0 }, /* GL_ACTIVE_TEXTURE_ARB */ + { 291, 0x000086A5 }, /* GL_ACTIVE_VERTEX_UNITS_ARB */ + { 318, 0x00000104 }, /* GL_ADD */ + { 325, 0x00008574 }, /* GL_ADD_SIGNED */ + { 339, 0x00008574 }, /* GL_ADD_SIGNED_ARB */ + { 357, 0x00008574 }, /* GL_ADD_SIGNED_EXT */ + { 375, 0x0000846E }, /* GL_ALIASED_LINE_WIDTH_RANGE */ + { 403, 0x0000846D }, /* GL_ALIASED_POINT_SIZE_RANGE */ + { 431, 0x000FFFFF }, /* GL_ALL_ATTRIB_BITS */ + { 450, 0xFFFFFFFF }, /* GL_ALL_CLIENT_ATTRIB_BITS */ + { 476, 0x00001906 }, /* GL_ALPHA */ + { 485, 0x0000803D }, /* GL_ALPHA12 */ + { 496, 0x0000803D }, /* GL_ALPHA12_EXT */ + { 511, 0x0000803E }, /* GL_ALPHA16 */ + { 522, 0x0000803E }, /* GL_ALPHA16_EXT */ + { 537, 0x0000803B }, /* GL_ALPHA4 */ + { 547, 0x0000803B }, /* GL_ALPHA4_EXT */ + { 561, 0x0000803C }, /* GL_ALPHA8 */ + { 571, 0x0000803C }, /* GL_ALPHA8_EXT */ + { 585, 0x00000D1D }, /* GL_ALPHA_BIAS */ + { 599, 0x00000D55 }, /* GL_ALPHA_BITS */ + { 613, 0x00000D1C }, /* GL_ALPHA_SCALE */ + { 628, 0x00000BC0 }, /* GL_ALPHA_TEST */ + { 642, 0x00000BC1 }, /* GL_ALPHA_TEST_FUNC */ + { 661, 0x00000BC2 }, /* GL_ALPHA_TEST_REF */ + { 679, 0x00000207 }, /* GL_ALWAYS */ + { 689, 0x00001200 }, /* GL_AMBIENT */ + { 700, 0x00001602 }, /* GL_AMBIENT_AND_DIFFUSE */ + { 723, 0x00001501 }, /* GL_AND */ + { 730, 0x00001504 }, /* GL_AND_INVERTED */ + { 746, 0x00001502 }, /* GL_AND_REVERSE */ + { 761, 0x00008892 }, /* GL_ARRAY_BUFFER */ + { 777, 0x00008892 }, /* GL_ARRAY_BUFFER_ARB */ + { 797, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING */ + { 821, 0x00008894 }, /* GL_ARRAY_BUFFER_BINDING_ARB */ + { 849, 0x00008645 }, /* GL_ATTRIB_ARRAY_POINTER_NV */ + { 876, 0x00008623 }, /* GL_ATTRIB_ARRAY_SIZE_NV */ + { 900, 0x00008624 }, /* GL_ATTRIB_ARRAY_STRIDE_NV */ + { 926, 0x00008625 }, /* GL_ATTRIB_ARRAY_TYPE_NV */ + { 950, 0x00000BB0 }, /* GL_ATTRIB_STACK_DEPTH */ + { 972, 0x00000D80 }, /* GL_AUTO_NORMAL */ + { 987, 0x00000409 }, /* GL_AUX0 */ + { 995, 0x0000040A }, /* GL_AUX1 */ + { 1003, 0x0000040B }, /* GL_AUX2 */ + { 1011, 0x0000040C }, /* GL_AUX3 */ + { 1019, 0x00000C00 }, /* GL_AUX_BUFFERS */ + { 1034, 0x00000405 }, /* GL_BACK */ + { 1042, 0x00000402 }, /* GL_BACK_LEFT */ + { 1055, 0x00000403 }, /* GL_BACK_RIGHT */ + { 1069, 0x000080E0 }, /* GL_BGR */ + { 1076, 0x000080E1 }, /* GL_BGRA */ + { 1084, 0x00001A00 }, /* GL_BITMAP */ + { 1094, 0x00000704 }, /* GL_BITMAP_TOKEN */ + { 1110, 0x00000BE2 }, /* GL_BLEND */ + { 1119, 0x00008005 }, /* GL_BLEND_COLOR */ + { 1134, 0x00008005 }, /* GL_BLEND_COLOR_EXT */ + { 1153, 0x00000BE0 }, /* GL_BLEND_DST */ + { 1166, 0x000080CA }, /* GL_BLEND_DST_ALPHA */ + { 1185, 0x000080C8 }, /* GL_BLEND_DST_RGB */ + { 1202, 0x00008009 }, /* GL_BLEND_EQUATION */ + { 1220, 0x0000883D }, /* GL_BLEND_EQUATION_ALPHA_EXT */ + { 1248, 0x00008009 }, /* GL_BLEND_EQUATION_EXT */ + { 1270, 0x00008009 }, /* GL_BLEND_EQUATION_RGB_EXT */ + { 1296, 0x00000BE1 }, /* GL_BLEND_SRC */ + { 1309, 0x000080CB }, /* GL_BLEND_SRC_ALPHA */ + { 1328, 0x000080C9 }, /* GL_BLEND_SRC_RGB */ + { 1345, 0x00001905 }, /* GL_BLUE */ + { 1353, 0x00000D1B }, /* GL_BLUE_BIAS */ + { 1366, 0x00000D54 }, /* GL_BLUE_BITS */ + { 1379, 0x00000D1A }, /* GL_BLUE_SCALE */ + { 1393, 0x00008B56 }, /* GL_BOOL_ARB */ + { 1405, 0x00008B57 }, /* GL_BOOL_VEC2_ARB */ + { 1422, 0x00008B58 }, /* GL_BOOL_VEC3_ARB */ + { 1439, 0x00008B59 }, /* GL_BOOL_VEC4_ARB */ + { 1456, 0x000088BB }, /* GL_BUFFER_ACCESS */ + { 1473, 0x000088BB }, /* GL_BUFFER_ACCESS_ARB */ + { 1494, 0x000088BC }, /* GL_BUFFER_MAPPED */ + { 1511, 0x000088BC }, /* GL_BUFFER_MAPPED_ARB */ + { 1532, 0x000088BD }, /* GL_BUFFER_MAP_POINTER */ + { 1554, 0x000088BD }, /* GL_BUFFER_MAP_POINTER_ARB */ + { 1580, 0x00008764 }, /* GL_BUFFER_SIZE */ + { 1595, 0x00008764 }, /* GL_BUFFER_SIZE_ARB */ + { 1614, 0x00008765 }, /* GL_BUFFER_USAGE */ + { 1630, 0x00008765 }, /* GL_BUFFER_USAGE_ARB */ + { 1650, 0x00001400 }, /* GL_BYTE */ + { 1658, 0x00002A24 }, /* GL_C3F_V3F */ + { 1669, 0x00002A26 }, /* GL_C4F_N3F_V3F */ + { 1684, 0x00002A22 }, /* GL_C4UB_V2F */ + { 1696, 0x00002A23 }, /* GL_C4UB_V3F */ + { 1708, 0x00000901 }, /* GL_CCW */ + { 1715, 0x00002900 }, /* GL_CLAMP */ + { 1724, 0x0000812D }, /* GL_CLAMP_TO_BORDER */ + { 1743, 0x0000812D }, /* GL_CLAMP_TO_BORDER_ARB */ + { 1766, 0x0000812D }, /* GL_CLAMP_TO_BORDER_SGIS */ + { 1790, 0x0000812F }, /* GL_CLAMP_TO_EDGE */ + { 1807, 0x0000812F }, /* GL_CLAMP_TO_EDGE_SGIS */ + { 1829, 0x00001500 }, /* GL_CLEAR */ + { 1838, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE */ + { 1863, 0x000084E1 }, /* GL_CLIENT_ACTIVE_TEXTURE_ARB */ + { 1892, 0xFFFFFFFF }, /* GL_CLIENT_ALL_ATTRIB_BITS */ + { 1918, 0x00000BB1 }, /* GL_CLIENT_ATTRIB_STACK_DEPTH */ + { 1947, 0x00000001 }, /* GL_CLIENT_PIXEL_STORE_BIT */ + { 1973, 0x00000002 }, /* GL_CLIENT_VERTEX_ARRAY_BIT */ + { 2000, 0x00003000 }, /* GL_CLIP_PLANE0 */ + { 2015, 0x00003001 }, /* GL_CLIP_PLANE1 */ + { 2030, 0x00003002 }, /* GL_CLIP_PLANE2 */ + { 2045, 0x00003003 }, /* GL_CLIP_PLANE3 */ + { 2060, 0x00003004 }, /* GL_CLIP_PLANE4 */ + { 2075, 0x00003005 }, /* GL_CLIP_PLANE5 */ + { 2090, 0x000080F0 }, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */ + { 2123, 0x00000A00 }, /* GL_COEFF */ + { 2132, 0x00001800 }, /* GL_COLOR */ + { 2141, 0x00008076 }, /* GL_COLOR_ARRAY */ + { 2156, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING */ + { 2186, 0x00008898 }, /* GL_COLOR_ARRAY_BUFFER_BINDING_ARB */ + { 2220, 0x00008090 }, /* GL_COLOR_ARRAY_POINTER */ + { 2243, 0x00008081 }, /* GL_COLOR_ARRAY_SIZE */ + { 2263, 0x00008083 }, /* GL_COLOR_ARRAY_STRIDE */ + { 2285, 0x00008082 }, /* GL_COLOR_ARRAY_TYPE */ + { 2305, 0x00008CE0 }, /* GL_COLOR_ATTACHMENT0_EXT */ + { 2330, 0x00008CEA }, /* GL_COLOR_ATTACHMENT10_EXT */ + { 2356, 0x00008CEB }, /* GL_COLOR_ATTACHMENT11_EXT */ + { 2382, 0x00008CEC }, /* GL_COLOR_ATTACHMENT12_EXT */ + { 2408, 0x00008CED }, /* GL_COLOR_ATTACHMENT13_EXT */ + { 2434, 0x00008CEE }, /* GL_COLOR_ATTACHMENT14_EXT */ + { 2460, 0x00008CEF }, /* GL_COLOR_ATTACHMENT15_EXT */ + { 2486, 0x00008CE1 }, /* GL_COLOR_ATTACHMENT1_EXT */ + { 2511, 0x00008CE2 }, /* GL_COLOR_ATTACHMENT2_EXT */ + { 2536, 0x00008CE3 }, /* GL_COLOR_ATTACHMENT3_EXT */ + { 2561, 0x00008CE4 }, /* GL_COLOR_ATTACHMENT4_EXT */ + { 2586, 0x00008CE5 }, /* GL_COLOR_ATTACHMENT5_EXT */ + { 2611, 0x00008CE6 }, /* GL_COLOR_ATTACHMENT6_EXT */ + { 2636, 0x00008CE7 }, /* GL_COLOR_ATTACHMENT7_EXT */ + { 2661, 0x00008CE8 }, /* GL_COLOR_ATTACHMENT8_EXT */ + { 2686, 0x00008CE9 }, /* GL_COLOR_ATTACHMENT9_EXT */ + { 2711, 0x00004000 }, /* GL_COLOR_BUFFER_BIT */ + { 2731, 0x00000C22 }, /* GL_COLOR_CLEAR_VALUE */ + { 2752, 0x00001900 }, /* GL_COLOR_INDEX */ + { 2767, 0x00001603 }, /* GL_COLOR_INDEXES */ + { 2784, 0x00000BF2 }, /* GL_COLOR_LOGIC_OP */ + { 2802, 0x00000B57 }, /* GL_COLOR_MATERIAL */ + { 2820, 0x00000B55 }, /* GL_COLOR_MATERIAL_FACE */ + { 2843, 0x00000B56 }, /* GL_COLOR_MATERIAL_PARAMETER */ + { 2871, 0x000080B1 }, /* GL_COLOR_MATRIX */ + { 2887, 0x000080B1 }, /* GL_COLOR_MATRIX_SGI */ + { 2907, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH */ + { 2935, 0x000080B2 }, /* GL_COLOR_MATRIX_STACK_DEPTH_SGI */ + { 2967, 0x00008458 }, /* GL_COLOR_SUM */ + { 2980, 0x00008458 }, /* GL_COLOR_SUM_ARB */ + { 2997, 0x000080D0 }, /* GL_COLOR_TABLE */ + { 3012, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE */ + { 3038, 0x000080DD }, /* GL_COLOR_TABLE_ALPHA_SIZE_EXT */ + { 3068, 0x000080D7 }, /* GL_COLOR_TABLE_BIAS */ + { 3088, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE */ + { 3113, 0x000080DC }, /* GL_COLOR_TABLE_BLUE_SIZE_EXT */ + { 3142, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT */ + { 3164, 0x000080D8 }, /* GL_COLOR_TABLE_FORMAT_EXT */ + { 3190, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE */ + { 3216, 0x000080DB }, /* GL_COLOR_TABLE_GREEN_SIZE_EXT */ + { 3246, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE */ + { 3276, 0x000080DF }, /* GL_COLOR_TABLE_INTENSITY_SIZE_EXT */ + { 3310, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE */ + { 3340, 0x000080DE }, /* GL_COLOR_TABLE_LUMINANCE_SIZE_EXT */ + { 3374, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE */ + { 3398, 0x000080DA }, /* GL_COLOR_TABLE_RED_SIZE_EXT */ + { 3426, 0x000080D6 }, /* GL_COLOR_TABLE_SCALE */ + { 3447, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH */ + { 3468, 0x000080D9 }, /* GL_COLOR_TABLE_WIDTH_EXT */ + { 3493, 0x00000C23 }, /* GL_COLOR_WRITEMASK */ + { 3512, 0x00008570 }, /* GL_COMBINE */ + { 3523, 0x00008503 }, /* GL_COMBINE4 */ + { 3535, 0x00008572 }, /* GL_COMBINE_ALPHA */ + { 3552, 0x00008572 }, /* GL_COMBINE_ALPHA_ARB */ + { 3573, 0x00008572 }, /* GL_COMBINE_ALPHA_EXT */ + { 3594, 0x00008570 }, /* GL_COMBINE_ARB */ + { 3609, 0x00008570 }, /* GL_COMBINE_EXT */ + { 3624, 0x00008571 }, /* GL_COMBINE_RGB */ + { 3639, 0x00008571 }, /* GL_COMBINE_RGB_ARB */ + { 3658, 0x00008571 }, /* GL_COMBINE_RGB_EXT */ + { 3677, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE */ + { 3701, 0x0000884E }, /* GL_COMPARE_R_TO_TEXTURE_ARB */ + { 3729, 0x00001300 }, /* GL_COMPILE */ + { 3740, 0x00001301 }, /* GL_COMPILE_AND_EXECUTE */ + { 3763, 0x000084E9 }, /* GL_COMPRESSED_ALPHA */ + { 3783, 0x000084E9 }, /* GL_COMPRESSED_ALPHA_ARB */ + { 3807, 0x000084EC }, /* GL_COMPRESSED_INTENSITY */ + { 3831, 0x000084EC }, /* GL_COMPRESSED_INTENSITY_ARB */ + { 3859, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE */ + { 3883, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA */ + { 3913, 0x000084EB }, /* GL_COMPRESSED_LUMINANCE_ALPHA_ARB */ + { 3947, 0x000084EA }, /* GL_COMPRESSED_LUMINANCE_ARB */ + { 3975, 0x000084ED }, /* GL_COMPRESSED_RGB */ + { 3993, 0x000084EE }, /* GL_COMPRESSED_RGBA */ + { 4012, 0x000084EE }, /* GL_COMPRESSED_RGBA_ARB */ + { 4035, 0x000086B1 }, /* GL_COMPRESSED_RGBA_FXT1_3DFX */ + { 4064, 0x000083F1 }, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */ + { 4097, 0x000083F2 }, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */ + { 4130, 0x000083F3 }, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */ + { 4163, 0x000084ED }, /* GL_COMPRESSED_RGB_ARB */ + { 4185, 0x000086B0 }, /* GL_COMPRESSED_RGB_FXT1_3DFX */ + { 4213, 0x000083F0 }, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */ + { 4245, 0x000086A3 }, /* GL_COMPRESSED_TEXTURE_FORMATS */ + { 4275, 0x00008576 }, /* GL_CONSTANT */ + { 4287, 0x00008003 }, /* GL_CONSTANT_ALPHA */ + { 4305, 0x00008003 }, /* GL_CONSTANT_ALPHA_EXT */ + { 4327, 0x00008576 }, /* GL_CONSTANT_ARB */ + { 4343, 0x00001207 }, /* GL_CONSTANT_ATTENUATION */ + { 4367, 0x00008151 }, /* GL_CONSTANT_BORDER_HP */ + { 4389, 0x00008001 }, /* GL_CONSTANT_COLOR */ + { 4407, 0x00008001 }, /* GL_CONSTANT_COLOR_EXT */ + { 4429, 0x00008576 }, /* GL_CONSTANT_EXT */ + { 4445, 0x00008010 }, /* GL_CONVOLUTION_1D */ + { 4463, 0x00008011 }, /* GL_CONVOLUTION_2D */ + { 4481, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR */ + { 4509, 0x00008154 }, /* GL_CONVOLUTION_BORDER_COLOR_HP */ + { 4540, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE */ + { 4567, 0x00008013 }, /* GL_CONVOLUTION_BORDER_MODE_EXT */ + { 4598, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS */ + { 4625, 0x00008015 }, /* GL_CONVOLUTION_FILTER_BIAS_EXT */ + { 4656, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE */ + { 4684, 0x00008014 }, /* GL_CONVOLUTION_FILTER_SCALE_EXT */ + { 4716, 0x00008017 }, /* GL_CONVOLUTION_FORMAT */ + { 4738, 0x00008017 }, /* GL_CONVOLUTION_FORMAT_EXT */ + { 4764, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT */ + { 4786, 0x00008019 }, /* GL_CONVOLUTION_HEIGHT_EXT */ + { 4812, 0x00008018 }, /* GL_CONVOLUTION_WIDTH */ + { 4833, 0x00008018 }, /* GL_CONVOLUTION_WIDTH_EXT */ + { 4858, 0x00008862 }, /* GL_COORD_REPLACE_ARB */ + { 4879, 0x00008862 }, /* GL_COORD_REPLACE_NV */ + { 4899, 0x00001503 }, /* GL_COPY */ + { 4907, 0x0000150C }, /* GL_COPY_INVERTED */ + { 4924, 0x00000706 }, /* GL_COPY_PIXEL_TOKEN */ + { 4944, 0x00000B44 }, /* GL_CULL_FACE */ + { 4957, 0x00000B45 }, /* GL_CULL_FACE_MODE */ + { 4975, 0x000081AA }, /* GL_CULL_VERTEX_EXT */ + { 4994, 0x000081AC }, /* GL_CULL_VERTEX_EYE_POSITION_EXT */ + { 5026, 0x000081AB }, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */ + { 5061, 0x00008626 }, /* GL_CURRENT_ATTRIB_NV */ + { 5082, 0x00000001 }, /* GL_CURRENT_BIT */ + { 5097, 0x00000B00 }, /* GL_CURRENT_COLOR */ + { 5114, 0x00008453 }, /* GL_CURRENT_FOG_COORD */ + { 5135, 0x00008453 }, /* GL_CURRENT_FOG_COORDINATE */ + { 5161, 0x00000B01 }, /* GL_CURRENT_INDEX */ + { 5178, 0x00008641 }, /* GL_CURRENT_MATRIX_ARB */ + { 5200, 0x00008845 }, /* GL_CURRENT_MATRIX_INDEX_ARB */ + { 5228, 0x00008641 }, /* GL_CURRENT_MATRIX_NV */ + { 5249, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */ + { 5283, 0x00008640 }, /* GL_CURRENT_MATRIX_STACK_DEPTH_NV */ + { 5316, 0x00000B02 }, /* GL_CURRENT_NORMAL */ + { 5334, 0x00008843 }, /* GL_CURRENT_PALETTE_MATRIX_ARB */ + { 5364, 0x00008865 }, /* GL_CURRENT_QUERY */ + { 5381, 0x00008865 }, /* GL_CURRENT_QUERY_ARB */ + { 5402, 0x00000B04 }, /* GL_CURRENT_RASTER_COLOR */ + { 5426, 0x00000B09 }, /* GL_CURRENT_RASTER_DISTANCE */ + { 5453, 0x00000B05 }, /* GL_CURRENT_RASTER_INDEX */ + { 5477, 0x00000B07 }, /* GL_CURRENT_RASTER_POSITION */ + { 5504, 0x00000B08 }, /* GL_CURRENT_RASTER_POSITION_VALID */ + { 5537, 0x00000B06 }, /* GL_CURRENT_RASTER_TEXTURE_COORDS */ + { 5570, 0x00008459 }, /* GL_CURRENT_SECONDARY_COLOR */ + { 5597, 0x00000B03 }, /* GL_CURRENT_TEXTURE_COORDS */ + { 5623, 0x00008626 }, /* GL_CURRENT_VERTEX_ATTRIB_ARB */ + { 5652, 0x000086A8 }, /* GL_CURRENT_WEIGHT_ARB */ + { 5674, 0x00000900 }, /* GL_CW */ + { 5680, 0x00002101 }, /* GL_DECAL */ + { 5689, 0x00001E03 }, /* GL_DECR */ + { 5697, 0x00008508 }, /* GL_DECR_WRAP */ + { 5710, 0x00008508 }, /* GL_DECR_WRAP_EXT */ + { 5727, 0x00001801 }, /* GL_DEPTH */ + { 5736, 0x00008D00 }, /* GL_DEPTH_ATTACHMENT_EXT */ + { 5760, 0x00000D1F }, /* GL_DEPTH_BIAS */ + { 5774, 0x00000D56 }, /* GL_DEPTH_BITS */ + { 5788, 0x00008891 }, /* GL_DEPTH_BOUNDS_EXT */ + { 5808, 0x00008890 }, /* GL_DEPTH_BOUNDS_TEST_EXT */ + { 5833, 0x00000100 }, /* GL_DEPTH_BUFFER_BIT */ + { 5853, 0x0000864F }, /* GL_DEPTH_CLAMP_NV */ + { 5871, 0x00000B73 }, /* GL_DEPTH_CLEAR_VALUE */ + { 5892, 0x00001902 }, /* GL_DEPTH_COMPONENT */ + { 5911, 0x000081A5 }, /* GL_DEPTH_COMPONENT16 */ + { 5932, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_ARB */ + { 5957, 0x000081A5 }, /* GL_DEPTH_COMPONENT16_SGIX */ + { 5983, 0x000081A6 }, /* GL_DEPTH_COMPONENT24 */ + { 6004, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_ARB */ + { 6029, 0x000081A6 }, /* GL_DEPTH_COMPONENT24_SGIX */ + { 6055, 0x000081A7 }, /* GL_DEPTH_COMPONENT32 */ + { 6076, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_ARB */ + { 6101, 0x000081A7 }, /* GL_DEPTH_COMPONENT32_SGIX */ + { 6127, 0x00000B74 }, /* GL_DEPTH_FUNC */ + { 6141, 0x00000B70 }, /* GL_DEPTH_RANGE */ + { 6156, 0x00000D1E }, /* GL_DEPTH_SCALE */ + { 6171, 0x000084F9 }, /* GL_DEPTH_STENCIL_NV */ + { 6191, 0x0000886F }, /* GL_DEPTH_STENCIL_TO_BGRA_NV */ + { 6219, 0x0000886E }, /* GL_DEPTH_STENCIL_TO_RGBA_NV */ + { 6247, 0x00000B71 }, /* GL_DEPTH_TEST */ + { 6261, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE */ + { 6283, 0x0000884B }, /* GL_DEPTH_TEXTURE_MODE_ARB */ + { 6309, 0x00000B72 }, /* GL_DEPTH_WRITEMASK */ + { 6328, 0x00001201 }, /* GL_DIFFUSE */ + { 6339, 0x00000BD0 }, /* GL_DITHER */ + { 6349, 0x00000A02 }, /* GL_DOMAIN */ + { 6359, 0x00001100 }, /* GL_DONT_CARE */ + { 6372, 0x000086AE }, /* GL_DOT3_RGB */ + { 6384, 0x000086AF }, /* GL_DOT3_RGBA */ + { 6397, 0x000086AF }, /* GL_DOT3_RGBA_ARB */ + { 6414, 0x00008741 }, /* GL_DOT3_RGBA_EXT */ + { 6431, 0x000086AE }, /* GL_DOT3_RGB_ARB */ + { 6447, 0x00008740 }, /* GL_DOT3_RGB_EXT */ + { 6463, 0x0000140A }, /* GL_DOUBLE */ + { 6473, 0x00000C32 }, /* GL_DOUBLEBUFFER */ + { 6489, 0x00000C01 }, /* GL_DRAW_BUFFER */ + { 6504, 0x00008825 }, /* GL_DRAW_BUFFER0_ARB */ + { 6524, 0x00008825 }, /* GL_DRAW_BUFFER0_ATI */ + { 6544, 0x0000882F }, /* GL_DRAW_BUFFER10_ARB */ + { 6565, 0x0000882F }, /* GL_DRAW_BUFFER10_ATI */ + { 6586, 0x00008830 }, /* GL_DRAW_BUFFER11_ARB */ + { 6607, 0x00008830 }, /* GL_DRAW_BUFFER11_ATI */ + { 6628, 0x00008831 }, /* GL_DRAW_BUFFER12_ARB */ + { 6649, 0x00008831 }, /* GL_DRAW_BUFFER12_ATI */ + { 6670, 0x00008832 }, /* GL_DRAW_BUFFER13_ARB */ + { 6691, 0x00008832 }, /* GL_DRAW_BUFFER13_ATI */ + { 6712, 0x00008833 }, /* GL_DRAW_BUFFER14_ARB */ + { 6733, 0x00008833 }, /* GL_DRAW_BUFFER14_ATI */ + { 6754, 0x00008834 }, /* GL_DRAW_BUFFER15_ARB */ + { 6775, 0x00008834 }, /* GL_DRAW_BUFFER15_ATI */ + { 6796, 0x00008826 }, /* GL_DRAW_BUFFER1_ARB */ + { 6816, 0x00008826 }, /* GL_DRAW_BUFFER1_ATI */ + { 6836, 0x00008827 }, /* GL_DRAW_BUFFER2_ARB */ + { 6856, 0x00008827 }, /* GL_DRAW_BUFFER2_ATI */ + { 6876, 0x00008828 }, /* GL_DRAW_BUFFER3_ARB */ + { 6896, 0x00008828 }, /* GL_DRAW_BUFFER3_ATI */ + { 6916, 0x00008829 }, /* GL_DRAW_BUFFER4_ARB */ + { 6936, 0x00008829 }, /* GL_DRAW_BUFFER4_ATI */ + { 6956, 0x0000882A }, /* GL_DRAW_BUFFER5_ARB */ + { 6976, 0x0000882A }, /* GL_DRAW_BUFFER5_ATI */ + { 6996, 0x0000882B }, /* GL_DRAW_BUFFER6_ARB */ + { 7016, 0x0000882B }, /* GL_DRAW_BUFFER6_ATI */ + { 7036, 0x0000882C }, /* GL_DRAW_BUFFER7_ARB */ + { 7056, 0x0000882C }, /* GL_DRAW_BUFFER7_ATI */ + { 7076, 0x0000882D }, /* GL_DRAW_BUFFER8_ARB */ + { 7096, 0x0000882D }, /* GL_DRAW_BUFFER8_ATI */ + { 7116, 0x0000882E }, /* GL_DRAW_BUFFER9_ARB */ + { 7136, 0x0000882E }, /* GL_DRAW_BUFFER9_ATI */ + { 7156, 0x00000705 }, /* GL_DRAW_PIXEL_TOKEN */ + { 7176, 0x00000304 }, /* GL_DST_ALPHA */ + { 7189, 0x00000306 }, /* GL_DST_COLOR */ + { 7202, 0x000088EA }, /* GL_DYNAMIC_COPY */ + { 7218, 0x000088EA }, /* GL_DYNAMIC_COPY_ARB */ + { 7238, 0x000088E8 }, /* GL_DYNAMIC_DRAW */ + { 7254, 0x000088E8 }, /* GL_DYNAMIC_DRAW_ARB */ + { 7274, 0x000088E9 }, /* GL_DYNAMIC_READ */ + { 7290, 0x000088E9 }, /* GL_DYNAMIC_READ_ARB */ + { 7310, 0x00000B43 }, /* GL_EDGE_FLAG */ + { 7323, 0x00008079 }, /* GL_EDGE_FLAG_ARRAY */ + { 7342, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */ + { 7376, 0x0000889B }, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB */ + { 7414, 0x00008093 }, /* GL_EDGE_FLAG_ARRAY_POINTER */ + { 7441, 0x0000808C }, /* GL_EDGE_FLAG_ARRAY_STRIDE */ + { 7467, 0x00008893 }, /* GL_ELEMENT_ARRAY_BUFFER */ + { 7491, 0x00008893 }, /* GL_ELEMENT_ARRAY_BUFFER_ARB */ + { 7519, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */ + { 7551, 0x00008895 }, /* GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB */ + { 7587, 0x00001600 }, /* GL_EMISSION */ + { 7599, 0x00002000 }, /* GL_ENABLE_BIT */ + { 7613, 0x00000202 }, /* GL_EQUAL */ + { 7622, 0x00001509 }, /* GL_EQUIV */ + { 7631, 0x00010000 }, /* GL_EVAL_BIT */ + { 7643, 0x00000800 }, /* GL_EXP */ + { 7650, 0x00000801 }, /* GL_EXP2 */ + { 7658, 0x00001F03 }, /* GL_EXTENSIONS */ + { 7672, 0x00002400 }, /* GL_EYE_LINEAR */ + { 7686, 0x00002502 }, /* GL_EYE_PLANE */ + { 7699, 0x0000855C }, /* GL_EYE_PLANE_ABSOLUTE_NV */ + { 7724, 0x0000855B }, /* GL_EYE_RADIAL_NV */ + { 7741, 0x00000000 }, /* GL_FALSE */ + { 7750, 0x00001101 }, /* GL_FASTEST */ + { 7761, 0x00001C01 }, /* GL_FEEDBACK */ + { 7773, 0x00000DF0 }, /* GL_FEEDBACK_BUFFER_POINTER */ + { 7800, 0x00000DF1 }, /* GL_FEEDBACK_BUFFER_SIZE */ + { 7824, 0x00000DF2 }, /* GL_FEEDBACK_BUFFER_TYPE */ + { 7848, 0x00001B02 }, /* GL_FILL */ + { 7856, 0x00001D00 }, /* GL_FLAT */ + { 7864, 0x00001406 }, /* GL_FLOAT */ + { 7873, 0x00008B5A }, /* GL_FLOAT_MAT2_ARB */ + { 7891, 0x00008B5B }, /* GL_FLOAT_MAT3_ARB */ + { 7909, 0x00008B5C }, /* GL_FLOAT_MAT4_ARB */ + { 7927, 0x00008B50 }, /* GL_FLOAT_VEC2_ARB */ + { 7945, 0x00008B51 }, /* GL_FLOAT_VEC3_ARB */ + { 7963, 0x00008B52 }, /* GL_FLOAT_VEC4_ARB */ + { 7981, 0x00000B60 }, /* GL_FOG */ + { 7988, 0x00000080 }, /* GL_FOG_BIT */ + { 7999, 0x00000B66 }, /* GL_FOG_COLOR */ + { 8012, 0x00008451 }, /* GL_FOG_COORD */ + { 8025, 0x00008451 }, /* GL_FOG_COORDINATE */ + { 8043, 0x00008457 }, /* GL_FOG_COORDINATE_ARRAY */ + { 8067, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */ + { 8106, 0x0000889D }, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB */ + { 8149, 0x00008456 }, /* GL_FOG_COORDINATE_ARRAY_POINTER */ + { 8181, 0x00008455 }, /* GL_FOG_COORDINATE_ARRAY_STRIDE */ + { 8212, 0x00008454 }, /* GL_FOG_COORDINATE_ARRAY_TYPE */ + { 8241, 0x00008450 }, /* GL_FOG_COORDINATE_SOURCE */ + { 8266, 0x00008457 }, /* GL_FOG_COORD_ARRAY */ + { 8285, 0x0000889D }, /* GL_FOG_COORD_ARRAY_BUFFER_BINDING */ + { 8319, 0x00008456 }, /* GL_FOG_COORD_ARRAY_POINTER */ + { 8346, 0x00008455 }, /* GL_FOG_COORD_ARRAY_STRIDE */ + { 8372, 0x00008454 }, /* GL_FOG_COORD_ARRAY_TYPE */ + { 8396, 0x00008450 }, /* GL_FOG_COORD_SOURCE */ + { 8416, 0x00000B62 }, /* GL_FOG_DENSITY */ + { 8431, 0x0000855A }, /* GL_FOG_DISTANCE_MODE_NV */ + { 8455, 0x00000B64 }, /* GL_FOG_END */ + { 8466, 0x00000C54 }, /* GL_FOG_HINT */ + { 8478, 0x00000B61 }, /* GL_FOG_INDEX */ + { 8491, 0x00000B65 }, /* GL_FOG_MODE */ + { 8503, 0x00008198 }, /* GL_FOG_OFFSET_SGIX */ + { 8522, 0x00008199 }, /* GL_FOG_OFFSET_VALUE_SGIX */ + { 8547, 0x00000B63 }, /* GL_FOG_START */ + { 8560, 0x00008452 }, /* GL_FRAGMENT_DEPTH */ + { 8578, 0x00008804 }, /* GL_FRAGMENT_PROGRAM_ARB */ + { 8602, 0x00008B30 }, /* GL_FRAGMENT_SHADER_ARB */ + { 8625, 0x00008CD1 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT */ + { 8667, 0x00008CD0 }, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT */ + { 8709, 0x00008CD4 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT */ + { 8758, 0x00008CD3 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT */ + { 8810, 0x00008CD2 }, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT */ + { 8854, 0x00008CA6 }, /* GL_FRAMEBUFFER_BINDING_EXT */ + { 8881, 0x00008CD5 }, /* GL_FRAMEBUFFER_COMPLETE_EXT */ + { 8909, 0x00008D40 }, /* GL_FRAMEBUFFER_EXT */ + { 8928, 0x00008CD6 }, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT */ + { 8969, 0x00008CD9 }, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */ + { 9010, 0x00008CDB }, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */ + { 9052, 0x00008CD8 }, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */ + { 9103, 0x00008CDA }, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */ + { 9141, 0x00008CD7 }, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT */ + { 9190, 0x00008CDC }, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */ + { 9232, 0x00008CDE }, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */ + { 9264, 0x00008CDD }, /* GL_FRAMEBUFFER_UNSUPPORTED_EXT */ + { 9295, 0x00000404 }, /* GL_FRONT */ + { 9304, 0x00000408 }, /* GL_FRONT_AND_BACK */ + { 9322, 0x00000B46 }, /* GL_FRONT_FACE */ + { 9336, 0x00000400 }, /* GL_FRONT_LEFT */ + { 9350, 0x00000401 }, /* GL_FRONT_RIGHT */ + { 9365, 0x00008006 }, /* GL_FUNC_ADD */ + { 9377, 0x00008006 }, /* GL_FUNC_ADD_EXT */ + { 9393, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT */ + { 9418, 0x0000800B }, /* GL_FUNC_REVERSE_SUBTRACT_EXT */ + { 9447, 0x0000800A }, /* GL_FUNC_SUBTRACT */ + { 9464, 0x0000800A }, /* GL_FUNC_SUBTRACT_EXT */ + { 9485, 0x00008191 }, /* GL_GENERATE_MIPMAP */ + { 9504, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT */ + { 9528, 0x00008192 }, /* GL_GENERATE_MIPMAP_HINT_SGIS */ + { 9557, 0x00008191 }, /* GL_GENERATE_MIPMAP_SGIS */ + { 9581, 0x00000206 }, /* GL_GEQUAL */ + { 9591, 0x00000204 }, /* GL_GREATER */ + { 9602, 0x00001904 }, /* GL_GREEN */ + { 9611, 0x00000D19 }, /* GL_GREEN_BIAS */ + { 9625, 0x00000D53 }, /* GL_GREEN_BITS */ + { 9639, 0x00000D18 }, /* GL_GREEN_SCALE */ + { 9654, 0x00008000 }, /* GL_HINT_BIT */ + { 9666, 0x00008024 }, /* GL_HISTOGRAM */ + { 9679, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE */ + { 9703, 0x0000802B }, /* GL_HISTOGRAM_ALPHA_SIZE_EXT */ + { 9731, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE */ + { 9754, 0x0000802A }, /* GL_HISTOGRAM_BLUE_SIZE_EXT */ + { 9781, 0x00008024 }, /* GL_HISTOGRAM_EXT */ + { 9798, 0x00008027 }, /* GL_HISTOGRAM_FORMAT */ + { 9818, 0x00008027 }, /* GL_HISTOGRAM_FORMAT_EXT */ + { 9842, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE */ + { 9866, 0x00008029 }, /* GL_HISTOGRAM_GREEN_SIZE_EXT */ + { 9894, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE */ + { 9922, 0x0000802C }, /* GL_HISTOGRAM_LUMINANCE_SIZE_EXT */ + { 9954, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE */ + { 9976, 0x00008028 }, /* GL_HISTOGRAM_RED_SIZE_EXT */ + { 10002, 0x0000802D }, /* GL_HISTOGRAM_SINK */ + { 10020, 0x0000802D }, /* GL_HISTOGRAM_SINK_EXT */ + { 10042, 0x00008026 }, /* GL_HISTOGRAM_WIDTH */ + { 10061, 0x00008026 }, /* GL_HISTOGRAM_WIDTH_EXT */ + { 10084, 0x0000862A }, /* GL_IDENTITY_NV */ + { 10099, 0x00008150 }, /* GL_IGNORE_BORDER_HP */ + { 10119, 0x00008B9B }, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */ + { 10159, 0x00008B9A }, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */ + { 10197, 0x00001E02 }, /* GL_INCR */ + { 10205, 0x00008507 }, /* GL_INCR_WRAP */ + { 10218, 0x00008507 }, /* GL_INCR_WRAP_EXT */ + { 10235, 0x00008077 }, /* GL_INDEX_ARRAY */ + { 10250, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING */ + { 10280, 0x00008899 }, /* GL_INDEX_ARRAY_BUFFER_BINDING_ARB */ + { 10314, 0x00008091 }, /* GL_INDEX_ARRAY_POINTER */ + { 10337, 0x00008086 }, /* GL_INDEX_ARRAY_STRIDE */ + { 10359, 0x00008085 }, /* GL_INDEX_ARRAY_TYPE */ + { 10379, 0x00000D51 }, /* GL_INDEX_BITS */ + { 10393, 0x00000C20 }, /* GL_INDEX_CLEAR_VALUE */ + { 10414, 0x00000BF1 }, /* GL_INDEX_LOGIC_OP */ + { 10432, 0x00000C30 }, /* GL_INDEX_MODE */ + { 10446, 0x00000D13 }, /* GL_INDEX_OFFSET */ + { 10462, 0x00000D12 }, /* GL_INDEX_SHIFT */ + { 10477, 0x00000C21 }, /* GL_INDEX_WRITEMASK */ + { 10496, 0x00001404 }, /* GL_INT */ + { 10503, 0x00008049 }, /* GL_INTENSITY */ + { 10516, 0x0000804C }, /* GL_INTENSITY12 */ + { 10531, 0x0000804C }, /* GL_INTENSITY12_EXT */ + { 10550, 0x0000804D }, /* GL_INTENSITY16 */ + { 10565, 0x0000804D }, /* GL_INTENSITY16_EXT */ + { 10584, 0x0000804A }, /* GL_INTENSITY4 */ + { 10598, 0x0000804A }, /* GL_INTENSITY4_EXT */ + { 10616, 0x0000804B }, /* GL_INTENSITY8 */ + { 10630, 0x0000804B }, /* GL_INTENSITY8_EXT */ + { 10648, 0x00008049 }, /* GL_INTENSITY_EXT */ + { 10665, 0x00008575 }, /* GL_INTERPOLATE */ + { 10680, 0x00008575 }, /* GL_INTERPOLATE_ARB */ + { 10699, 0x00008575 }, /* GL_INTERPOLATE_EXT */ + { 10718, 0x00008B53 }, /* GL_INT_VEC2_ARB */ + { 10734, 0x00008B54 }, /* GL_INT_VEC3_ARB */ + { 10750, 0x00008B55 }, /* GL_INT_VEC4_ARB */ + { 10766, 0x00000500 }, /* GL_INVALID_ENUM */ + { 10782, 0x00000506 }, /* GL_INVALID_FRAMEBUFFER_OPERATION_EXT */ + { 10819, 0x00000502 }, /* GL_INVALID_OPERATION */ + { 10840, 0x00000501 }, /* GL_INVALID_VALUE */ + { 10857, 0x0000862B }, /* GL_INVERSE_NV */ + { 10871, 0x0000862D }, /* GL_INVERSE_TRANSPOSE_NV */ + { 10895, 0x0000150A }, /* GL_INVERT */ + { 10905, 0x00001E00 }, /* GL_KEEP */ + { 10913, 0x00000406 }, /* GL_LEFT */ + { 10921, 0x00000203 }, /* GL_LEQUAL */ + { 10931, 0x00000201 }, /* GL_LESS */ + { 10939, 0x00004000 }, /* GL_LIGHT0 */ + { 10949, 0x00004001 }, /* GL_LIGHT1 */ + { 10959, 0x00004002 }, /* GL_LIGHT2 */ + { 10969, 0x00004003 }, /* GL_LIGHT3 */ + { 10979, 0x00004004 }, /* GL_LIGHT4 */ + { 10989, 0x00004005 }, /* GL_LIGHT5 */ + { 10999, 0x00004006 }, /* GL_LIGHT6 */ + { 11009, 0x00004007 }, /* GL_LIGHT7 */ + { 11019, 0x00000B50 }, /* GL_LIGHTING */ + { 11031, 0x00000040 }, /* GL_LIGHTING_BIT */ + { 11047, 0x00000B53 }, /* GL_LIGHT_MODEL_AMBIENT */ + { 11070, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL */ + { 11099, 0x000081F8 }, /* GL_LIGHT_MODEL_COLOR_CONTROL_EXT */ + { 11132, 0x00000B51 }, /* GL_LIGHT_MODEL_LOCAL_VIEWER */ + { 11160, 0x00000B52 }, /* GL_LIGHT_MODEL_TWO_SIDE */ + { 11184, 0x00001B01 }, /* GL_LINE */ + { 11192, 0x00002601 }, /* GL_LINEAR */ + { 11202, 0x00001208 }, /* GL_LINEAR_ATTENUATION */ + { 11224, 0x00008170 }, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */ + { 11254, 0x0000844F }, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */ + { 11285, 0x00002703 }, /* GL_LINEAR_MIPMAP_LINEAR */ + { 11309, 0x00002701 }, /* GL_LINEAR_MIPMAP_NEAREST */ + { 11334, 0x00000001 }, /* GL_LINES */ + { 11343, 0x00000004 }, /* GL_LINE_BIT */ + { 11355, 0x00000002 }, /* GL_LINE_LOOP */ + { 11368, 0x00000707 }, /* GL_LINE_RESET_TOKEN */ + { 11388, 0x00000B20 }, /* GL_LINE_SMOOTH */ + { 11403, 0x00000C52 }, /* GL_LINE_SMOOTH_HINT */ + { 11423, 0x00000B24 }, /* GL_LINE_STIPPLE */ + { 11439, 0x00000B25 }, /* GL_LINE_STIPPLE_PATTERN */ + { 11463, 0x00000B26 }, /* GL_LINE_STIPPLE_REPEAT */ + { 11486, 0x00000003 }, /* GL_LINE_STRIP */ + { 11500, 0x00000702 }, /* GL_LINE_TOKEN */ + { 11514, 0x00000B21 }, /* GL_LINE_WIDTH */ + { 11528, 0x00000B23 }, /* GL_LINE_WIDTH_GRANULARITY */ + { 11554, 0x00000B22 }, /* GL_LINE_WIDTH_RANGE */ + { 11574, 0x00000B32 }, /* GL_LIST_BASE */ + { 11587, 0x00020000 }, /* GL_LIST_BIT */ + { 11599, 0x00000B33 }, /* GL_LIST_INDEX */ + { 11613, 0x00000B30 }, /* GL_LIST_MODE */ + { 11626, 0x00000101 }, /* GL_LOAD */ + { 11634, 0x00000BF1 }, /* GL_LOGIC_OP */ + { 11646, 0x00000BF0 }, /* GL_LOGIC_OP_MODE */ + { 11663, 0x00001909 }, /* GL_LUMINANCE */ + { 11676, 0x00008041 }, /* GL_LUMINANCE12 */ + { 11691, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12 */ + { 11714, 0x00008047 }, /* GL_LUMINANCE12_ALPHA12_EXT */ + { 11741, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4 */ + { 11763, 0x00008046 }, /* GL_LUMINANCE12_ALPHA4_EXT */ + { 11789, 0x00008041 }, /* GL_LUMINANCE12_EXT */ + { 11808, 0x00008042 }, /* GL_LUMINANCE16 */ + { 11823, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16 */ + { 11846, 0x00008048 }, /* GL_LUMINANCE16_ALPHA16_EXT */ + { 11873, 0x00008042 }, /* GL_LUMINANCE16_EXT */ + { 11892, 0x0000803F }, /* GL_LUMINANCE4 */ + { 11906, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4 */ + { 11927, 0x00008043 }, /* GL_LUMINANCE4_ALPHA4_EXT */ + { 11952, 0x0000803F }, /* GL_LUMINANCE4_EXT */ + { 11970, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2 */ + { 11991, 0x00008044 }, /* GL_LUMINANCE6_ALPHA2_EXT */ + { 12016, 0x00008040 }, /* GL_LUMINANCE8 */ + { 12030, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8 */ + { 12051, 0x00008045 }, /* GL_LUMINANCE8_ALPHA8_EXT */ + { 12076, 0x00008040 }, /* GL_LUMINANCE8_EXT */ + { 12094, 0x0000190A }, /* GL_LUMINANCE_ALPHA */ + { 12113, 0x00000D90 }, /* GL_MAP1_COLOR_4 */ + { 12129, 0x00000DD0 }, /* GL_MAP1_GRID_DOMAIN */ + { 12149, 0x00000DD1 }, /* GL_MAP1_GRID_SEGMENTS */ + { 12171, 0x00000D91 }, /* GL_MAP1_INDEX */ + { 12185, 0x00000D92 }, /* GL_MAP1_NORMAL */ + { 12200, 0x00000D93 }, /* GL_MAP1_TEXTURE_COORD_1 */ + { 12224, 0x00000D94 }, /* GL_MAP1_TEXTURE_COORD_2 */ + { 12248, 0x00000D95 }, /* GL_MAP1_TEXTURE_COORD_3 */ + { 12272, 0x00000D96 }, /* GL_MAP1_TEXTURE_COORD_4 */ + { 12296, 0x00000D97 }, /* GL_MAP1_VERTEX_3 */ + { 12313, 0x00000D98 }, /* GL_MAP1_VERTEX_4 */ + { 12330, 0x00008660 }, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */ + { 12358, 0x0000866A }, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */ + { 12387, 0x0000866B }, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */ + { 12416, 0x0000866C }, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */ + { 12445, 0x0000866D }, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */ + { 12474, 0x0000866E }, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */ + { 12503, 0x0000866F }, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */ + { 12532, 0x00008661 }, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */ + { 12560, 0x00008662 }, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */ + { 12588, 0x00008663 }, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */ + { 12616, 0x00008664 }, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */ + { 12644, 0x00008665 }, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */ + { 12672, 0x00008666 }, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */ + { 12700, 0x00008667 }, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */ + { 12728, 0x00008668 }, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */ + { 12756, 0x00008669 }, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */ + { 12784, 0x00000DB0 }, /* GL_MAP2_COLOR_4 */ + { 12800, 0x00000DD2 }, /* GL_MAP2_GRID_DOMAIN */ + { 12820, 0x00000DD3 }, /* GL_MAP2_GRID_SEGMENTS */ + { 12842, 0x00000DB1 }, /* GL_MAP2_INDEX */ + { 12856, 0x00000DB2 }, /* GL_MAP2_NORMAL */ + { 12871, 0x00000DB3 }, /* GL_MAP2_TEXTURE_COORD_1 */ + { 12895, 0x00000DB4 }, /* GL_MAP2_TEXTURE_COORD_2 */ + { 12919, 0x00000DB5 }, /* GL_MAP2_TEXTURE_COORD_3 */ + { 12943, 0x00000DB6 }, /* GL_MAP2_TEXTURE_COORD_4 */ + { 12967, 0x00000DB7 }, /* GL_MAP2_VERTEX_3 */ + { 12984, 0x00000DB8 }, /* GL_MAP2_VERTEX_4 */ + { 13001, 0x00008670 }, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */ + { 13029, 0x0000867A }, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */ + { 13058, 0x0000867B }, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */ + { 13087, 0x0000867C }, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */ + { 13116, 0x0000867D }, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */ + { 13145, 0x0000867E }, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */ + { 13174, 0x0000867F }, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */ + { 13203, 0x00008671 }, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */ + { 13231, 0x00008672 }, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */ + { 13259, 0x00008673 }, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */ + { 13287, 0x00008674 }, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */ + { 13315, 0x00008675 }, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */ + { 13343, 0x00008676 }, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */ + { 13371, 0x00008677 }, /* GL_MAP2_VERTEX_ATTRIB7_4_NV */ + { 13399, 0x00008678 }, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */ + { 13427, 0x00008679 }, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */ + { 13455, 0x00000D10 }, /* GL_MAP_COLOR */ + { 13468, 0x00000D11 }, /* GL_MAP_STENCIL */ + { 13483, 0x000088C0 }, /* GL_MATRIX0_ARB */ + { 13498, 0x00008630 }, /* GL_MATRIX0_NV */ + { 13512, 0x000088CA }, /* GL_MATRIX10_ARB */ + { 13528, 0x000088CB }, /* GL_MATRIX11_ARB */ + { 13544, 0x000088CC }, /* GL_MATRIX12_ARB */ + { 13560, 0x000088CD }, /* GL_MATRIX13_ARB */ + { 13576, 0x000088CE }, /* GL_MATRIX14_ARB */ + { 13592, 0x000088CF }, /* GL_MATRIX15_ARB */ + { 13608, 0x000088D0 }, /* GL_MATRIX16_ARB */ + { 13624, 0x000088D1 }, /* GL_MATRIX17_ARB */ + { 13640, 0x000088D2 }, /* GL_MATRIX18_ARB */ + { 13656, 0x000088D3 }, /* GL_MATRIX19_ARB */ + { 13672, 0x000088C1 }, /* GL_MATRIX1_ARB */ + { 13687, 0x00008631 }, /* GL_MATRIX1_NV */ + { 13701, 0x000088D4 }, /* GL_MATRIX20_ARB */ + { 13717, 0x000088D5 }, /* GL_MATRIX21_ARB */ + { 13733, 0x000088D6 }, /* GL_MATRIX22_ARB */ + { 13749, 0x000088D7 }, /* GL_MATRIX23_ARB */ + { 13765, 0x000088D8 }, /* GL_MATRIX24_ARB */ + { 13781, 0x000088D9 }, /* GL_MATRIX25_ARB */ + { 13797, 0x000088DA }, /* GL_MATRIX26_ARB */ + { 13813, 0x000088DB }, /* GL_MATRIX27_ARB */ + { 13829, 0x000088DC }, /* GL_MATRIX28_ARB */ + { 13845, 0x000088DD }, /* GL_MATRIX29_ARB */ + { 13861, 0x000088C2 }, /* GL_MATRIX2_ARB */ + { 13876, 0x00008632 }, /* GL_MATRIX2_NV */ + { 13890, 0x000088DE }, /* GL_MATRIX30_ARB */ + { 13906, 0x000088DF }, /* GL_MATRIX31_ARB */ + { 13922, 0x000088C3 }, /* GL_MATRIX3_ARB */ + { 13937, 0x00008633 }, /* GL_MATRIX3_NV */ + { 13951, 0x000088C4 }, /* GL_MATRIX4_ARB */ + { 13966, 0x00008634 }, /* GL_MATRIX4_NV */ + { 13980, 0x000088C5 }, /* GL_MATRIX5_ARB */ + { 13995, 0x00008635 }, /* GL_MATRIX5_NV */ + { 14009, 0x000088C6 }, /* GL_MATRIX6_ARB */ + { 14024, 0x00008636 }, /* GL_MATRIX6_NV */ + { 14038, 0x000088C7 }, /* GL_MATRIX7_ARB */ + { 14053, 0x00008637 }, /* GL_MATRIX7_NV */ + { 14067, 0x000088C8 }, /* GL_MATRIX8_ARB */ + { 14082, 0x000088C9 }, /* GL_MATRIX9_ARB */ + { 14097, 0x00008844 }, /* GL_MATRIX_INDEX_ARRAY_ARB */ + { 14123, 0x00008849 }, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */ + { 14157, 0x00008846 }, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */ + { 14188, 0x00008848 }, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */ + { 14221, 0x00008847 }, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */ + { 14252, 0x00000BA0 }, /* GL_MATRIX_MODE */ + { 14267, 0x00008840 }, /* GL_MATRIX_PALETTE_ARB */ + { 14289, 0x00008008 }, /* GL_MAX */ + { 14296, 0x00008073 }, /* GL_MAX_3D_TEXTURE_SIZE */ + { 14319, 0x00000D35 }, /* GL_MAX_ATTRIB_STACK_DEPTH */ + { 14345, 0x00000D3B }, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */ + { 14378, 0x00008177 }, /* GL_MAX_CLIPMAP_DEPTH_SGIX */ + { 14404, 0x00008178 }, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */ + { 14438, 0x00000D32 }, /* GL_MAX_CLIP_PLANES */ + { 14457, 0x00008CDF }, /* GL_MAX_COLOR_ATTACHMENTS_EXT */ + { 14486, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */ + { 14518, 0x000080B3 }, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI */ + { 14554, 0x00008B4D }, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB */ + { 14594, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT */ + { 14620, 0x0000801B }, /* GL_MAX_CONVOLUTION_HEIGHT_EXT */ + { 14650, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH */ + { 14675, 0x0000801A }, /* GL_MAX_CONVOLUTION_WIDTH_EXT */ + { 14704, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */ + { 14733, 0x0000851C }, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB */ + { 14766, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ARB */ + { 14790, 0x00008824 }, /* GL_MAX_DRAW_BUFFERS_ATI */ + { 14814, 0x000080E9 }, /* GL_MAX_ELEMENTS_INDICES */ + { 14838, 0x000080E8 }, /* GL_MAX_ELEMENTS_VERTICES */ + { 14863, 0x00000D30 }, /* GL_MAX_EVAL_ORDER */ + { 14881, 0x00008008 }, /* GL_MAX_EXT */ + { 14892, 0x00008B49 }, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB */ + { 14931, 0x00000D31 }, /* GL_MAX_LIGHTS */ + { 14945, 0x00000B31 }, /* GL_MAX_LIST_NESTING */ + { 14965, 0x00008841 }, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */ + { 15003, 0x00000D36 }, /* GL_MAX_MODELVIEW_STACK_DEPTH */ + { 15032, 0x00000D37 }, /* GL_MAX_NAME_STACK_DEPTH */ + { 15056, 0x00008842 }, /* GL_MAX_PALETTE_MATRICES_ARB */ + { 15084, 0x00000D34 }, /* GL_MAX_PIXEL_MAP_TABLE */ + { 15107, 0x000088B1 }, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */ + { 15144, 0x0000880B }, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */ + { 15180, 0x000088AD }, /* GL_MAX_PROGRAM_ATTRIBS_ARB */ + { 15207, 0x000088F5 }, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */ + { 15236, 0x000088B5 }, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */ + { 15270, 0x000088F4 }, /* GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */ + { 15306, 0x000088F6 }, /* GL_MAX_PROGRAM_IF_DEPTH_NV */ + { 15333, 0x000088A1 }, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */ + { 15365, 0x000088B4 }, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */ + { 15401, 0x000088F8 }, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */ + { 15430, 0x000088F7 }, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */ + { 15459, 0x0000862F }, /* GL_MAX_PROGRAM_MATRICES_ARB */ + { 15487, 0x0000862E }, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */ + { 15525, 0x000088B3 }, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */ + { 15569, 0x0000880E }, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */ + { 15612, 0x000088AF }, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */ + { 15646, 0x000088A3 }, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */ + { 15685, 0x000088AB }, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */ + { 15722, 0x000088A7 }, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */ + { 15760, 0x00008810 }, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */ + { 15803, 0x0000880F }, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */ + { 15846, 0x000088A9 }, /* GL_MAX_PROGRAM_PARAMETERS_ARB */ + { 15876, 0x000088A5 }, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */ + { 15907, 0x0000880D }, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */ + { 15943, 0x0000880C }, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */ + { 15979, 0x00000D38 }, /* GL_MAX_PROJECTION_STACK_DEPTH */ + { 16009, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */ + { 16043, 0x000084F8 }, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_NV */ + { 16076, 0x000084E8 }, /* GL_MAX_RENDERBUFFER_SIZE_EXT */ + { 16105, 0x00008504 }, /* GL_MAX_SHININESS_NV */ + { 16125, 0x00008505 }, /* GL_MAX_SPOT_EXPONENT_NV */ + { 16149, 0x00008871 }, /* GL_MAX_TEXTURE_COORDS_ARB */ + { 16175, 0x00008872 }, /* GL_MAX_TEXTURE_IMAGE_UNITS_ARB */ + { 16206, 0x000084FD }, /* GL_MAX_TEXTURE_LOD_BIAS */ + { 16230, 0x000084FF }, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */ + { 16264, 0x00000D33 }, /* GL_MAX_TEXTURE_SIZE */ + { 16284, 0x00000D39 }, /* GL_MAX_TEXTURE_STACK_DEPTH */ + { 16311, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS */ + { 16332, 0x000084E2 }, /* GL_MAX_TEXTURE_UNITS_ARB */ + { 16357, 0x0000862F }, /* GL_MAX_TRACK_MATRICES_NV */ + { 16382, 0x0000862E }, /* GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV */ + { 16417, 0x00008B4B }, /* GL_MAX_VARYING_FLOATS_ARB */ + { 16443, 0x00008869 }, /* GL_MAX_VERTEX_ATTRIBS_ARB */ + { 16469, 0x00008B4C }, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */ + { 16507, 0x00008B4A }, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB */ + { 16544, 0x000086A4 }, /* GL_MAX_VERTEX_UNITS_ARB */ + { 16568, 0x00000D3A }, /* GL_MAX_VIEWPORT_DIMS */ + { 16589, 0x00008007 }, /* GL_MIN */ + { 16596, 0x0000802E }, /* GL_MINMAX */ + { 16606, 0x0000802E }, /* GL_MINMAX_EXT */ + { 16620, 0x0000802F }, /* GL_MINMAX_FORMAT */ + { 16637, 0x0000802F }, /* GL_MINMAX_FORMAT_EXT */ + { 16658, 0x00008030 }, /* GL_MINMAX_SINK */ + { 16673, 0x00008030 }, /* GL_MINMAX_SINK_EXT */ + { 16692, 0x00008007 }, /* GL_MIN_EXT */ + { 16703, 0x00008370 }, /* GL_MIRRORED_REPEAT */ + { 16722, 0x00008370 }, /* GL_MIRRORED_REPEAT_ARB */ + { 16745, 0x00008370 }, /* GL_MIRRORED_REPEAT_IBM */ + { 16768, 0x00008742 }, /* GL_MIRROR_CLAMP_ATI */ + { 16788, 0x00008742 }, /* GL_MIRROR_CLAMP_EXT */ + { 16808, 0x00008912 }, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */ + { 16838, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_ATI */ + { 16866, 0x00008743 }, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */ + { 16894, 0x00001700 }, /* GL_MODELVIEW */ + { 16907, 0x00001700 }, /* GL_MODELVIEW0_ARB */ + { 16925, 0x0000872A }, /* GL_MODELVIEW10_ARB */ + { 16944, 0x0000872B }, /* GL_MODELVIEW11_ARB */ + { 16963, 0x0000872C }, /* GL_MODELVIEW12_ARB */ + { 16982, 0x0000872D }, /* GL_MODELVIEW13_ARB */ + { 17001, 0x0000872E }, /* GL_MODELVIEW14_ARB */ + { 17020, 0x0000872F }, /* GL_MODELVIEW15_ARB */ + { 17039, 0x00008730 }, /* GL_MODELVIEW16_ARB */ + { 17058, 0x00008731 }, /* GL_MODELVIEW17_ARB */ + { 17077, 0x00008732 }, /* GL_MODELVIEW18_ARB */ + { 17096, 0x00008733 }, /* GL_MODELVIEW19_ARB */ + { 17115, 0x0000850A }, /* GL_MODELVIEW1_ARB */ + { 17133, 0x00008734 }, /* GL_MODELVIEW20_ARB */ + { 17152, 0x00008735 }, /* GL_MODELVIEW21_ARB */ + { 17171, 0x00008736 }, /* GL_MODELVIEW22_ARB */ + { 17190, 0x00008737 }, /* GL_MODELVIEW23_ARB */ + { 17209, 0x00008738 }, /* GL_MODELVIEW24_ARB */ + { 17228, 0x00008739 }, /* GL_MODELVIEW25_ARB */ + { 17247, 0x0000873A }, /* GL_MODELVIEW26_ARB */ + { 17266, 0x0000873B }, /* GL_MODELVIEW27_ARB */ + { 17285, 0x0000873C }, /* GL_MODELVIEW28_ARB */ + { 17304, 0x0000873D }, /* GL_MODELVIEW29_ARB */ + { 17323, 0x00008722 }, /* GL_MODELVIEW2_ARB */ + { 17341, 0x0000873E }, /* GL_MODELVIEW30_ARB */ + { 17360, 0x0000873F }, /* GL_MODELVIEW31_ARB */ + { 17379, 0x00008723 }, /* GL_MODELVIEW3_ARB */ + { 17397, 0x00008724 }, /* GL_MODELVIEW4_ARB */ + { 17415, 0x00008725 }, /* GL_MODELVIEW5_ARB */ + { 17433, 0x00008726 }, /* GL_MODELVIEW6_ARB */ + { 17451, 0x00008727 }, /* GL_MODELVIEW7_ARB */ + { 17469, 0x00008728 }, /* GL_MODELVIEW8_ARB */ + { 17487, 0x00008729 }, /* GL_MODELVIEW9_ARB */ + { 17505, 0x00000BA6 }, /* GL_MODELVIEW_MATRIX */ + { 17525, 0x00008629 }, /* GL_MODELVIEW_PROJECTION_NV */ + { 17552, 0x00000BA3 }, /* GL_MODELVIEW_STACK_DEPTH */ + { 17577, 0x00002100 }, /* GL_MODULATE */ + { 17589, 0x00008744 }, /* GL_MODULATE_ADD_ATI */ + { 17609, 0x00008745 }, /* GL_MODULATE_SIGNED_ADD_ATI */ + { 17636, 0x00008746 }, /* GL_MODULATE_SUBTRACT_ATI */ + { 17661, 0x00000103 }, /* GL_MULT */ + { 17669, 0x0000809D }, /* GL_MULTISAMPLE */ + { 17684, 0x000086B2 }, /* GL_MULTISAMPLE_3DFX */ + { 17704, 0x0000809D }, /* GL_MULTISAMPLE_ARB */ + { 17723, 0x20000000 }, /* GL_MULTISAMPLE_BIT */ + { 17742, 0x20000000 }, /* GL_MULTISAMPLE_BIT_3DFX */ + { 17766, 0x20000000 }, /* GL_MULTISAMPLE_BIT_ARB */ + { 17789, 0x00008534 }, /* GL_MULTISAMPLE_FILTER_HINT_NV */ + { 17819, 0x00002A25 }, /* GL_N3F_V3F */ + { 17830, 0x00000D70 }, /* GL_NAME_STACK_DEPTH */ + { 17850, 0x0000150E }, /* GL_NAND */ + { 17858, 0x00002600 }, /* GL_NEAREST */ + { 17869, 0x0000844E }, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */ + { 17900, 0x0000844D }, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */ + { 17932, 0x00002702 }, /* GL_NEAREST_MIPMAP_LINEAR */ + { 17957, 0x00002700 }, /* GL_NEAREST_MIPMAP_NEAREST */ + { 17983, 0x00000200 }, /* GL_NEVER */ + { 17992, 0x00001102 }, /* GL_NICEST */ + { 18002, 0x00000000 }, /* GL_NONE */ + { 18010, 0x00001505 }, /* GL_NOOP */ + { 18018, 0x00001508 }, /* GL_NOR */ + { 18025, 0x00000BA1 }, /* GL_NORMALIZE */ + { 18038, 0x00008075 }, /* GL_NORMAL_ARRAY */ + { 18054, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING */ + { 18085, 0x00008897 }, /* GL_NORMAL_ARRAY_BUFFER_BINDING_ARB */ + { 18120, 0x0000808F }, /* GL_NORMAL_ARRAY_POINTER */ + { 18144, 0x0000807F }, /* GL_NORMAL_ARRAY_STRIDE */ + { 18167, 0x0000807E }, /* GL_NORMAL_ARRAY_TYPE */ + { 18188, 0x00008511 }, /* GL_NORMAL_MAP */ + { 18202, 0x00008511 }, /* GL_NORMAL_MAP_ARB */ + { 18220, 0x00008511 }, /* GL_NORMAL_MAP_NV */ + { 18237, 0x00000205 }, /* GL_NOTEQUAL */ + { 18249, 0x00000000 }, /* GL_NO_ERROR */ + { 18261, 0x000086A2 }, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */ + { 18295, 0x000086A2 }, /* GL_NUM_TEXTURE_COMPRESSED_FORMATS_ARB */ + { 18333, 0x00008B89 }, /* GL_OBJECT_ACTIVE_ATTRIBUTES_ARB */ + { 18365, 0x00008B8A }, /* GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB */ + { 18407, 0x00008B86 }, /* GL_OBJECT_ACTIVE_UNIFORMS_ARB */ + { 18437, 0x00008B87 }, /* GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB */ + { 18477, 0x00008B85 }, /* GL_OBJECT_ATTACHED_OBJECTS_ARB */ + { 18508, 0x00008B81 }, /* GL_OBJECT_COMPILE_STATUS_ARB */ + { 18537, 0x00008B80 }, /* GL_OBJECT_DELETE_STATUS_ARB */ + { 18565, 0x00008B84 }, /* GL_OBJECT_INFO_LOG_LENGTH_ARB */ + { 18595, 0x00002401 }, /* GL_OBJECT_LINEAR */ + { 18612, 0x00008B82 }, /* GL_OBJECT_LINK_STATUS_ARB */ + { 18638, 0x00002501 }, /* GL_OBJECT_PLANE */ + { 18654, 0x00008B88 }, /* GL_OBJECT_SHADER_SOURCE_LENGTH_ARB */ + { 18689, 0x00008B4F }, /* GL_OBJECT_SUBTYPE_ARB */ + { 18711, 0x00008B4E }, /* GL_OBJECT_TYPE_ARB */ + { 18730, 0x00008B83 }, /* GL_OBJECT_VALIDATE_STATUS_ARB */ + { 18760, 0x00008165 }, /* GL_OCCLUSION_TEST_HP */ + { 18781, 0x00008166 }, /* GL_OCCLUSION_TEST_RESULT_HP */ + { 18809, 0x00000001 }, /* GL_ONE */ + { 18816, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA */ + { 18844, 0x00008004 }, /* GL_ONE_MINUS_CONSTANT_ALPHA_EXT */ + { 18876, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR */ + { 18904, 0x00008002 }, /* GL_ONE_MINUS_CONSTANT_COLOR_EXT */ + { 18936, 0x00000305 }, /* GL_ONE_MINUS_DST_ALPHA */ + { 18959, 0x00000307 }, /* GL_ONE_MINUS_DST_COLOR */ + { 18982, 0x00000303 }, /* GL_ONE_MINUS_SRC_ALPHA */ + { 19005, 0x00000301 }, /* GL_ONE_MINUS_SRC_COLOR */ + { 19028, 0x00008598 }, /* GL_OPERAND0_ALPHA */ + { 19046, 0x00008598 }, /* GL_OPERAND0_ALPHA_ARB */ + { 19068, 0x00008598 }, /* GL_OPERAND0_ALPHA_EXT */ + { 19090, 0x00008590 }, /* GL_OPERAND0_RGB */ + { 19106, 0x00008590 }, /* GL_OPERAND0_RGB_ARB */ + { 19126, 0x00008590 }, /* GL_OPERAND0_RGB_EXT */ + { 19146, 0x00008599 }, /* GL_OPERAND1_ALPHA */ + { 19164, 0x00008599 }, /* GL_OPERAND1_ALPHA_ARB */ + { 19186, 0x00008599 }, /* GL_OPERAND1_ALPHA_EXT */ + { 19208, 0x00008591 }, /* GL_OPERAND1_RGB */ + { 19224, 0x00008591 }, /* GL_OPERAND1_RGB_ARB */ + { 19244, 0x00008591 }, /* GL_OPERAND1_RGB_EXT */ + { 19264, 0x0000859A }, /* GL_OPERAND2_ALPHA */ + { 19282, 0x0000859A }, /* GL_OPERAND2_ALPHA_ARB */ + { 19304, 0x0000859A }, /* GL_OPERAND2_ALPHA_EXT */ + { 19326, 0x00008592 }, /* GL_OPERAND2_RGB */ + { 19342, 0x00008592 }, /* GL_OPERAND2_RGB_ARB */ + { 19362, 0x00008592 }, /* GL_OPERAND2_RGB_EXT */ + { 19382, 0x0000859B }, /* GL_OPERAND3_ALPHA_NV */ + { 19403, 0x00008593 }, /* GL_OPERAND3_RGB_NV */ + { 19422, 0x00001507 }, /* GL_OR */ + { 19428, 0x00000A01 }, /* GL_ORDER */ + { 19437, 0x0000150D }, /* GL_OR_INVERTED */ + { 19452, 0x0000150B }, /* GL_OR_REVERSE */ + { 19466, 0x00000505 }, /* GL_OUT_OF_MEMORY */ + { 19483, 0x00000D05 }, /* GL_PACK_ALIGNMENT */ + { 19501, 0x0000806C }, /* GL_PACK_IMAGE_HEIGHT */ + { 19522, 0x00008758 }, /* GL_PACK_INVERT_MESA */ + { 19542, 0x00000D01 }, /* GL_PACK_LSB_FIRST */ + { 19560, 0x00000D02 }, /* GL_PACK_ROW_LENGTH */ + { 19579, 0x0000806B }, /* GL_PACK_SKIP_IMAGES */ + { 19599, 0x00000D04 }, /* GL_PACK_SKIP_PIXELS */ + { 19619, 0x00000D03 }, /* GL_PACK_SKIP_ROWS */ + { 19637, 0x00000D00 }, /* GL_PACK_SWAP_BYTES */ + { 19656, 0x00008B92 }, /* GL_PALETTE4_R5_G6_B5_OES */ + { 19681, 0x00008B94 }, /* GL_PALETTE4_RGB5_A1_OES */ + { 19705, 0x00008B90 }, /* GL_PALETTE4_RGB8_OES */ + { 19726, 0x00008B93 }, /* GL_PALETTE4_RGBA4_OES */ + { 19748, 0x00008B91 }, /* GL_PALETTE4_RGBA8_OES */ + { 19770, 0x00008B97 }, /* GL_PALETTE8_R5_G6_B5_OES */ + { 19795, 0x00008B99 }, /* GL_PALETTE8_RGB5_A1_OES */ + { 19819, 0x00008B95 }, /* GL_PALETTE8_RGB8_OES */ + { 19840, 0x00008B98 }, /* GL_PALETTE8_RGBA4_OES */ + { 19862, 0x00008B96 }, /* GL_PALETTE8_RGBA8_OES */ + { 19884, 0x00000700 }, /* GL_PASS_THROUGH_TOKEN */ + { 19906, 0x00000C50 }, /* GL_PERSPECTIVE_CORRECTION_HINT */ + { 19937, 0x00000C79 }, /* GL_PIXEL_MAP_A_TO_A */ + { 19957, 0x00000CB9 }, /* GL_PIXEL_MAP_A_TO_A_SIZE */ + { 19982, 0x00000C78 }, /* GL_PIXEL_MAP_B_TO_B */ + { 20002, 0x00000CB8 }, /* GL_PIXEL_MAP_B_TO_B_SIZE */ + { 20027, 0x00000C77 }, /* GL_PIXEL_MAP_G_TO_G */ + { 20047, 0x00000CB7 }, /* GL_PIXEL_MAP_G_TO_G_SIZE */ + { 20072, 0x00000C75 }, /* GL_PIXEL_MAP_I_TO_A */ + { 20092, 0x00000CB5 }, /* GL_PIXEL_MAP_I_TO_A_SIZE */ + { 20117, 0x00000C74 }, /* GL_PIXEL_MAP_I_TO_B */ + { 20137, 0x00000CB4 }, /* GL_PIXEL_MAP_I_TO_B_SIZE */ + { 20162, 0x00000C73 }, /* GL_PIXEL_MAP_I_TO_G */ + { 20182, 0x00000CB3 }, /* GL_PIXEL_MAP_I_TO_G_SIZE */ + { 20207, 0x00000C70 }, /* GL_PIXEL_MAP_I_TO_I */ + { 20227, 0x00000CB0 }, /* GL_PIXEL_MAP_I_TO_I_SIZE */ + { 20252, 0x00000C72 }, /* GL_PIXEL_MAP_I_TO_R */ + { 20272, 0x00000CB2 }, /* GL_PIXEL_MAP_I_TO_R_SIZE */ + { 20297, 0x00000C76 }, /* GL_PIXEL_MAP_R_TO_R */ + { 20317, 0x00000CB6 }, /* GL_PIXEL_MAP_R_TO_R_SIZE */ + { 20342, 0x00000C71 }, /* GL_PIXEL_MAP_S_TO_S */ + { 20362, 0x00000CB1 }, /* GL_PIXEL_MAP_S_TO_S_SIZE */ + { 20387, 0x00000020 }, /* GL_PIXEL_MODE_BIT */ + { 20405, 0x000088ED }, /* GL_PIXEL_PACK_BUFFER_BINDING_EXT */ + { 20438, 0x000088EB }, /* GL_PIXEL_PACK_BUFFER_EXT */ + { 20463, 0x000088EF }, /* GL_PIXEL_UNPACK_BUFFER_BINDING_EXT */ + { 20498, 0x000088EC }, /* GL_PIXEL_UNPACK_BUFFER_EXT */ + { 20525, 0x00001B00 }, /* GL_POINT */ + { 20534, 0x00000000 }, /* GL_POINTS */ + { 20544, 0x00000002 }, /* GL_POINT_BIT */ + { 20557, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION */ + { 20587, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_ARB */ + { 20621, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_EXT */ + { 20655, 0x00008129 }, /* GL_POINT_DISTANCE_ATTENUATION_SGIS */ + { 20690, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE */ + { 20719, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_ARB */ + { 20752, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_EXT */ + { 20785, 0x00008128 }, /* GL_POINT_FADE_THRESHOLD_SIZE_SGIS */ + { 20819, 0x00000B11 }, /* GL_POINT_SIZE */ + { 20833, 0x00000B13 }, /* GL_POINT_SIZE_GRANULARITY */ + { 20859, 0x00008127 }, /* GL_POINT_SIZE_MAX */ + { 20877, 0x00008127 }, /* GL_POINT_SIZE_MAX_ARB */ + { 20899, 0x00008127 }, /* GL_POINT_SIZE_MAX_EXT */ + { 20921, 0x00008127 }, /* GL_POINT_SIZE_MAX_SGIS */ + { 20944, 0x00008126 }, /* GL_POINT_SIZE_MIN */ + { 20962, 0x00008126 }, /* GL_POINT_SIZE_MIN_ARB */ + { 20984, 0x00008126 }, /* GL_POINT_SIZE_MIN_EXT */ + { 21006, 0x00008126 }, /* GL_POINT_SIZE_MIN_SGIS */ + { 21029, 0x00000B12 }, /* GL_POINT_SIZE_RANGE */ + { 21049, 0x00000B10 }, /* GL_POINT_SMOOTH */ + { 21065, 0x00000C51 }, /* GL_POINT_SMOOTH_HINT */ + { 21086, 0x00008861 }, /* GL_POINT_SPRITE_ARB */ + { 21106, 0x00008CA0 }, /* GL_POINT_SPRITE_COORD_ORIGIN */ + { 21135, 0x00008861 }, /* GL_POINT_SPRITE_NV */ + { 21154, 0x00008863 }, /* GL_POINT_SPRITE_R_MODE_NV */ + { 21180, 0x00000701 }, /* GL_POINT_TOKEN */ + { 21195, 0x00000009 }, /* GL_POLYGON */ + { 21206, 0x00000008 }, /* GL_POLYGON_BIT */ + { 21221, 0x00000B40 }, /* GL_POLYGON_MODE */ + { 21237, 0x00008039 }, /* GL_POLYGON_OFFSET_BIAS */ + { 21260, 0x00008038 }, /* GL_POLYGON_OFFSET_FACTOR */ + { 21285, 0x00008037 }, /* GL_POLYGON_OFFSET_FILL */ + { 21308, 0x00002A02 }, /* GL_POLYGON_OFFSET_LINE */ + { 21331, 0x00002A01 }, /* GL_POLYGON_OFFSET_POINT */ + { 21355, 0x00002A00 }, /* GL_POLYGON_OFFSET_UNITS */ + { 21379, 0x00000B41 }, /* GL_POLYGON_SMOOTH */ + { 21397, 0x00000C53 }, /* GL_POLYGON_SMOOTH_HINT */ + { 21420, 0x00000B42 }, /* GL_POLYGON_STIPPLE */ + { 21439, 0x00000010 }, /* GL_POLYGON_STIPPLE_BIT */ + { 21462, 0x00000703 }, /* GL_POLYGON_TOKEN */ + { 21479, 0x00001203 }, /* GL_POSITION */ + { 21491, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */ + { 21523, 0x000080BB }, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI */ + { 21559, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */ + { 21592, 0x000080B7 }, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI */ + { 21629, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */ + { 21660, 0x000080BA }, /* GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI */ + { 21695, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */ + { 21727, 0x000080B6 }, /* GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI */ + { 21763, 0x000080D2 }, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */ + { 21796, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */ + { 21828, 0x000080B9 }, /* GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI */ + { 21864, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */ + { 21897, 0x000080B5 }, /* GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI */ + { 21934, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS */ + { 21964, 0x000080B8 }, /* GL_POST_COLOR_MATRIX_RED_BIAS_SGI */ + { 21998, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE */ + { 22029, 0x000080B4 }, /* GL_POST_COLOR_MATRIX_RED_SCALE_SGI */ + { 22064, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS */ + { 22095, 0x00008023 }, /* GL_POST_CONVOLUTION_ALPHA_BIAS_EXT */ + { 22130, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE */ + { 22162, 0x0000801F }, /* GL_POST_CONVOLUTION_ALPHA_SCALE_EXT */ + { 22198, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS */ + { 22228, 0x00008022 }, /* GL_POST_CONVOLUTION_BLUE_BIAS_EXT */ + { 22262, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE */ + { 22293, 0x0000801E }, /* GL_POST_CONVOLUTION_BLUE_SCALE_EXT */ + { 22328, 0x000080D1 }, /* GL_POST_CONVOLUTION_COLOR_TABLE */ + { 22360, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS */ + { 22391, 0x00008021 }, /* GL_POST_CONVOLUTION_GREEN_BIAS_EXT */ + { 22426, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE */ + { 22458, 0x0000801D }, /* GL_POST_CONVOLUTION_GREEN_SCALE_EXT */ + { 22494, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS */ + { 22523, 0x00008020 }, /* GL_POST_CONVOLUTION_RED_BIAS_EXT */ + { 22556, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE */ + { 22586, 0x0000801C }, /* GL_POST_CONVOLUTION_RED_SCALE_EXT */ + { 22620, 0x0000817B }, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */ + { 22659, 0x00008179 }, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */ + { 22692, 0x0000817C }, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */ + { 22732, 0x0000817A }, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */ + { 22766, 0x00008578 }, /* GL_PREVIOUS */ + { 22778, 0x00008578 }, /* GL_PREVIOUS_ARB */ + { 22794, 0x00008578 }, /* GL_PREVIOUS_EXT */ + { 22810, 0x00008577 }, /* GL_PRIMARY_COLOR */ + { 22827, 0x00008577 }, /* GL_PRIMARY_COLOR_ARB */ + { 22848, 0x00008577 }, /* GL_PRIMARY_COLOR_EXT */ + { 22869, 0x000088B0 }, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */ + { 22902, 0x00008805 }, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */ + { 22934, 0x000088AC }, /* GL_PROGRAM_ATTRIBS_ARB */ + { 22957, 0x00008677 }, /* GL_PROGRAM_BINDING_ARB */ + { 22980, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_ARB */ + { 23010, 0x0000864B }, /* GL_PROGRAM_ERROR_POSITION_NV */ + { 23039, 0x00008874 }, /* GL_PROGRAM_ERROR_STRING_ARB */ + { 23067, 0x00008876 }, /* GL_PROGRAM_FORMAT_ARB */ + { 23089, 0x00008875 }, /* GL_PROGRAM_FORMAT_ASCII_ARB */ + { 23117, 0x000088A0 }, /* GL_PROGRAM_INSTRUCTIONS_ARB */ + { 23145, 0x00008627 }, /* GL_PROGRAM_LENGTH_ARB */ + { 23167, 0x00008627 }, /* GL_PROGRAM_LENGTH_NV */ + { 23188, 0x000088B2 }, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */ + { 23228, 0x00008808 }, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */ + { 23267, 0x000088AE }, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */ + { 23297, 0x000088A2 }, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */ + { 23332, 0x000088AA }, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */ + { 23365, 0x000088A6 }, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */ + { 23399, 0x0000880A }, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */ + { 23438, 0x00008809 }, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */ + { 23477, 0x00008B40 }, /* GL_PROGRAM_OBJECT_ARB */ + { 23499, 0x000088A8 }, /* GL_PROGRAM_PARAMETERS_ARB */ + { 23525, 0x00008644 }, /* GL_PROGRAM_PARAMETER_NV */ + { 23549, 0x00008647 }, /* GL_PROGRAM_RESIDENT_NV */ + { 23572, 0x00008628 }, /* GL_PROGRAM_STRING_ARB */ + { 23594, 0x00008628 }, /* GL_PROGRAM_STRING_NV */ + { 23615, 0x00008646 }, /* GL_PROGRAM_TARGET_NV */ + { 23636, 0x000088A4 }, /* GL_PROGRAM_TEMPORARIES_ARB */ + { 23663, 0x00008807 }, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */ + { 23695, 0x00008806 }, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */ + { 23727, 0x000088B6 }, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */ + { 23762, 0x00001701 }, /* GL_PROJECTION */ + { 23776, 0x00000BA7 }, /* GL_PROJECTION_MATRIX */ + { 23797, 0x00000BA4 }, /* GL_PROJECTION_STACK_DEPTH */ + { 23823, 0x000080D3 }, /* GL_PROXY_COLOR_TABLE */ + { 23844, 0x00008025 }, /* GL_PROXY_HISTOGRAM */ + { 23863, 0x00008025 }, /* GL_PROXY_HISTOGRAM_EXT */ + { 23886, 0x000080D5 }, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */ + { 23925, 0x000080D4 }, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */ + { 23963, 0x00008063 }, /* GL_PROXY_TEXTURE_1D */ + { 23983, 0x00008063 }, /* GL_PROXY_TEXTURE_1D_EXT */ + { 24007, 0x00008064 }, /* GL_PROXY_TEXTURE_2D */ + { 24027, 0x00008064 }, /* GL_PROXY_TEXTURE_2D_EXT */ + { 24051, 0x00008070 }, /* GL_PROXY_TEXTURE_3D */ + { 24071, 0x000080BD }, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */ + { 24104, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP */ + { 24130, 0x0000851B }, /* GL_PROXY_TEXTURE_CUBE_MAP_ARB */ + { 24160, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */ + { 24191, 0x000084F7 }, /* GL_PROXY_TEXTURE_RECTANGLE_NV */ + { 24221, 0x00002003 }, /* GL_Q */ + { 24226, 0x00001209 }, /* GL_QUADRATIC_ATTENUATION */ + { 24251, 0x00000007 }, /* GL_QUADS */ + { 24260, 0x00008614 }, /* GL_QUAD_MESH_SUN */ + { 24277, 0x00000008 }, /* GL_QUAD_STRIP */ + { 24291, 0x00008864 }, /* GL_QUERY_COUNTER_BITS */ + { 24313, 0x00008864 }, /* GL_QUERY_COUNTER_BITS_ARB */ + { 24339, 0x00008866 }, /* GL_QUERY_RESULT */ + { 24355, 0x00008866 }, /* GL_QUERY_RESULT_ARB */ + { 24375, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE */ + { 24401, 0x00008867 }, /* GL_QUERY_RESULT_AVAILABLE_ARB */ + { 24431, 0x00002002 }, /* GL_R */ + { 24436, 0x00002A10 }, /* GL_R3_G3_B2 */ + { 24448, 0x00019262 }, /* GL_RASTER_POSITION_UNCLIPPED_IBM */ + { 24481, 0x00000C02 }, /* GL_READ_BUFFER */ + { 24496, 0x000088B8 }, /* GL_READ_ONLY */ + { 24509, 0x000088B8 }, /* GL_READ_ONLY_ARB */ + { 24526, 0x000088BA }, /* GL_READ_WRITE */ + { 24540, 0x000088BA }, /* GL_READ_WRITE_ARB */ + { 24558, 0x00001903 }, /* GL_RED */ + { 24565, 0x00008016 }, /* GL_REDUCE */ + { 24575, 0x00008016 }, /* GL_REDUCE_EXT */ + { 24589, 0x00000D15 }, /* GL_RED_BIAS */ + { 24601, 0x00000D52 }, /* GL_RED_BITS */ + { 24613, 0x00000D14 }, /* GL_RED_SCALE */ + { 24626, 0x00008512 }, /* GL_REFLECTION_MAP */ + { 24644, 0x00008512 }, /* GL_REFLECTION_MAP_ARB */ + { 24666, 0x00008512 }, /* GL_REFLECTION_MAP_NV */ + { 24687, 0x00001C00 }, /* GL_RENDER */ + { 24697, 0x00008CA7 }, /* GL_RENDERBUFFER_BINDING_EXT */ + { 24725, 0x00008D41 }, /* GL_RENDERBUFFER_EXT */ + { 24745, 0x00008D43 }, /* GL_RENDERBUFFER_HEIGHT_EXT */ + { 24772, 0x00008D44 }, /* GL_RENDERBUFFER_INTERNAL_FORMAT_EXT */ + { 24808, 0x00008D42 }, /* GL_RENDERBUFFER_WIDTH_EXT */ + { 24834, 0x00001F01 }, /* GL_RENDERER */ + { 24846, 0x00000C40 }, /* GL_RENDER_MODE */ + { 24861, 0x00002901 }, /* GL_REPEAT */ + { 24871, 0x00001E01 }, /* GL_REPLACE */ + { 24882, 0x00008062 }, /* GL_REPLACE_EXT */ + { 24897, 0x00008153 }, /* GL_REPLICATE_BORDER_HP */ + { 24920, 0x0000803A }, /* GL_RESCALE_NORMAL */ + { 24938, 0x0000803A }, /* GL_RESCALE_NORMAL_EXT */ + { 24960, 0x00000102 }, /* GL_RETURN */ + { 24970, 0x00001907 }, /* GL_RGB */ + { 24977, 0x00008052 }, /* GL_RGB10 */ + { 24986, 0x00008059 }, /* GL_RGB10_A2 */ + { 24998, 0x00008059 }, /* GL_RGB10_A2_EXT */ + { 25014, 0x00008052 }, /* GL_RGB10_EXT */ + { 25027, 0x00008053 }, /* GL_RGB12 */ + { 25036, 0x00008053 }, /* GL_RGB12_EXT */ + { 25049, 0x00008054 }, /* GL_RGB16 */ + { 25058, 0x00008054 }, /* GL_RGB16_EXT */ + { 25071, 0x0000804E }, /* GL_RGB2_EXT */ + { 25083, 0x0000804F }, /* GL_RGB4 */ + { 25091, 0x0000804F }, /* GL_RGB4_EXT */ + { 25103, 0x000083A1 }, /* GL_RGB4_S3TC */ + { 25116, 0x00008050 }, /* GL_RGB5 */ + { 25124, 0x00008057 }, /* GL_RGB5_A1 */ + { 25135, 0x00008057 }, /* GL_RGB5_A1_EXT */ + { 25150, 0x00008050 }, /* GL_RGB5_EXT */ + { 25162, 0x00008051 }, /* GL_RGB8 */ + { 25170, 0x00008051 }, /* GL_RGB8_EXT */ + { 25182, 0x00001908 }, /* GL_RGBA */ + { 25190, 0x0000805A }, /* GL_RGBA12 */ + { 25200, 0x0000805A }, /* GL_RGBA12_EXT */ + { 25214, 0x0000805B }, /* GL_RGBA16 */ + { 25224, 0x0000805B }, /* GL_RGBA16_EXT */ + { 25238, 0x00008055 }, /* GL_RGBA2 */ + { 25247, 0x00008055 }, /* GL_RGBA2_EXT */ + { 25260, 0x00008056 }, /* GL_RGBA4 */ + { 25269, 0x000083A5 }, /* GL_RGBA4_DXT5_S3TC */ + { 25288, 0x00008056 }, /* GL_RGBA4_EXT */ + { 25301, 0x000083A3 }, /* GL_RGBA4_S3TC */ + { 25315, 0x00008058 }, /* GL_RGBA8 */ + { 25324, 0x00008058 }, /* GL_RGBA8_EXT */ + { 25337, 0x000083A4 }, /* GL_RGBA_DXT5_S3TC */ + { 25355, 0x00000C31 }, /* GL_RGBA_MODE */ + { 25368, 0x000083A2 }, /* GL_RGBA_S3TC */ + { 25381, 0x000083A0 }, /* GL_RGB_S3TC */ + { 25393, 0x00008573 }, /* GL_RGB_SCALE */ + { 25406, 0x00008573 }, /* GL_RGB_SCALE_ARB */ + { 25423, 0x00008573 }, /* GL_RGB_SCALE_EXT */ + { 25440, 0x00000407 }, /* GL_RIGHT */ + { 25449, 0x00002000 }, /* GL_S */ + { 25454, 0x000080A9 }, /* GL_SAMPLES */ + { 25465, 0x000086B4 }, /* GL_SAMPLES_3DFX */ + { 25481, 0x000080A9 }, /* GL_SAMPLES_ARB */ + { 25496, 0x00008914 }, /* GL_SAMPLES_PASSED */ + { 25514, 0x00008914 }, /* GL_SAMPLES_PASSED_ARB */ + { 25536, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE */ + { 25564, 0x0000809E }, /* GL_SAMPLE_ALPHA_TO_COVERAGE_ARB */ + { 25596, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE */ + { 25619, 0x0000809F }, /* GL_SAMPLE_ALPHA_TO_ONE_ARB */ + { 25646, 0x000080A8 }, /* GL_SAMPLE_BUFFERS */ + { 25664, 0x000086B3 }, /* GL_SAMPLE_BUFFERS_3DFX */ + { 25687, 0x000080A8 }, /* GL_SAMPLE_BUFFERS_ARB */ + { 25709, 0x000080A0 }, /* GL_SAMPLE_COVERAGE */ + { 25728, 0x000080A0 }, /* GL_SAMPLE_COVERAGE_ARB */ + { 25751, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT */ + { 25777, 0x000080AB }, /* GL_SAMPLE_COVERAGE_INVERT_ARB */ + { 25807, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE */ + { 25832, 0x000080AA }, /* GL_SAMPLE_COVERAGE_VALUE_ARB */ + { 25861, 0x00080000 }, /* GL_SCISSOR_BIT */ + { 25876, 0x00000C10 }, /* GL_SCISSOR_BOX */ + { 25891, 0x00000C11 }, /* GL_SCISSOR_TEST */ + { 25907, 0x0000845E }, /* GL_SECONDARY_COLOR_ARRAY */ + { 25932, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */ + { 25972, 0x0000889C }, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB */ + { 26016, 0x0000845D }, /* GL_SECONDARY_COLOR_ARRAY_POINTER */ + { 26049, 0x0000845A }, /* GL_SECONDARY_COLOR_ARRAY_SIZE */ + { 26079, 0x0000845C }, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */ + { 26111, 0x0000845B }, /* GL_SECONDARY_COLOR_ARRAY_TYPE */ + { 26141, 0x00001C02 }, /* GL_SELECT */ + { 26151, 0x00000DF3 }, /* GL_SELECTION_BUFFER_POINTER */ + { 26179, 0x00000DF4 }, /* GL_SELECTION_BUFFER_SIZE */ + { 26204, 0x00008012 }, /* GL_SEPARABLE_2D */ + { 26220, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR */ + { 26247, 0x000081FA }, /* GL_SEPARATE_SPECULAR_COLOR_EXT */ + { 26278, 0x0000150F }, /* GL_SET */ + { 26285, 0x00008B48 }, /* GL_SHADER_OBJECT_ARB */ + { 26306, 0x00000B54 }, /* GL_SHADE_MODEL */ + { 26321, 0x000080BF }, /* GL_SHADOW_AMBIENT_SGIX */ + { 26344, 0x000081FB }, /* GL_SHARED_TEXTURE_PALETTE_EXT */ + { 26374, 0x00001601 }, /* GL_SHININESS */ + { 26387, 0x00001402 }, /* GL_SHORT */ + { 26396, 0x000081F9 }, /* GL_SINGLE_COLOR */ + { 26412, 0x000081F9 }, /* GL_SINGLE_COLOR_EXT */ + { 26432, 0x000085CC }, /* GL_SLICE_ACCUM_SUN */ + { 26451, 0x00001D01 }, /* GL_SMOOTH */ + { 26461, 0x00000B23 }, /* GL_SMOOTH_LINE_WIDTH_GRANULARITY */ + { 26494, 0x00000B22 }, /* GL_SMOOTH_LINE_WIDTH_RANGE */ + { 26521, 0x00000B13 }, /* GL_SMOOTH_POINT_SIZE_GRANULARITY */ + { 26554, 0x00000B12 }, /* GL_SMOOTH_POINT_SIZE_RANGE */ + { 26581, 0x00008588 }, /* GL_SOURCE0_ALPHA */ + { 26598, 0x00008588 }, /* GL_SOURCE0_ALPHA_ARB */ + { 26619, 0x00008588 }, /* GL_SOURCE0_ALPHA_EXT */ + { 26640, 0x00008580 }, /* GL_SOURCE0_RGB */ + { 26655, 0x00008580 }, /* GL_SOURCE0_RGB_ARB */ + { 26674, 0x00008580 }, /* GL_SOURCE0_RGB_EXT */ + { 26693, 0x00008589 }, /* GL_SOURCE1_ALPHA */ + { 26710, 0x00008589 }, /* GL_SOURCE1_ALPHA_ARB */ + { 26731, 0x00008589 }, /* GL_SOURCE1_ALPHA_EXT */ + { 26752, 0x00008581 }, /* GL_SOURCE1_RGB */ + { 26767, 0x00008581 }, /* GL_SOURCE1_RGB_ARB */ + { 26786, 0x00008581 }, /* GL_SOURCE1_RGB_EXT */ + { 26805, 0x0000858A }, /* GL_SOURCE2_ALPHA */ + { 26822, 0x0000858A }, /* GL_SOURCE2_ALPHA_ARB */ + { 26843, 0x0000858A }, /* GL_SOURCE2_ALPHA_EXT */ + { 26864, 0x00008582 }, /* GL_SOURCE2_RGB */ + { 26879, 0x00008582 }, /* GL_SOURCE2_RGB_ARB */ + { 26898, 0x00008582 }, /* GL_SOURCE2_RGB_EXT */ + { 26917, 0x0000858B }, /* GL_SOURCE3_ALPHA_NV */ + { 26937, 0x00008583 }, /* GL_SOURCE3_RGB_NV */ + { 26955, 0x00001202 }, /* GL_SPECULAR */ + { 26967, 0x00002402 }, /* GL_SPHERE_MAP */ + { 26981, 0x00001206 }, /* GL_SPOT_CUTOFF */ + { 26996, 0x00001204 }, /* GL_SPOT_DIRECTION */ + { 27014, 0x00001205 }, /* GL_SPOT_EXPONENT */ + { 27031, 0x00008588 }, /* GL_SRC0_ALPHA */ + { 27045, 0x00008580 }, /* GL_SRC0_RGB */ + { 27057, 0x00008589 }, /* GL_SRC1_ALPHA */ + { 27071, 0x00008581 }, /* GL_SRC1_RGB */ + { 27083, 0x0000858A }, /* GL_SRC2_ALPHA */ + { 27097, 0x00008582 }, /* GL_SRC2_RGB */ + { 27109, 0x00000302 }, /* GL_SRC_ALPHA */ + { 27122, 0x00000308 }, /* GL_SRC_ALPHA_SATURATE */ + { 27144, 0x00000300 }, /* GL_SRC_COLOR */ + { 27157, 0x00000503 }, /* GL_STACK_OVERFLOW */ + { 27175, 0x00000504 }, /* GL_STACK_UNDERFLOW */ + { 27194, 0x000088E6 }, /* GL_STATIC_COPY */ + { 27209, 0x000088E6 }, /* GL_STATIC_COPY_ARB */ + { 27228, 0x000088E4 }, /* GL_STATIC_DRAW */ + { 27243, 0x000088E4 }, /* GL_STATIC_DRAW_ARB */ + { 27262, 0x000088E5 }, /* GL_STATIC_READ */ + { 27277, 0x000088E5 }, /* GL_STATIC_READ_ARB */ + { 27296, 0x00001802 }, /* GL_STENCIL */ + { 27307, 0x00008D20 }, /* GL_STENCIL_ATTACHMENT_EXT */ + { 27333, 0x00000D57 }, /* GL_STENCIL_BITS */ + { 27349, 0x00000400 }, /* GL_STENCIL_BUFFER_BIT */ + { 27371, 0x00000B91 }, /* GL_STENCIL_CLEAR_VALUE */ + { 27394, 0x00000B94 }, /* GL_STENCIL_FAIL */ + { 27410, 0x00000B92 }, /* GL_STENCIL_FUNC */ + { 27426, 0x00001901 }, /* GL_STENCIL_INDEX */ + { 27443, 0x00008D49 }, /* GL_STENCIL_INDEX16_EXT */ + { 27466, 0x00008D46 }, /* GL_STENCIL_INDEX1_EXT */ + { 27488, 0x00008D47 }, /* GL_STENCIL_INDEX4_EXT */ + { 27510, 0x00008D48 }, /* GL_STENCIL_INDEX8_EXT */ + { 27532, 0x00008D45 }, /* GL_STENCIL_INDEX_EXT */ + { 27553, 0x00000B95 }, /* GL_STENCIL_PASS_DEPTH_FAIL */ + { 27580, 0x00000B96 }, /* GL_STENCIL_PASS_DEPTH_PASS */ + { 27607, 0x00000B97 }, /* GL_STENCIL_REF */ + { 27622, 0x00000B90 }, /* GL_STENCIL_TEST */ + { 27638, 0x00008910 }, /* GL_STENCIL_TEST_TWO_SIDE_EXT */ + { 27667, 0x00000B93 }, /* GL_STENCIL_VALUE_MASK */ + { 27689, 0x00000B98 }, /* GL_STENCIL_WRITEMASK */ + { 27710, 0x00000C33 }, /* GL_STEREO */ + { 27720, 0x000088E2 }, /* GL_STREAM_COPY */ + { 27735, 0x000088E2 }, /* GL_STREAM_COPY_ARB */ + { 27754, 0x000088E0 }, /* GL_STREAM_DRAW */ + { 27769, 0x000088E0 }, /* GL_STREAM_DRAW_ARB */ + { 27788, 0x000088E1 }, /* GL_STREAM_READ */ + { 27803, 0x000088E1 }, /* GL_STREAM_READ_ARB */ + { 27822, 0x00000D50 }, /* GL_SUBPIXEL_BITS */ + { 27839, 0x000084E7 }, /* GL_SUBTRACT */ + { 27851, 0x000084E7 }, /* GL_SUBTRACT_ARB */ + { 27867, 0x00002001 }, /* GL_T */ + { 27872, 0x00002A2A }, /* GL_T2F_C3F_V3F */ + { 27887, 0x00002A2C }, /* GL_T2F_C4F_N3F_V3F */ + { 27906, 0x00002A29 }, /* GL_T2F_C4UB_V3F */ + { 27922, 0x00002A2B }, /* GL_T2F_N3F_V3F */ + { 27937, 0x00002A27 }, /* GL_T2F_V3F */ + { 27948, 0x00002A2D }, /* GL_T4F_C4F_N3F_V4F */ + { 27967, 0x00002A28 }, /* GL_T4F_V4F */ + { 27978, 0x00008031 }, /* GL_TABLE_TOO_LARGE_EXT */ + { 28001, 0x00001702 }, /* GL_TEXTURE */ + { 28012, 0x000084C0 }, /* GL_TEXTURE0 */ + { 28024, 0x000084C0 }, /* GL_TEXTURE0_ARB */ + { 28040, 0x000084C1 }, /* GL_TEXTURE1 */ + { 28052, 0x000084CA }, /* GL_TEXTURE10 */ + { 28065, 0x000084CA }, /* GL_TEXTURE10_ARB */ + { 28082, 0x000084CB }, /* GL_TEXTURE11 */ + { 28095, 0x000084CB }, /* GL_TEXTURE11_ARB */ + { 28112, 0x000084CC }, /* GL_TEXTURE12 */ + { 28125, 0x000084CC }, /* GL_TEXTURE12_ARB */ + { 28142, 0x000084CD }, /* GL_TEXTURE13 */ + { 28155, 0x000084CD }, /* GL_TEXTURE13_ARB */ + { 28172, 0x000084CE }, /* GL_TEXTURE14 */ + { 28185, 0x000084CE }, /* GL_TEXTURE14_ARB */ + { 28202, 0x000084CF }, /* GL_TEXTURE15 */ + { 28215, 0x000084CF }, /* GL_TEXTURE15_ARB */ + { 28232, 0x000084D0 }, /* GL_TEXTURE16 */ + { 28245, 0x000084D0 }, /* GL_TEXTURE16_ARB */ + { 28262, 0x000084D1 }, /* GL_TEXTURE17 */ + { 28275, 0x000084D1 }, /* GL_TEXTURE17_ARB */ + { 28292, 0x000084D2 }, /* GL_TEXTURE18 */ + { 28305, 0x000084D2 }, /* GL_TEXTURE18_ARB */ + { 28322, 0x000084D3 }, /* GL_TEXTURE19 */ + { 28335, 0x000084D3 }, /* GL_TEXTURE19_ARB */ + { 28352, 0x000084C1 }, /* GL_TEXTURE1_ARB */ + { 28368, 0x000084C2 }, /* GL_TEXTURE2 */ + { 28380, 0x000084D4 }, /* GL_TEXTURE20 */ + { 28393, 0x000084D4 }, /* GL_TEXTURE20_ARB */ + { 28410, 0x000084D5 }, /* GL_TEXTURE21 */ + { 28423, 0x000084D5 }, /* GL_TEXTURE21_ARB */ + { 28440, 0x000084D6 }, /* GL_TEXTURE22 */ + { 28453, 0x000084D6 }, /* GL_TEXTURE22_ARB */ + { 28470, 0x000084D7 }, /* GL_TEXTURE23 */ + { 28483, 0x000084D7 }, /* GL_TEXTURE23_ARB */ + { 28500, 0x000084D8 }, /* GL_TEXTURE24 */ + { 28513, 0x000084D8 }, /* GL_TEXTURE24_ARB */ + { 28530, 0x000084D9 }, /* GL_TEXTURE25 */ + { 28543, 0x000084D9 }, /* GL_TEXTURE25_ARB */ + { 28560, 0x000084DA }, /* GL_TEXTURE26 */ + { 28573, 0x000084DA }, /* GL_TEXTURE26_ARB */ + { 28590, 0x000084DB }, /* GL_TEXTURE27 */ + { 28603, 0x000084DB }, /* GL_TEXTURE27_ARB */ + { 28620, 0x000084DC }, /* GL_TEXTURE28 */ + { 28633, 0x000084DC }, /* GL_TEXTURE28_ARB */ + { 28650, 0x000084DD }, /* GL_TEXTURE29 */ + { 28663, 0x000084DD }, /* GL_TEXTURE29_ARB */ + { 28680, 0x000084C2 }, /* GL_TEXTURE2_ARB */ + { 28696, 0x000084C3 }, /* GL_TEXTURE3 */ + { 28708, 0x000084DE }, /* GL_TEXTURE30 */ + { 28721, 0x000084DE }, /* GL_TEXTURE30_ARB */ + { 28738, 0x000084DF }, /* GL_TEXTURE31 */ + { 28751, 0x000084DF }, /* GL_TEXTURE31_ARB */ + { 28768, 0x000084C3 }, /* GL_TEXTURE3_ARB */ + { 28784, 0x000084C4 }, /* GL_TEXTURE4 */ + { 28796, 0x000084C4 }, /* GL_TEXTURE4_ARB */ + { 28812, 0x000084C5 }, /* GL_TEXTURE5 */ + { 28824, 0x000084C5 }, /* GL_TEXTURE5_ARB */ + { 28840, 0x000084C6 }, /* GL_TEXTURE6 */ + { 28852, 0x000084C6 }, /* GL_TEXTURE6_ARB */ + { 28868, 0x000084C7 }, /* GL_TEXTURE7 */ + { 28880, 0x000084C7 }, /* GL_TEXTURE7_ARB */ + { 28896, 0x000084C8 }, /* GL_TEXTURE8 */ + { 28908, 0x000084C8 }, /* GL_TEXTURE8_ARB */ + { 28924, 0x000084C9 }, /* GL_TEXTURE9 */ + { 28936, 0x000084C9 }, /* GL_TEXTURE9_ARB */ + { 28952, 0x00000DE0 }, /* GL_TEXTURE_1D */ + { 28966, 0x00000DE1 }, /* GL_TEXTURE_2D */ + { 28980, 0x0000806F }, /* GL_TEXTURE_3D */ + { 28994, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE */ + { 29016, 0x0000805F }, /* GL_TEXTURE_ALPHA_SIZE_EXT */ + { 29042, 0x0000813C }, /* GL_TEXTURE_BASE_LEVEL */ + { 29064, 0x00008068 }, /* GL_TEXTURE_BINDING_1D */ + { 29086, 0x00008069 }, /* GL_TEXTURE_BINDING_2D */ + { 29108, 0x0000806A }, /* GL_TEXTURE_BINDING_3D */ + { 29130, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP */ + { 29158, 0x00008514 }, /* GL_TEXTURE_BINDING_CUBE_MAP_ARB */ + { 29190, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */ + { 29223, 0x000084F6 }, /* GL_TEXTURE_BINDING_RECTANGLE_NV */ + { 29255, 0x00040000 }, /* GL_TEXTURE_BIT */ + { 29270, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE */ + { 29291, 0x0000805E }, /* GL_TEXTURE_BLUE_SIZE_EXT */ + { 29316, 0x00001005 }, /* GL_TEXTURE_BORDER */ + { 29334, 0x00001004 }, /* GL_TEXTURE_BORDER_COLOR */ + { 29358, 0x00008171 }, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */ + { 29389, 0x00008176 }, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */ + { 29419, 0x00008172 }, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */ + { 29449, 0x00008175 }, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */ + { 29484, 0x00008173 }, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */ + { 29515, 0x00008174 }, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */ + { 29553, 0x000080BC }, /* GL_TEXTURE_COLOR_TABLE_SGI */ + { 29580, 0x000081EF }, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */ + { 29612, 0x000080BF }, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */ + { 29646, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC */ + { 29670, 0x0000884D }, /* GL_TEXTURE_COMPARE_FUNC_ARB */ + { 29698, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE */ + { 29722, 0x0000884C }, /* GL_TEXTURE_COMPARE_MODE_ARB */ + { 29750, 0x0000819B }, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */ + { 29783, 0x0000819A }, /* GL_TEXTURE_COMPARE_SGIX */ + { 29807, 0x00001003 }, /* GL_TEXTURE_COMPONENTS */ + { 29829, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED */ + { 29851, 0x000086A1 }, /* GL_TEXTURE_COMPRESSED_ARB */ + { 29877, 0x000086A3 }, /* GL_TEXTURE_COMPRESSED_FORMATS_ARB */ + { 29911, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */ + { 29944, 0x000086A0 }, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB */ + { 29981, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT */ + { 30009, 0x000084EF }, /* GL_TEXTURE_COMPRESSION_HINT_ARB */ + { 30041, 0x00008078 }, /* GL_TEXTURE_COORD_ARRAY */ + { 30064, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */ + { 30102, 0x0000889A }, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB */ + { 30144, 0x00008092 }, /* GL_TEXTURE_COORD_ARRAY_POINTER */ + { 30175, 0x00008088 }, /* GL_TEXTURE_COORD_ARRAY_SIZE */ + { 30203, 0x0000808A }, /* GL_TEXTURE_COORD_ARRAY_STRIDE */ + { 30233, 0x00008089 }, /* GL_TEXTURE_COORD_ARRAY_TYPE */ + { 30261, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP */ + { 30281, 0x00008513 }, /* GL_TEXTURE_CUBE_MAP_ARB */ + { 30305, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */ + { 30336, 0x00008516 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB */ + { 30371, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */ + { 30402, 0x00008518 }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB */ + { 30437, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */ + { 30468, 0x0000851A }, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB */ + { 30503, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */ + { 30534, 0x00008515 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB */ + { 30569, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */ + { 30600, 0x00008517 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB */ + { 30635, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */ + { 30666, 0x00008519 }, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB */ + { 30701, 0x00008071 }, /* GL_TEXTURE_DEPTH */ + { 30718, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE */ + { 30740, 0x0000884A }, /* GL_TEXTURE_DEPTH_SIZE_ARB */ + { 30766, 0x00002300 }, /* GL_TEXTURE_ENV */ + { 30781, 0x00002201 }, /* GL_TEXTURE_ENV_COLOR */ + { 30802, 0x00002200 }, /* GL_TEXTURE_ENV_MODE */ + { 30822, 0x00008500 }, /* GL_TEXTURE_FILTER_CONTROL */ + { 30848, 0x00002500 }, /* GL_TEXTURE_GEN_MODE */ + { 30868, 0x00000C63 }, /* GL_TEXTURE_GEN_Q */ + { 30885, 0x00000C62 }, /* GL_TEXTURE_GEN_R */ + { 30902, 0x00000C60 }, /* GL_TEXTURE_GEN_S */ + { 30919, 0x00000C61 }, /* GL_TEXTURE_GEN_T */ + { 30936, 0x0000819D }, /* GL_TEXTURE_GEQUAL_R_SGIX */ + { 30961, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE */ + { 30983, 0x0000805D }, /* GL_TEXTURE_GREEN_SIZE_EXT */ + { 31009, 0x00001001 }, /* GL_TEXTURE_HEIGHT */ + { 31027, 0x000080ED }, /* GL_TEXTURE_INDEX_SIZE_EXT */ + { 31053, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE */ + { 31079, 0x00008061 }, /* GL_TEXTURE_INTENSITY_SIZE_EXT */ + { 31109, 0x00001003 }, /* GL_TEXTURE_INTERNAL_FORMAT */ + { 31136, 0x0000819C }, /* GL_TEXTURE_LEQUAL_R_SGIX */ + { 31161, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS */ + { 31181, 0x00008501 }, /* GL_TEXTURE_LOD_BIAS_EXT */ + { 31205, 0x00008190 }, /* GL_TEXTURE_LOD_BIAS_R_SGIX */ + { 31232, 0x0000818E }, /* GL_TEXTURE_LOD_BIAS_S_SGIX */ + { 31259, 0x0000818F }, /* GL_TEXTURE_LOD_BIAS_T_SGIX */ + { 31286, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE */ + { 31312, 0x00008060 }, /* GL_TEXTURE_LUMINANCE_SIZE_EXT */ + { 31342, 0x00002800 }, /* GL_TEXTURE_MAG_FILTER */ + { 31364, 0x00000BA8 }, /* GL_TEXTURE_MATRIX */ + { 31382, 0x000084FE }, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */ + { 31412, 0x0000836B }, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */ + { 31440, 0x00008369 }, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */ + { 31468, 0x0000836A }, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */ + { 31496, 0x0000813D }, /* GL_TEXTURE_MAX_LEVEL */ + { 31517, 0x0000813B }, /* GL_TEXTURE_MAX_LOD */ + { 31536, 0x00002801 }, /* GL_TEXTURE_MIN_FILTER */ + { 31558, 0x0000813A }, /* GL_TEXTURE_MIN_LOD */ + { 31577, 0x00008066 }, /* GL_TEXTURE_PRIORITY */ + { 31597, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_ARB */ + { 31622, 0x000084F5 }, /* GL_TEXTURE_RECTANGLE_NV */ + { 31646, 0x0000805C }, /* GL_TEXTURE_RED_SIZE */ + { 31666, 0x0000805C }, /* GL_TEXTURE_RED_SIZE_EXT */ + { 31690, 0x00008067 }, /* GL_TEXTURE_RESIDENT */ + { 31710, 0x00000BA5 }, /* GL_TEXTURE_STACK_DEPTH */ + { 31733, 0x00008065 }, /* GL_TEXTURE_TOO_LARGE_EXT */ + { 31758, 0x0000888F }, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */ + { 31792, 0x00001000 }, /* GL_TEXTURE_WIDTH */ + { 31809, 0x00008072 }, /* GL_TEXTURE_WRAP_R */ + { 31827, 0x00002802 }, /* GL_TEXTURE_WRAP_S */ + { 31845, 0x00002803 }, /* GL_TEXTURE_WRAP_T */ + { 31863, 0x00008648 }, /* GL_TRACK_MATRIX_NV */ + { 31882, 0x00008649 }, /* GL_TRACK_MATRIX_TRANSFORM_NV */ + { 31911, 0x00001000 }, /* GL_TRANSFORM_BIT */ + { 31928, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX */ + { 31954, 0x000084E6 }, /* GL_TRANSPOSE_COLOR_MATRIX_ARB */ + { 31984, 0x000088B7 }, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */ + { 32016, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX */ + { 32046, 0x000084E3 }, /* GL_TRANSPOSE_MODELVIEW_MATRIX_ARB */ + { 32080, 0x0000862C }, /* GL_TRANSPOSE_NV */ + { 32096, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX */ + { 32127, 0x000084E4 }, /* GL_TRANSPOSE_PROJECTION_MATRIX_ARB */ + { 32162, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX */ + { 32190, 0x000084E5 }, /* GL_TRANSPOSE_TEXTURE_MATRIX_ARB */ + { 32222, 0x00000004 }, /* GL_TRIANGLES */ + { 32235, 0x00000006 }, /* GL_TRIANGLE_FAN */ + { 32251, 0x00008615 }, /* GL_TRIANGLE_MESH_SUN */ + { 32272, 0x00000005 }, /* GL_TRIANGLE_STRIP */ + { 32290, 0x00000001 }, /* GL_TRUE */ + { 32298, 0x00000CF5 }, /* GL_UNPACK_ALIGNMENT */ + { 32318, 0x0000806E }, /* GL_UNPACK_IMAGE_HEIGHT */ + { 32341, 0x00000CF1 }, /* GL_UNPACK_LSB_FIRST */ + { 32361, 0x00000CF2 }, /* GL_UNPACK_ROW_LENGTH */ + { 32382, 0x0000806D }, /* GL_UNPACK_SKIP_IMAGES */ + { 32404, 0x00000CF4 }, /* GL_UNPACK_SKIP_PIXELS */ + { 32426, 0x00000CF3 }, /* GL_UNPACK_SKIP_ROWS */ + { 32446, 0x00000CF0 }, /* GL_UNPACK_SWAP_BYTES */ + { 32467, 0x00001401 }, /* GL_UNSIGNED_BYTE */ + { 32484, 0x00008362 }, /* GL_UNSIGNED_BYTE_2_3_3_REV */ + { 32511, 0x00008032 }, /* GL_UNSIGNED_BYTE_3_3_2 */ + { 32534, 0x00001405 }, /* GL_UNSIGNED_INT */ + { 32550, 0x00008036 }, /* GL_UNSIGNED_INT_10_10_10_2 */ + { 32577, 0x000084FA }, /* GL_UNSIGNED_INT_24_8_NV */ + { 32601, 0x00008368 }, /* GL_UNSIGNED_INT_2_10_10_10_REV */ + { 32632, 0x00008035 }, /* GL_UNSIGNED_INT_8_8_8_8 */ + { 32656, 0x00008367 }, /* GL_UNSIGNED_INT_8_8_8_8_REV */ + { 32684, 0x00001403 }, /* GL_UNSIGNED_SHORT */ + { 32702, 0x00008366 }, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */ + { 32732, 0x00008033 }, /* GL_UNSIGNED_SHORT_4_4_4_4 */ + { 32758, 0x00008365 }, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */ + { 32788, 0x00008034 }, /* GL_UNSIGNED_SHORT_5_5_5_1 */ + { 32814, 0x00008363 }, /* GL_UNSIGNED_SHORT_5_6_5 */ + { 32838, 0x00008364 }, /* GL_UNSIGNED_SHORT_5_6_5_REV */ + { 32866, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_APPLE */ + { 32894, 0x000085BA }, /* GL_UNSIGNED_SHORT_8_8_MESA */ + { 32921, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */ + { 32953, 0x000085BB }, /* GL_UNSIGNED_SHORT_8_8_REV_MESA */ + { 32984, 0x00002A20 }, /* GL_V2F */ + { 32991, 0x00002A21 }, /* GL_V3F */ + { 32998, 0x00001F00 }, /* GL_VENDOR */ + { 33008, 0x00001F02 }, /* GL_VERSION */ + { 33019, 0x00008074 }, /* GL_VERTEX_ARRAY */ + { 33035, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING */ + { 33066, 0x00008896 }, /* GL_VERTEX_ARRAY_BUFFER_BINDING_ARB */ + { 33101, 0x0000808E }, /* GL_VERTEX_ARRAY_POINTER */ + { 33125, 0x0000807A }, /* GL_VERTEX_ARRAY_SIZE */ + { 33146, 0x0000807C }, /* GL_VERTEX_ARRAY_STRIDE */ + { 33169, 0x0000807B }, /* GL_VERTEX_ARRAY_TYPE */ + { 33190, 0x00008650 }, /* GL_VERTEX_ATTRIB_ARRAY0_NV */ + { 33217, 0x0000865A }, /* GL_VERTEX_ATTRIB_ARRAY10_NV */ + { 33245, 0x0000865B }, /* GL_VERTEX_ATTRIB_ARRAY11_NV */ + { 33273, 0x0000865C }, /* GL_VERTEX_ATTRIB_ARRAY12_NV */ + { 33301, 0x0000865D }, /* GL_VERTEX_ATTRIB_ARRAY13_NV */ + { 33329, 0x0000865E }, /* GL_VERTEX_ATTRIB_ARRAY14_NV */ + { 33357, 0x0000865F }, /* GL_VERTEX_ATTRIB_ARRAY15_NV */ + { 33385, 0x00008651 }, /* GL_VERTEX_ATTRIB_ARRAY1_NV */ + { 33412, 0x00008652 }, /* GL_VERTEX_ATTRIB_ARRAY2_NV */ + { 33439, 0x00008653 }, /* GL_VERTEX_ATTRIB_ARRAY3_NV */ + { 33466, 0x00008654 }, /* GL_VERTEX_ATTRIB_ARRAY4_NV */ + { 33493, 0x00008655 }, /* GL_VERTEX_ATTRIB_ARRAY5_NV */ + { 33520, 0x00008656 }, /* GL_VERTEX_ATTRIB_ARRAY6_NV */ + { 33547, 0x00008657 }, /* GL_VERTEX_ATTRIB_ARRAY7_NV */ + { 33574, 0x00008658 }, /* GL_VERTEX_ATTRIB_ARRAY8_NV */ + { 33601, 0x00008659 }, /* GL_VERTEX_ATTRIB_ARRAY9_NV */ + { 33628, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */ + { 33666, 0x0000889F }, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB */ + { 33708, 0x00008622 }, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB */ + { 33743, 0x0000886A }, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB */ + { 33781, 0x00008645 }, /* GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB */ + { 33816, 0x00008623 }, /* GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB */ + { 33848, 0x00008624 }, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB */ + { 33882, 0x00008625 }, /* GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB */ + { 33914, 0x000086A7 }, /* GL_VERTEX_BLEND_ARB */ + { 33934, 0x00008620 }, /* GL_VERTEX_PROGRAM_ARB */ + { 33956, 0x0000864A }, /* GL_VERTEX_PROGRAM_BINDING_NV */ + { 33985, 0x00008620 }, /* GL_VERTEX_PROGRAM_NV */ + { 34006, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_ARB */ + { 34039, 0x00008642 }, /* GL_VERTEX_PROGRAM_POINT_SIZE_NV */ + { 34071, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_ARB */ + { 34102, 0x00008643 }, /* GL_VERTEX_PROGRAM_TWO_SIDE_NV */ + { 34132, 0x00008B31 }, /* GL_VERTEX_SHADER_ARB */ + { 34153, 0x00008621 }, /* GL_VERTEX_STATE_PROGRAM_NV */ + { 34180, 0x00000BA2 }, /* GL_VIEWPORT */ + { 34192, 0x00000800 }, /* GL_VIEWPORT_BIT */ + { 34208, 0x000086AD }, /* GL_WEIGHT_ARRAY_ARB */ + { 34228, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */ + { 34259, 0x0000889E }, /* GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB */ + { 34294, 0x000086AC }, /* GL_WEIGHT_ARRAY_POINTER_ARB */ + { 34322, 0x000086AB }, /* GL_WEIGHT_ARRAY_SIZE_ARB */ + { 34347, 0x000086AA }, /* GL_WEIGHT_ARRAY_STRIDE_ARB */ + { 34374, 0x000086A9 }, /* GL_WEIGHT_ARRAY_TYPE_ARB */ + { 34399, 0x000086A6 }, /* GL_WEIGHT_SUM_UNITY_ARB */ + { 34423, 0x000081D4 }, /* GL_WRAP_BORDER_SUN */ + { 34442, 0x000088B9 }, /* GL_WRITE_ONLY */ + { 34456, 0x000088B9 }, /* GL_WRITE_ONLY_ARB */ + { 34474, 0x00001506 }, /* GL_XOR */ + { 34481, 0x000085B9 }, /* GL_YCBCR_422_APPLE */ + { 34500, 0x00008757 }, /* GL_YCBCR_MESA */ + { 34514, 0x00000000 }, /* GL_ZERO */ + { 34522, 0x00000D16 }, /* GL_ZOOM_X */ + { 34532, 0x00000D17 }, /* GL_ZOOM_Y */ +}; + +static const unsigned reduced_enums[1232] = +{ + 26, /* GL_ALL_CLIENT_ATTRIB_BITS */ + 389, /* GL_FALSE */ + 561, /* GL_LINES */ + 563, /* GL_LINE_LOOP */ + 570, /* GL_LINE_STRIP */ + 1515, /* GL_TRIANGLES */ + 1518, /* GL_TRIANGLE_STRIP */ + 1516, /* GL_TRIANGLE_FAN */ + 1112, /* GL_QUADS */ + 1114, /* GL_QUAD_STRIP */ + 1002, /* GL_POLYGON */ + 1014, /* GL_POLYGON_STIPPLE_BIT */ + 968, /* GL_PIXEL_MODE_BIT */ + 548, /* GL_LIGHTING_BIT */ + 405, /* GL_FOG_BIT */ + 8, /* GL_ACCUM */ + 579, /* GL_LOAD */ + 1152, /* GL_RETURN */ + 841, /* GL_MULT */ + 19, /* GL_ADD */ + 857, /* GL_NEVER */ + 538, /* GL_LESS */ + 379, /* GL_EQUAL */ + 537, /* GL_LEQUAL */ + 467, /* GL_GREATER */ + 872, /* GL_NOTEQUAL */ + 466, /* GL_GEQUAL */ + 42, /* GL_ALWAYS */ + 1276, /* GL_SRC_COLOR */ + 901, /* GL_ONE_MINUS_SRC_COLOR */ + 1274, /* GL_SRC_ALPHA */ + 900, /* GL_ONE_MINUS_SRC_ALPHA */ + 359, /* GL_DST_ALPHA */ + 898, /* GL_ONE_MINUS_DST_ALPHA */ + 360, /* GL_DST_COLOR */ + 899, /* GL_ONE_MINUS_DST_COLOR */ + 1275, /* GL_SRC_ALPHA_SATURATE */ + 454, /* GL_FRONT_LEFT */ + 455, /* GL_FRONT_RIGHT */ + 64, /* GL_BACK_LEFT */ + 65, /* GL_BACK_RIGHT */ + 451, /* GL_FRONT */ + 63, /* GL_BACK */ + 536, /* GL_LEFT */ + 1192, /* GL_RIGHT */ + 452, /* GL_FRONT_AND_BACK */ + 58, /* GL_AUX0 */ + 59, /* GL_AUX1 */ + 60, /* GL_AUX2 */ + 61, /* GL_AUX3 */ + 528, /* GL_INVALID_ENUM */ + 531, /* GL_INVALID_VALUE */ + 530, /* GL_INVALID_OPERATION */ + 1277, /* GL_STACK_OVERFLOW */ + 1278, /* GL_STACK_UNDERFLOW */ + 926, /* GL_OUT_OF_MEMORY */ + 529, /* GL_INVALID_FRAMEBUFFER_OPERATION_EXT */ + 0, /* GL_2D */ + 2, /* GL_3D */ + 3, /* GL_3D_COLOR */ + 4, /* GL_3D_COLOR_TEXTURE */ + 6, /* GL_4D_COLOR_TEXTURE */ + 946, /* GL_PASS_THROUGH_TOKEN */ + 1001, /* GL_POINT_TOKEN */ + 571, /* GL_LINE_TOKEN */ + 1015, /* GL_POLYGON_TOKEN */ + 69, /* GL_BITMAP_TOKEN */ + 358, /* GL_DRAW_PIXEL_TOKEN */ + 248, /* GL_COPY_PIXEL_TOKEN */ + 564, /* GL_LINE_RESET_TOKEN */ + 382, /* GL_EXP */ + 383, /* GL_EXP2 */ + 279, /* GL_CW */ + 106, /* GL_CCW */ + 127, /* GL_COEFF */ + 923, /* GL_ORDER */ + 315, /* GL_DOMAIN */ + 256, /* GL_CURRENT_COLOR */ + 259, /* GL_CURRENT_INDEX */ + 265, /* GL_CURRENT_NORMAL */ + 276, /* GL_CURRENT_TEXTURE_COORDS */ + 269, /* GL_CURRENT_RASTER_COLOR */ + 271, /* GL_CURRENT_RASTER_INDEX */ + 274, /* GL_CURRENT_RASTER_TEXTURE_COORDS */ + 272, /* GL_CURRENT_RASTER_POSITION */ + 273, /* GL_CURRENT_RASTER_POSITION_VALID */ + 270, /* GL_CURRENT_RASTER_DISTANCE */ + 995, /* GL_POINT_SMOOTH */ + 984, /* GL_POINT_SIZE */ + 994, /* GL_POINT_SIZE_RANGE */ + 985, /* GL_POINT_SIZE_GRANULARITY */ + 565, /* GL_LINE_SMOOTH */ + 572, /* GL_LINE_WIDTH */ + 574, /* GL_LINE_WIDTH_RANGE */ + 573, /* GL_LINE_WIDTH_GRANULARITY */ + 567, /* GL_LINE_STIPPLE */ + 568, /* GL_LINE_STIPPLE_PATTERN */ + 569, /* GL_LINE_STIPPLE_REPEAT */ + 578, /* GL_LIST_MODE */ + 732, /* GL_MAX_LIST_NESTING */ + 575, /* GL_LIST_BASE */ + 577, /* GL_LIST_INDEX */ + 1004, /* GL_POLYGON_MODE */ + 1011, /* GL_POLYGON_SMOOTH */ + 1013, /* GL_POLYGON_STIPPLE */ + 367, /* GL_EDGE_FLAG */ + 249, /* GL_CULL_FACE */ + 250, /* GL_CULL_FACE_MODE */ + 453, /* GL_FRONT_FACE */ + 547, /* GL_LIGHTING */ + 552, /* GL_LIGHT_MODEL_LOCAL_VIEWER */ + 553, /* GL_LIGHT_MODEL_TWO_SIDE */ + 549, /* GL_LIGHT_MODEL_AMBIENT */ + 1230, /* GL_SHADE_MODEL */ + 158, /* GL_COLOR_MATERIAL_FACE */ + 159, /* GL_COLOR_MATERIAL_PARAMETER */ + 157, /* GL_COLOR_MATERIAL */ + 404, /* GL_FOG */ + 426, /* GL_FOG_INDEX */ + 422, /* GL_FOG_DENSITY */ + 430, /* GL_FOG_START */ + 424, /* GL_FOG_END */ + 427, /* GL_FOG_MODE */ + 406, /* GL_FOG_COLOR */ + 304, /* GL_DEPTH_RANGE */ + 309, /* GL_DEPTH_TEST */ + 312, /* GL_DEPTH_WRITEMASK */ + 292, /* GL_DEPTH_CLEAR_VALUE */ + 303, /* GL_DEPTH_FUNC */ + 12, /* GL_ACCUM_CLEAR_VALUE */ + 1301, /* GL_STENCIL_TEST */ + 1289, /* GL_STENCIL_CLEAR_VALUE */ + 1291, /* GL_STENCIL_FUNC */ + 1303, /* GL_STENCIL_VALUE_MASK */ + 1290, /* GL_STENCIL_FAIL */ + 1298, /* GL_STENCIL_PASS_DEPTH_FAIL */ + 1299, /* GL_STENCIL_PASS_DEPTH_PASS */ + 1300, /* GL_STENCIL_REF */ + 1304, /* GL_STENCIL_WRITEMASK */ + 705, /* GL_MATRIX_MODE */ + 862, /* GL_NORMALIZE */ + 1593, /* GL_VIEWPORT */ + 836, /* GL_MODELVIEW_STACK_DEPTH */ + 1094, /* GL_PROJECTION_STACK_DEPTH */ + 1495, /* GL_TEXTURE_STACK_DEPTH */ + 834, /* GL_MODELVIEW_MATRIX */ + 1093, /* GL_PROJECTION_MATRIX */ + 1480, /* GL_TEXTURE_MATRIX */ + 56, /* GL_ATTRIB_STACK_DEPTH */ + 117, /* GL_CLIENT_ATTRIB_STACK_DEPTH */ + 39, /* GL_ALPHA_TEST */ + 40, /* GL_ALPHA_TEST_FUNC */ + 41, /* GL_ALPHA_TEST_REF */ + 314, /* GL_DITHER */ + 73, /* GL_BLEND_DST */ + 80, /* GL_BLEND_SRC */ + 70, /* GL_BLEND */ + 581, /* GL_LOGIC_OP_MODE */ + 506, /* GL_INDEX_LOGIC_OP */ + 156, /* GL_COLOR_LOGIC_OP */ + 62, /* GL_AUX_BUFFERS */ + 325, /* GL_DRAW_BUFFER */ + 1124, /* GL_READ_BUFFER */ + 1213, /* GL_SCISSOR_BOX */ + 1214, /* GL_SCISSOR_TEST */ + 505, /* GL_INDEX_CLEAR_VALUE */ + 510, /* GL_INDEX_WRITEMASK */ + 153, /* GL_COLOR_CLEAR_VALUE */ + 185, /* GL_COLOR_WRITEMASK */ + 507, /* GL_INDEX_MODE */ + 1186, /* GL_RGBA_MODE */ + 324, /* GL_DOUBLEBUFFER */ + 1305, /* GL_STEREO */ + 1145, /* GL_RENDER_MODE */ + 947, /* GL_PERSPECTIVE_CORRECTION_HINT */ + 996, /* GL_POINT_SMOOTH_HINT */ + 566, /* GL_LINE_SMOOTH_HINT */ + 1012, /* GL_POLYGON_SMOOTH_HINT */ + 425, /* GL_FOG_HINT */ + 1461, /* GL_TEXTURE_GEN_S */ + 1462, /* GL_TEXTURE_GEN_T */ + 1460, /* GL_TEXTURE_GEN_R */ + 1459, /* GL_TEXTURE_GEN_Q */ + 960, /* GL_PIXEL_MAP_I_TO_I */ + 966, /* GL_PIXEL_MAP_S_TO_S */ + 962, /* GL_PIXEL_MAP_I_TO_R */ + 958, /* GL_PIXEL_MAP_I_TO_G */ + 956, /* GL_PIXEL_MAP_I_TO_B */ + 954, /* GL_PIXEL_MAP_I_TO_A */ + 964, /* GL_PIXEL_MAP_R_TO_R */ + 952, /* GL_PIXEL_MAP_G_TO_G */ + 950, /* GL_PIXEL_MAP_B_TO_B */ + 948, /* GL_PIXEL_MAP_A_TO_A */ + 961, /* GL_PIXEL_MAP_I_TO_I_SIZE */ + 967, /* GL_PIXEL_MAP_S_TO_S_SIZE */ + 963, /* GL_PIXEL_MAP_I_TO_R_SIZE */ + 959, /* GL_PIXEL_MAP_I_TO_G_SIZE */ + 957, /* GL_PIXEL_MAP_I_TO_B_SIZE */ + 955, /* GL_PIXEL_MAP_I_TO_A_SIZE */ + 965, /* GL_PIXEL_MAP_R_TO_R_SIZE */ + 953, /* GL_PIXEL_MAP_G_TO_G_SIZE */ + 951, /* GL_PIXEL_MAP_B_TO_B_SIZE */ + 949, /* GL_PIXEL_MAP_A_TO_A_SIZE */ + 1527, /* GL_UNPACK_SWAP_BYTES */ + 1522, /* GL_UNPACK_LSB_FIRST */ + 1523, /* GL_UNPACK_ROW_LENGTH */ + 1526, /* GL_UNPACK_SKIP_ROWS */ + 1525, /* GL_UNPACK_SKIP_PIXELS */ + 1520, /* GL_UNPACK_ALIGNMENT */ + 935, /* GL_PACK_SWAP_BYTES */ + 930, /* GL_PACK_LSB_FIRST */ + 931, /* GL_PACK_ROW_LENGTH */ + 934, /* GL_PACK_SKIP_ROWS */ + 933, /* GL_PACK_SKIP_PIXELS */ + 927, /* GL_PACK_ALIGNMENT */ + 658, /* GL_MAP_COLOR */ + 659, /* GL_MAP_STENCIL */ + 509, /* GL_INDEX_SHIFT */ + 508, /* GL_INDEX_OFFSET */ + 1134, /* GL_RED_SCALE */ + 1132, /* GL_RED_BIAS */ + 1610, /* GL_ZOOM_X */ + 1611, /* GL_ZOOM_Y */ + 471, /* GL_GREEN_SCALE */ + 469, /* GL_GREEN_BIAS */ + 86, /* GL_BLUE_SCALE */ + 84, /* GL_BLUE_BIAS */ + 38, /* GL_ALPHA_SCALE */ + 36, /* GL_ALPHA_BIAS */ + 305, /* GL_DEPTH_SCALE */ + 286, /* GL_DEPTH_BIAS */ + 728, /* GL_MAX_EVAL_ORDER */ + 731, /* GL_MAX_LIGHTS */ + 713, /* GL_MAX_CLIP_PLANES */ + 773, /* GL_MAX_TEXTURE_SIZE */ + 737, /* GL_MAX_PIXEL_MAP_TABLE */ + 709, /* GL_MAX_ATTRIB_STACK_DEPTH */ + 734, /* GL_MAX_MODELVIEW_STACK_DEPTH */ + 735, /* GL_MAX_NAME_STACK_DEPTH */ + 763, /* GL_MAX_PROJECTION_STACK_DEPTH */ + 774, /* GL_MAX_TEXTURE_STACK_DEPTH */ + 784, /* GL_MAX_VIEWPORT_DIMS */ + 710, /* GL_MAX_CLIENT_ATTRIB_STACK_DEPTH */ + 1312, /* GL_SUBPIXEL_BITS */ + 504, /* GL_INDEX_BITS */ + 1133, /* GL_RED_BITS */ + 470, /* GL_GREEN_BITS */ + 85, /* GL_BLUE_BITS */ + 37, /* GL_ALPHA_BITS */ + 287, /* GL_DEPTH_BITS */ + 1287, /* GL_STENCIL_BITS */ + 14, /* GL_ACCUM_RED_BITS */ + 13, /* GL_ACCUM_GREEN_BITS */ + 10, /* GL_ACCUM_BLUE_BITS */ + 9, /* GL_ACCUM_ALPHA_BITS */ + 850, /* GL_NAME_STACK_DEPTH */ + 57, /* GL_AUTO_NORMAL */ + 604, /* GL_MAP1_COLOR_4 */ + 607, /* GL_MAP1_INDEX */ + 608, /* GL_MAP1_NORMAL */ + 609, /* GL_MAP1_TEXTURE_COORD_1 */ + 610, /* GL_MAP1_TEXTURE_COORD_2 */ + 611, /* GL_MAP1_TEXTURE_COORD_3 */ + 612, /* GL_MAP1_TEXTURE_COORD_4 */ + 613, /* GL_MAP1_VERTEX_3 */ + 614, /* GL_MAP1_VERTEX_4 */ + 631, /* GL_MAP2_COLOR_4 */ + 634, /* GL_MAP2_INDEX */ + 635, /* GL_MAP2_NORMAL */ + 636, /* GL_MAP2_TEXTURE_COORD_1 */ + 637, /* GL_MAP2_TEXTURE_COORD_2 */ + 638, /* GL_MAP2_TEXTURE_COORD_3 */ + 639, /* GL_MAP2_TEXTURE_COORD_4 */ + 640, /* GL_MAP2_VERTEX_3 */ + 641, /* GL_MAP2_VERTEX_4 */ + 605, /* GL_MAP1_GRID_DOMAIN */ + 606, /* GL_MAP1_GRID_SEGMENTS */ + 632, /* GL_MAP2_GRID_DOMAIN */ + 633, /* GL_MAP2_GRID_SEGMENTS */ + 1389, /* GL_TEXTURE_1D */ + 1390, /* GL_TEXTURE_2D */ + 392, /* GL_FEEDBACK_BUFFER_POINTER */ + 393, /* GL_FEEDBACK_BUFFER_SIZE */ + 394, /* GL_FEEDBACK_BUFFER_TYPE */ + 1223, /* GL_SELECTION_BUFFER_POINTER */ + 1224, /* GL_SELECTION_BUFFER_SIZE */ + 1498, /* GL_TEXTURE_WIDTH */ + 1466, /* GL_TEXTURE_HEIGHT */ + 1422, /* GL_TEXTURE_COMPONENTS */ + 1406, /* GL_TEXTURE_BORDER_COLOR */ + 1405, /* GL_TEXTURE_BORDER */ + 316, /* GL_DONT_CARE */ + 390, /* GL_FASTEST */ + 858, /* GL_NICEST */ + 43, /* GL_AMBIENT */ + 313, /* GL_DIFFUSE */ + 1263, /* GL_SPECULAR */ + 1016, /* GL_POSITION */ + 1266, /* GL_SPOT_DIRECTION */ + 1267, /* GL_SPOT_EXPONENT */ + 1265, /* GL_SPOT_CUTOFF */ + 223, /* GL_CONSTANT_ATTENUATION */ + 556, /* GL_LINEAR_ATTENUATION */ + 1111, /* GL_QUADRATIC_ATTENUATION */ + 198, /* GL_COMPILE */ + 199, /* GL_COMPILE_AND_EXECUTE */ + 101, /* GL_BYTE */ + 1528, /* GL_UNSIGNED_BYTE */ + 1234, /* GL_SHORT */ + 1537, /* GL_UNSIGNED_SHORT */ + 511, /* GL_INT */ + 1531, /* GL_UNSIGNED_INT */ + 397, /* GL_FLOAT */ + 1, /* GL_2_BYTES */ + 5, /* GL_3_BYTES */ + 7, /* GL_4_BYTES */ + 323, /* GL_DOUBLE */ + 113, /* GL_CLEAR */ + 45, /* GL_AND */ + 47, /* GL_AND_REVERSE */ + 246, /* GL_COPY */ + 46, /* GL_AND_INVERTED */ + 860, /* GL_NOOP */ + 1606, /* GL_XOR */ + 922, /* GL_OR */ + 861, /* GL_NOR */ + 380, /* GL_EQUIV */ + 534, /* GL_INVERT */ + 925, /* GL_OR_REVERSE */ + 247, /* GL_COPY_INVERTED */ + 924, /* GL_OR_INVERTED */ + 851, /* GL_NAND */ + 1228, /* GL_SET */ + 377, /* GL_EMISSION */ + 1233, /* GL_SHININESS */ + 44, /* GL_AMBIENT_AND_DIFFUSE */ + 155, /* GL_COLOR_INDEXES */ + 801, /* GL_MODELVIEW */ + 1092, /* GL_PROJECTION */ + 1324, /* GL_TEXTURE */ + 128, /* GL_COLOR */ + 284, /* GL_DEPTH */ + 1285, /* GL_STENCIL */ + 154, /* GL_COLOR_INDEX */ + 1292, /* GL_STENCIL_INDEX */ + 293, /* GL_DEPTH_COMPONENT */ + 1129, /* GL_RED */ + 468, /* GL_GREEN */ + 83, /* GL_BLUE */ + 27, /* GL_ALPHA */ + 1153, /* GL_RGB */ + 1172, /* GL_RGBA */ + 582, /* GL_LUMINANCE */ + 603, /* GL_LUMINANCE_ALPHA */ + 68, /* GL_BITMAP */ + 973, /* GL_POINT */ + 554, /* GL_LINE */ + 395, /* GL_FILL */ + 1138, /* GL_RENDER */ + 391, /* GL_FEEDBACK */ + 1222, /* GL_SELECT */ + 396, /* GL_FLAT */ + 1238, /* GL_SMOOTH */ + 535, /* GL_KEEP */ + 1147, /* GL_REPLACE */ + 495, /* GL_INCR */ + 281, /* GL_DECR */ + 1550, /* GL_VENDOR */ + 1144, /* GL_RENDERER */ + 1551, /* GL_VERSION */ + 384, /* GL_EXTENSIONS */ + 1193, /* GL_S */ + 1315, /* GL_T */ + 1121, /* GL_R */ + 1110, /* GL_Q */ + 837, /* GL_MODULATE */ + 280, /* GL_DECAL */ + 1456, /* GL_TEXTURE_ENV_MODE */ + 1455, /* GL_TEXTURE_ENV_COLOR */ + 1454, /* GL_TEXTURE_ENV */ + 385, /* GL_EYE_LINEAR */ + 884, /* GL_OBJECT_LINEAR */ + 1264, /* GL_SPHERE_MAP */ + 1458, /* GL_TEXTURE_GEN_MODE */ + 886, /* GL_OBJECT_PLANE */ + 386, /* GL_EYE_PLANE */ + 852, /* GL_NEAREST */ + 555, /* GL_LINEAR */ + 856, /* GL_NEAREST_MIPMAP_NEAREST */ + 560, /* GL_LINEAR_MIPMAP_NEAREST */ + 855, /* GL_NEAREST_MIPMAP_LINEAR */ + 559, /* GL_LINEAR_MIPMAP_LINEAR */ + 1479, /* GL_TEXTURE_MAG_FILTER */ + 1487, /* GL_TEXTURE_MIN_FILTER */ + 1500, /* GL_TEXTURE_WRAP_S */ + 1501, /* GL_TEXTURE_WRAP_T */ + 107, /* GL_CLAMP */ + 1146, /* GL_REPEAT */ + 1010, /* GL_POLYGON_OFFSET_UNITS */ + 1009, /* GL_POLYGON_OFFSET_POINT */ + 1008, /* GL_POLYGON_OFFSET_LINE */ + 1122, /* GL_R3_G3_B2 */ + 1548, /* GL_V2F */ + 1549, /* GL_V3F */ + 104, /* GL_C4UB_V2F */ + 105, /* GL_C4UB_V3F */ + 102, /* GL_C3F_V3F */ + 849, /* GL_N3F_V3F */ + 103, /* GL_C4F_N3F_V3F */ + 1320, /* GL_T2F_V3F */ + 1322, /* GL_T4F_V4F */ + 1318, /* GL_T2F_C4UB_V3F */ + 1316, /* GL_T2F_C3F_V3F */ + 1319, /* GL_T2F_N3F_V3F */ + 1317, /* GL_T2F_C4F_N3F_V3F */ + 1321, /* GL_T4F_C4F_N3F_V4F */ + 120, /* GL_CLIP_PLANE0 */ + 121, /* GL_CLIP_PLANE1 */ + 122, /* GL_CLIP_PLANE2 */ + 123, /* GL_CLIP_PLANE3 */ + 124, /* GL_CLIP_PLANE4 */ + 125, /* GL_CLIP_PLANE5 */ + 539, /* GL_LIGHT0 */ + 540, /* GL_LIGHT1 */ + 541, /* GL_LIGHT2 */ + 542, /* GL_LIGHT3 */ + 543, /* GL_LIGHT4 */ + 544, /* GL_LIGHT5 */ + 545, /* GL_LIGHT6 */ + 546, /* GL_LIGHT7 */ + 472, /* GL_HINT_BIT */ + 225, /* GL_CONSTANT_COLOR */ + 896, /* GL_ONE_MINUS_CONSTANT_COLOR */ + 220, /* GL_CONSTANT_ALPHA */ + 894, /* GL_ONE_MINUS_CONSTANT_ALPHA */ + 71, /* GL_BLEND_COLOR */ + 456, /* GL_FUNC_ADD */ + 785, /* GL_MIN */ + 707, /* GL_MAX */ + 76, /* GL_BLEND_EQUATION */ + 460, /* GL_FUNC_SUBTRACT */ + 458, /* GL_FUNC_REVERSE_SUBTRACT */ + 228, /* GL_CONVOLUTION_1D */ + 229, /* GL_CONVOLUTION_2D */ + 1225, /* GL_SEPARABLE_2D */ + 232, /* GL_CONVOLUTION_BORDER_MODE */ + 236, /* GL_CONVOLUTION_FILTER_SCALE */ + 234, /* GL_CONVOLUTION_FILTER_BIAS */ + 1130, /* GL_REDUCE */ + 238, /* GL_CONVOLUTION_FORMAT */ + 242, /* GL_CONVOLUTION_WIDTH */ + 240, /* GL_CONVOLUTION_HEIGHT */ + 720, /* GL_MAX_CONVOLUTION_WIDTH */ + 718, /* GL_MAX_CONVOLUTION_HEIGHT */ + 1049, /* GL_POST_CONVOLUTION_RED_SCALE */ + 1045, /* GL_POST_CONVOLUTION_GREEN_SCALE */ + 1040, /* GL_POST_CONVOLUTION_BLUE_SCALE */ + 1036, /* GL_POST_CONVOLUTION_ALPHA_SCALE */ + 1047, /* GL_POST_CONVOLUTION_RED_BIAS */ + 1043, /* GL_POST_CONVOLUTION_GREEN_BIAS */ + 1038, /* GL_POST_CONVOLUTION_BLUE_BIAS */ + 1034, /* GL_POST_CONVOLUTION_ALPHA_BIAS */ + 473, /* GL_HISTOGRAM */ + 1096, /* GL_PROXY_HISTOGRAM */ + 489, /* GL_HISTOGRAM_WIDTH */ + 479, /* GL_HISTOGRAM_FORMAT */ + 485, /* GL_HISTOGRAM_RED_SIZE */ + 481, /* GL_HISTOGRAM_GREEN_SIZE */ + 476, /* GL_HISTOGRAM_BLUE_SIZE */ + 474, /* GL_HISTOGRAM_ALPHA_SIZE */ + 483, /* GL_HISTOGRAM_LUMINANCE_SIZE */ + 487, /* GL_HISTOGRAM_SINK */ + 786, /* GL_MINMAX */ + 788, /* GL_MINMAX_FORMAT */ + 790, /* GL_MINMAX_SINK */ + 1323, /* GL_TABLE_TOO_LARGE_EXT */ + 1530, /* GL_UNSIGNED_BYTE_3_3_2 */ + 1539, /* GL_UNSIGNED_SHORT_4_4_4_4 */ + 1541, /* GL_UNSIGNED_SHORT_5_5_5_1 */ + 1535, /* GL_UNSIGNED_INT_8_8_8_8 */ + 1532, /* GL_UNSIGNED_INT_10_10_10_2 */ + 1007, /* GL_POLYGON_OFFSET_FILL */ + 1006, /* GL_POLYGON_OFFSET_FACTOR */ + 1005, /* GL_POLYGON_OFFSET_BIAS */ + 1150, /* GL_RESCALE_NORMAL */ + 32, /* GL_ALPHA4 */ + 34, /* GL_ALPHA8 */ + 28, /* GL_ALPHA12 */ + 30, /* GL_ALPHA16 */ + 593, /* GL_LUMINANCE4 */ + 599, /* GL_LUMINANCE8 */ + 583, /* GL_LUMINANCE12 */ + 589, /* GL_LUMINANCE16 */ + 594, /* GL_LUMINANCE4_ALPHA4 */ + 597, /* GL_LUMINANCE6_ALPHA2 */ + 600, /* GL_LUMINANCE8_ALPHA8 */ + 586, /* GL_LUMINANCE12_ALPHA4 */ + 584, /* GL_LUMINANCE12_ALPHA12 */ + 590, /* GL_LUMINANCE16_ALPHA16 */ + 512, /* GL_INTENSITY */ + 517, /* GL_INTENSITY4 */ + 519, /* GL_INTENSITY8 */ + 513, /* GL_INTENSITY12 */ + 515, /* GL_INTENSITY16 */ + 1162, /* GL_RGB2_EXT */ + 1163, /* GL_RGB4 */ + 1166, /* GL_RGB5 */ + 1170, /* GL_RGB8 */ + 1154, /* GL_RGB10 */ + 1158, /* GL_RGB12 */ + 1160, /* GL_RGB16 */ + 1177, /* GL_RGBA2 */ + 1179, /* GL_RGBA4 */ + 1167, /* GL_RGB5_A1 */ + 1183, /* GL_RGBA8 */ + 1155, /* GL_RGB10_A2 */ + 1173, /* GL_RGBA12 */ + 1175, /* GL_RGBA16 */ + 1492, /* GL_TEXTURE_RED_SIZE */ + 1464, /* GL_TEXTURE_GREEN_SIZE */ + 1403, /* GL_TEXTURE_BLUE_SIZE */ + 1392, /* GL_TEXTURE_ALPHA_SIZE */ + 1477, /* GL_TEXTURE_LUMINANCE_SIZE */ + 1468, /* GL_TEXTURE_INTENSITY_SIZE */ + 1148, /* GL_REPLACE_EXT */ + 1100, /* GL_PROXY_TEXTURE_1D */ + 1102, /* GL_PROXY_TEXTURE_2D */ + 1496, /* GL_TEXTURE_TOO_LARGE_EXT */ + 1489, /* GL_TEXTURE_PRIORITY */ + 1494, /* GL_TEXTURE_RESIDENT */ + 1395, /* GL_TEXTURE_BINDING_1D */ + 1396, /* GL_TEXTURE_BINDING_2D */ + 1397, /* GL_TEXTURE_BINDING_3D */ + 932, /* GL_PACK_SKIP_IMAGES */ + 928, /* GL_PACK_IMAGE_HEIGHT */ + 1524, /* GL_UNPACK_SKIP_IMAGES */ + 1521, /* GL_UNPACK_IMAGE_HEIGHT */ + 1391, /* GL_TEXTURE_3D */ + 1104, /* GL_PROXY_TEXTURE_3D */ + 1451, /* GL_TEXTURE_DEPTH */ + 1499, /* GL_TEXTURE_WRAP_R */ + 708, /* GL_MAX_3D_TEXTURE_SIZE */ + 1552, /* GL_VERTEX_ARRAY */ + 863, /* GL_NORMAL_ARRAY */ + 129, /* GL_COLOR_ARRAY */ + 498, /* GL_INDEX_ARRAY */ + 1430, /* GL_TEXTURE_COORD_ARRAY */ + 368, /* GL_EDGE_FLAG_ARRAY */ + 1556, /* GL_VERTEX_ARRAY_SIZE */ + 1558, /* GL_VERTEX_ARRAY_TYPE */ + 1557, /* GL_VERTEX_ARRAY_STRIDE */ + 868, /* GL_NORMAL_ARRAY_TYPE */ + 867, /* GL_NORMAL_ARRAY_STRIDE */ + 133, /* GL_COLOR_ARRAY_SIZE */ + 135, /* GL_COLOR_ARRAY_TYPE */ + 134, /* GL_COLOR_ARRAY_STRIDE */ + 503, /* GL_INDEX_ARRAY_TYPE */ + 502, /* GL_INDEX_ARRAY_STRIDE */ + 1434, /* GL_TEXTURE_COORD_ARRAY_SIZE */ + 1436, /* GL_TEXTURE_COORD_ARRAY_TYPE */ + 1435, /* GL_TEXTURE_COORD_ARRAY_STRIDE */ + 372, /* GL_EDGE_FLAG_ARRAY_STRIDE */ + 1555, /* GL_VERTEX_ARRAY_POINTER */ + 866, /* GL_NORMAL_ARRAY_POINTER */ + 132, /* GL_COLOR_ARRAY_POINTER */ + 501, /* GL_INDEX_ARRAY_POINTER */ + 1433, /* GL_TEXTURE_COORD_ARRAY_POINTER */ + 371, /* GL_EDGE_FLAG_ARRAY_POINTER */ + 842, /* GL_MULTISAMPLE */ + 1199, /* GL_SAMPLE_ALPHA_TO_COVERAGE */ + 1201, /* GL_SAMPLE_ALPHA_TO_ONE */ + 1206, /* GL_SAMPLE_COVERAGE */ + 1203, /* GL_SAMPLE_BUFFERS */ + 1194, /* GL_SAMPLES */ + 1210, /* GL_SAMPLE_COVERAGE_VALUE */ + 1208, /* GL_SAMPLE_COVERAGE_INVERT */ + 160, /* GL_COLOR_MATRIX */ + 162, /* GL_COLOR_MATRIX_STACK_DEPTH */ + 715, /* GL_MAX_COLOR_MATRIX_STACK_DEPTH */ + 1032, /* GL_POST_COLOR_MATRIX_RED_SCALE */ + 1028, /* GL_POST_COLOR_MATRIX_GREEN_SCALE */ + 1023, /* GL_POST_COLOR_MATRIX_BLUE_SCALE */ + 1019, /* GL_POST_COLOR_MATRIX_ALPHA_SCALE */ + 1030, /* GL_POST_COLOR_MATRIX_RED_BIAS */ + 1026, /* GL_POST_COLOR_MATRIX_GREEN_BIAS */ + 1021, /* GL_POST_COLOR_MATRIX_BLUE_BIAS */ + 1017, /* GL_POST_COLOR_MATRIX_ALPHA_BIAS */ + 1413, /* GL_TEXTURE_COLOR_TABLE_SGI */ + 1105, /* GL_PROXY_TEXTURE_COLOR_TABLE_SGI */ + 1415, /* GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */ + 75, /* GL_BLEND_DST_RGB */ + 82, /* GL_BLEND_SRC_RGB */ + 74, /* GL_BLEND_DST_ALPHA */ + 81, /* GL_BLEND_SRC_ALPHA */ + 166, /* GL_COLOR_TABLE */ + 1042, /* GL_POST_CONVOLUTION_COLOR_TABLE */ + 1025, /* GL_POST_COLOR_MATRIX_COLOR_TABLE */ + 1095, /* GL_PROXY_COLOR_TABLE */ + 1099, /* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */ + 1098, /* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */ + 182, /* GL_COLOR_TABLE_SCALE */ + 169, /* GL_COLOR_TABLE_BIAS */ + 172, /* GL_COLOR_TABLE_FORMAT */ + 183, /* GL_COLOR_TABLE_WIDTH */ + 180, /* GL_COLOR_TABLE_RED_SIZE */ + 174, /* GL_COLOR_TABLE_GREEN_SIZE */ + 170, /* GL_COLOR_TABLE_BLUE_SIZE */ + 167, /* GL_COLOR_TABLE_ALPHA_SIZE */ + 178, /* GL_COLOR_TABLE_LUMINANCE_SIZE */ + 176, /* GL_COLOR_TABLE_INTENSITY_SIZE */ + 66, /* GL_BGR */ + 67, /* GL_BGRA */ + 727, /* GL_MAX_ELEMENTS_VERTICES */ + 726, /* GL_MAX_ELEMENTS_INDICES */ + 1467, /* GL_TEXTURE_INDEX_SIZE_EXT */ + 126, /* GL_CLIP_VOLUME_CLIPPING_HINT_EXT */ + 990, /* GL_POINT_SIZE_MIN */ + 986, /* GL_POINT_SIZE_MAX */ + 980, /* GL_POINT_FADE_THRESHOLD_SIZE */ + 976, /* GL_POINT_DISTANCE_ATTENUATION */ + 108, /* GL_CLAMP_TO_BORDER */ + 111, /* GL_CLAMP_TO_EDGE */ + 1488, /* GL_TEXTURE_MIN_LOD */ + 1486, /* GL_TEXTURE_MAX_LOD */ + 1394, /* GL_TEXTURE_BASE_LEVEL */ + 1485, /* GL_TEXTURE_MAX_LEVEL */ + 492, /* GL_IGNORE_BORDER_HP */ + 224, /* GL_CONSTANT_BORDER_HP */ + 1149, /* GL_REPLICATE_BORDER_HP */ + 230, /* GL_CONVOLUTION_BORDER_COLOR */ + 891, /* GL_OCCLUSION_TEST_HP */ + 892, /* GL_OCCLUSION_TEST_RESULT_HP */ + 557, /* GL_LINEAR_CLIPMAP_LINEAR_SGIX */ + 1407, /* GL_TEXTURE_CLIPMAP_CENTER_SGIX */ + 1409, /* GL_TEXTURE_CLIPMAP_FRAME_SGIX */ + 1411, /* GL_TEXTURE_CLIPMAP_OFFSET_SGIX */ + 1412, /* GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX */ + 1410, /* GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX */ + 1408, /* GL_TEXTURE_CLIPMAP_DEPTH_SGIX */ + 711, /* GL_MAX_CLIPMAP_DEPTH_SGIX */ + 712, /* GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX */ + 1052, /* GL_POST_TEXTURE_FILTER_BIAS_SGIX */ + 1054, /* GL_POST_TEXTURE_FILTER_SCALE_SGIX */ + 1051, /* GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX */ + 1053, /* GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX */ + 1475, /* GL_TEXTURE_LOD_BIAS_S_SGIX */ + 1476, /* GL_TEXTURE_LOD_BIAS_T_SGIX */ + 1474, /* GL_TEXTURE_LOD_BIAS_R_SGIX */ + 462, /* GL_GENERATE_MIPMAP */ + 463, /* GL_GENERATE_MIPMAP_HINT */ + 428, /* GL_FOG_OFFSET_SGIX */ + 429, /* GL_FOG_OFFSET_VALUE_SGIX */ + 1421, /* GL_TEXTURE_COMPARE_SGIX */ + 1420, /* GL_TEXTURE_COMPARE_OPERATOR_SGIX */ + 1471, /* GL_TEXTURE_LEQUAL_R_SGIX */ + 1463, /* GL_TEXTURE_GEQUAL_R_SGIX */ + 294, /* GL_DEPTH_COMPONENT16 */ + 297, /* GL_DEPTH_COMPONENT24 */ + 300, /* GL_DEPTH_COMPONENT32 */ + 251, /* GL_CULL_VERTEX_EXT */ + 253, /* GL_CULL_VERTEX_OBJECT_POSITION_EXT */ + 252, /* GL_CULL_VERTEX_EYE_POSITION_EXT */ + 1603, /* GL_WRAP_BORDER_SUN */ + 1414, /* GL_TEXTURE_COLOR_WRITEMASK_SGIS */ + 550, /* GL_LIGHT_MODEL_COLOR_CONTROL */ + 1235, /* GL_SINGLE_COLOR */ + 1226, /* GL_SEPARATE_SPECULAR_COLOR */ + 1232, /* GL_SHARED_TEXTURE_PALETTE_EXT */ + 1529, /* GL_UNSIGNED_BYTE_2_3_3_REV */ + 1542, /* GL_UNSIGNED_SHORT_5_6_5 */ + 1543, /* GL_UNSIGNED_SHORT_5_6_5_REV */ + 1540, /* GL_UNSIGNED_SHORT_4_4_4_4_REV */ + 1538, /* GL_UNSIGNED_SHORT_1_5_5_5_REV */ + 1536, /* GL_UNSIGNED_INT_8_8_8_8_REV */ + 1534, /* GL_UNSIGNED_INT_2_10_10_10_REV */ + 1483, /* GL_TEXTURE_MAX_CLAMP_S_SGIX */ + 1484, /* GL_TEXTURE_MAX_CLAMP_T_SGIX */ + 1482, /* GL_TEXTURE_MAX_CLAMP_R_SGIX */ + 793, /* GL_MIRRORED_REPEAT */ + 1188, /* GL_RGB_S3TC */ + 1165, /* GL_RGB4_S3TC */ + 1187, /* GL_RGBA_S3TC */ + 1182, /* GL_RGBA4_S3TC */ + 1185, /* GL_RGBA_DXT5_S3TC */ + 1180, /* GL_RGBA4_DXT5_S3TC */ + 217, /* GL_COMPRESSED_RGB_S3TC_DXT1_EXT */ + 212, /* GL_COMPRESSED_RGBA_S3TC_DXT1_EXT */ + 213, /* GL_COMPRESSED_RGBA_S3TC_DXT3_EXT */ + 214, /* GL_COMPRESSED_RGBA_S3TC_DXT5_EXT */ + 854, /* GL_NEAREST_CLIPMAP_NEAREST_SGIX */ + 853, /* GL_NEAREST_CLIPMAP_LINEAR_SGIX */ + 558, /* GL_LINEAR_CLIPMAP_NEAREST_SGIX */ + 415, /* GL_FOG_COORDINATE_SOURCE */ + 407, /* GL_FOG_COORD */ + 431, /* GL_FRAGMENT_DEPTH */ + 257, /* GL_CURRENT_FOG_COORD */ + 414, /* GL_FOG_COORDINATE_ARRAY_TYPE */ + 413, /* GL_FOG_COORDINATE_ARRAY_STRIDE */ + 412, /* GL_FOG_COORDINATE_ARRAY_POINTER */ + 409, /* GL_FOG_COORDINATE_ARRAY */ + 164, /* GL_COLOR_SUM */ + 275, /* GL_CURRENT_SECONDARY_COLOR */ + 1219, /* GL_SECONDARY_COLOR_ARRAY_SIZE */ + 1221, /* GL_SECONDARY_COLOR_ARRAY_TYPE */ + 1220, /* GL_SECONDARY_COLOR_ARRAY_STRIDE */ + 1218, /* GL_SECONDARY_COLOR_ARRAY_POINTER */ + 1215, /* GL_SECONDARY_COLOR_ARRAY */ + 24, /* GL_ALIASED_POINT_SIZE_RANGE */ + 23, /* GL_ALIASED_LINE_WIDTH_RANGE */ + 1325, /* GL_TEXTURE0 */ + 1327, /* GL_TEXTURE1 */ + 1349, /* GL_TEXTURE2 */ + 1371, /* GL_TEXTURE3 */ + 1377, /* GL_TEXTURE4 */ + 1379, /* GL_TEXTURE5 */ + 1381, /* GL_TEXTURE6 */ + 1383, /* GL_TEXTURE7 */ + 1385, /* GL_TEXTURE8 */ + 1387, /* GL_TEXTURE9 */ + 1328, /* GL_TEXTURE10 */ + 1330, /* GL_TEXTURE11 */ + 1332, /* GL_TEXTURE12 */ + 1334, /* GL_TEXTURE13 */ + 1336, /* GL_TEXTURE14 */ + 1338, /* GL_TEXTURE15 */ + 1340, /* GL_TEXTURE16 */ + 1342, /* GL_TEXTURE17 */ + 1344, /* GL_TEXTURE18 */ + 1346, /* GL_TEXTURE19 */ + 1350, /* GL_TEXTURE20 */ + 1352, /* GL_TEXTURE21 */ + 1354, /* GL_TEXTURE22 */ + 1356, /* GL_TEXTURE23 */ + 1358, /* GL_TEXTURE24 */ + 1360, /* GL_TEXTURE25 */ + 1362, /* GL_TEXTURE26 */ + 1364, /* GL_TEXTURE27 */ + 1366, /* GL_TEXTURE28 */ + 1368, /* GL_TEXTURE29 */ + 1372, /* GL_TEXTURE30 */ + 1374, /* GL_TEXTURE31 */ + 16, /* GL_ACTIVE_TEXTURE */ + 114, /* GL_CLIENT_ACTIVE_TEXTURE */ + 775, /* GL_MAX_TEXTURE_UNITS */ + 1508, /* GL_TRANSPOSE_MODELVIEW_MATRIX */ + 1511, /* GL_TRANSPOSE_PROJECTION_MATRIX */ + 1513, /* GL_TRANSPOSE_TEXTURE_MATRIX */ + 1505, /* GL_TRANSPOSE_COLOR_MATRIX */ + 1313, /* GL_SUBTRACT */ + 766, /* GL_MAX_RENDERBUFFER_SIZE_EXT */ + 200, /* GL_COMPRESSED_ALPHA */ + 204, /* GL_COMPRESSED_LUMINANCE */ + 205, /* GL_COMPRESSED_LUMINANCE_ALPHA */ + 202, /* GL_COMPRESSED_INTENSITY */ + 208, /* GL_COMPRESSED_RGB */ + 209, /* GL_COMPRESSED_RGBA */ + 1428, /* GL_TEXTURE_COMPRESSION_HINT */ + 1490, /* GL_TEXTURE_RECTANGLE_ARB */ + 1400, /* GL_TEXTURE_BINDING_RECTANGLE_ARB */ + 1108, /* GL_PROXY_TEXTURE_RECTANGLE_ARB */ + 764, /* GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB */ + 306, /* GL_DEPTH_STENCIL_NV */ + 1533, /* GL_UNSIGNED_INT_24_8_NV */ + 771, /* GL_MAX_TEXTURE_LOD_BIAS */ + 1481, /* GL_TEXTURE_MAX_ANISOTROPY_EXT */ + 772, /* GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT */ + 1457, /* GL_TEXTURE_FILTER_CONTROL */ + 1472, /* GL_TEXTURE_LOD_BIAS */ + 187, /* GL_COMBINE4 */ + 767, /* GL_MAX_SHININESS_NV */ + 768, /* GL_MAX_SPOT_EXPONENT_NV */ + 496, /* GL_INCR_WRAP */ + 282, /* GL_DECR_WRAP */ + 813, /* GL_MODELVIEW1_ARB */ + 869, /* GL_NORMAL_MAP */ + 1135, /* GL_REFLECTION_MAP */ + 1437, /* GL_TEXTURE_CUBE_MAP */ + 1398, /* GL_TEXTURE_BINDING_CUBE_MAP */ + 1445, /* GL_TEXTURE_CUBE_MAP_POSITIVE_X */ + 1439, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_X */ + 1447, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Y */ + 1441, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Y */ + 1449, /* GL_TEXTURE_CUBE_MAP_POSITIVE_Z */ + 1443, /* GL_TEXTURE_CUBE_MAP_NEGATIVE_Z */ + 1106, /* GL_PROXY_TEXTURE_CUBE_MAP */ + 722, /* GL_MAX_CUBE_MAP_TEXTURE_SIZE */ + 848, /* GL_MULTISAMPLE_FILTER_HINT_NV */ + 423, /* GL_FOG_DISTANCE_MODE_NV */ + 388, /* GL_EYE_RADIAL_NV */ + 387, /* GL_EYE_PLANE_ABSOLUTE_NV */ + 186, /* GL_COMBINE */ + 193, /* GL_COMBINE_RGB */ + 188, /* GL_COMBINE_ALPHA */ + 1189, /* GL_RGB_SCALE */ + 20, /* GL_ADD_SIGNED */ + 522, /* GL_INTERPOLATE */ + 219, /* GL_CONSTANT */ + 1058, /* GL_PRIMARY_COLOR */ + 1055, /* GL_PREVIOUS */ + 1246, /* GL_SOURCE0_RGB */ + 1252, /* GL_SOURCE1_RGB */ + 1258, /* GL_SOURCE2_RGB */ + 1262, /* GL_SOURCE3_RGB_NV */ + 1243, /* GL_SOURCE0_ALPHA */ + 1249, /* GL_SOURCE1_ALPHA */ + 1255, /* GL_SOURCE2_ALPHA */ + 1261, /* GL_SOURCE3_ALPHA_NV */ + 905, /* GL_OPERAND0_RGB */ + 911, /* GL_OPERAND1_RGB */ + 917, /* GL_OPERAND2_RGB */ + 921, /* GL_OPERAND3_RGB_NV */ + 902, /* GL_OPERAND0_ALPHA */ + 908, /* GL_OPERAND1_ALPHA */ + 914, /* GL_OPERAND2_ALPHA */ + 920, /* GL_OPERAND3_ALPHA_NV */ + 1607, /* GL_YCBCR_422_APPLE */ + 1544, /* GL_UNSIGNED_SHORT_8_8_APPLE */ + 1546, /* GL_UNSIGNED_SHORT_8_8_REV_APPLE */ + 1237, /* GL_SLICE_ACCUM_SUN */ + 1113, /* GL_QUAD_MESH_SUN */ + 1517, /* GL_TRIANGLE_MESH_SUN */ + 1584, /* GL_VERTEX_PROGRAM_ARB */ + 1592, /* GL_VERTEX_STATE_PROGRAM_NV */ + 1577, /* GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB */ + 1580, /* GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB */ + 1581, /* GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB */ + 1582, /* GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB */ + 277, /* GL_CURRENT_VERTEX_ATTRIB_ARB */ + 1071, /* GL_PROGRAM_LENGTH_ARB */ + 1085, /* GL_PROGRAM_STRING_ARB */ + 835, /* GL_MODELVIEW_PROJECTION_NV */ + 491, /* GL_IDENTITY_NV */ + 532, /* GL_INVERSE_NV */ + 1510, /* GL_TRANSPOSE_NV */ + 533, /* GL_INVERSE_TRANSPOSE_NV */ + 750, /* GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB */ + 749, /* GL_MAX_PROGRAM_MATRICES_ARB */ + 661, /* GL_MATRIX0_NV */ + 673, /* GL_MATRIX1_NV */ + 685, /* GL_MATRIX2_NV */ + 689, /* GL_MATRIX3_NV */ + 691, /* GL_MATRIX4_NV */ + 693, /* GL_MATRIX5_NV */ + 695, /* GL_MATRIX6_NV */ + 697, /* GL_MATRIX7_NV */ + 263, /* GL_CURRENT_MATRIX_STACK_DEPTH_ARB */ + 260, /* GL_CURRENT_MATRIX_ARB */ + 1587, /* GL_VERTEX_PROGRAM_POINT_SIZE_ARB */ + 1589, /* GL_VERTEX_PROGRAM_TWO_SIDE_ARB */ + 1083, /* GL_PROGRAM_PARAMETER_NV */ + 1579, /* GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB */ + 1087, /* GL_PROGRAM_TARGET_NV */ + 1084, /* GL_PROGRAM_RESIDENT_NV */ + 1502, /* GL_TRACK_MATRIX_NV */ + 1503, /* GL_TRACK_MATRIX_TRANSFORM_NV */ + 1585, /* GL_VERTEX_PROGRAM_BINDING_NV */ + 1065, /* GL_PROGRAM_ERROR_POSITION_ARB */ + 291, /* GL_DEPTH_CLAMP_NV */ + 1559, /* GL_VERTEX_ATTRIB_ARRAY0_NV */ + 1566, /* GL_VERTEX_ATTRIB_ARRAY1_NV */ + 1567, /* GL_VERTEX_ATTRIB_ARRAY2_NV */ + 1568, /* GL_VERTEX_ATTRIB_ARRAY3_NV */ + 1569, /* GL_VERTEX_ATTRIB_ARRAY4_NV */ + 1570, /* GL_VERTEX_ATTRIB_ARRAY5_NV */ + 1571, /* GL_VERTEX_ATTRIB_ARRAY6_NV */ + 1572, /* GL_VERTEX_ATTRIB_ARRAY7_NV */ + 1573, /* GL_VERTEX_ATTRIB_ARRAY8_NV */ + 1574, /* GL_VERTEX_ATTRIB_ARRAY9_NV */ + 1560, /* GL_VERTEX_ATTRIB_ARRAY10_NV */ + 1561, /* GL_VERTEX_ATTRIB_ARRAY11_NV */ + 1562, /* GL_VERTEX_ATTRIB_ARRAY12_NV */ + 1563, /* GL_VERTEX_ATTRIB_ARRAY13_NV */ + 1564, /* GL_VERTEX_ATTRIB_ARRAY14_NV */ + 1565, /* GL_VERTEX_ATTRIB_ARRAY15_NV */ + 615, /* GL_MAP1_VERTEX_ATTRIB0_4_NV */ + 622, /* GL_MAP1_VERTEX_ATTRIB1_4_NV */ + 623, /* GL_MAP1_VERTEX_ATTRIB2_4_NV */ + 624, /* GL_MAP1_VERTEX_ATTRIB3_4_NV */ + 625, /* GL_MAP1_VERTEX_ATTRIB4_4_NV */ + 626, /* GL_MAP1_VERTEX_ATTRIB5_4_NV */ + 627, /* GL_MAP1_VERTEX_ATTRIB6_4_NV */ + 628, /* GL_MAP1_VERTEX_ATTRIB7_4_NV */ + 629, /* GL_MAP1_VERTEX_ATTRIB8_4_NV */ + 630, /* GL_MAP1_VERTEX_ATTRIB9_4_NV */ + 616, /* GL_MAP1_VERTEX_ATTRIB10_4_NV */ + 617, /* GL_MAP1_VERTEX_ATTRIB11_4_NV */ + 618, /* GL_MAP1_VERTEX_ATTRIB12_4_NV */ + 619, /* GL_MAP1_VERTEX_ATTRIB13_4_NV */ + 620, /* GL_MAP1_VERTEX_ATTRIB14_4_NV */ + 621, /* GL_MAP1_VERTEX_ATTRIB15_4_NV */ + 642, /* GL_MAP2_VERTEX_ATTRIB0_4_NV */ + 649, /* GL_MAP2_VERTEX_ATTRIB1_4_NV */ + 650, /* GL_MAP2_VERTEX_ATTRIB2_4_NV */ + 651, /* GL_MAP2_VERTEX_ATTRIB3_4_NV */ + 652, /* GL_MAP2_VERTEX_ATTRIB4_4_NV */ + 653, /* GL_MAP2_VERTEX_ATTRIB5_4_NV */ + 654, /* GL_MAP2_VERTEX_ATTRIB6_4_NV */ + 1064, /* GL_PROGRAM_BINDING_ARB */ + 656, /* GL_MAP2_VERTEX_ATTRIB8_4_NV */ + 657, /* GL_MAP2_VERTEX_ATTRIB9_4_NV */ + 643, /* GL_MAP2_VERTEX_ATTRIB10_4_NV */ + 644, /* GL_MAP2_VERTEX_ATTRIB11_4_NV */ + 645, /* GL_MAP2_VERTEX_ATTRIB12_4_NV */ + 646, /* GL_MAP2_VERTEX_ATTRIB13_4_NV */ + 647, /* GL_MAP2_VERTEX_ATTRIB14_4_NV */ + 648, /* GL_MAP2_VERTEX_ATTRIB15_4_NV */ + 1426, /* GL_TEXTURE_COMPRESSED_IMAGE_SIZE */ + 1423, /* GL_TEXTURE_COMPRESSED */ + 874, /* GL_NUM_COMPRESSED_TEXTURE_FORMATS */ + 218, /* GL_COMPRESSED_TEXTURE_FORMATS */ + 783, /* GL_MAX_VERTEX_UNITS_ARB */ + 18, /* GL_ACTIVE_VERTEX_UNITS_ARB */ + 1602, /* GL_WEIGHT_SUM_UNITY_ARB */ + 1583, /* GL_VERTEX_BLEND_ARB */ + 278, /* GL_CURRENT_WEIGHT_ARB */ + 1601, /* GL_WEIGHT_ARRAY_TYPE_ARB */ + 1600, /* GL_WEIGHT_ARRAY_STRIDE_ARB */ + 1599, /* GL_WEIGHT_ARRAY_SIZE_ARB */ + 1598, /* GL_WEIGHT_ARRAY_POINTER_ARB */ + 1595, /* GL_WEIGHT_ARRAY_ARB */ + 317, /* GL_DOT3_RGB */ + 318, /* GL_DOT3_RGBA */ + 216, /* GL_COMPRESSED_RGB_FXT1_3DFX */ + 211, /* GL_COMPRESSED_RGBA_FXT1_3DFX */ + 843, /* GL_MULTISAMPLE_3DFX */ + 1204, /* GL_SAMPLE_BUFFERS_3DFX */ + 1195, /* GL_SAMPLES_3DFX */ + 824, /* GL_MODELVIEW2_ARB */ + 827, /* GL_MODELVIEW3_ARB */ + 828, /* GL_MODELVIEW4_ARB */ + 829, /* GL_MODELVIEW5_ARB */ + 830, /* GL_MODELVIEW6_ARB */ + 831, /* GL_MODELVIEW7_ARB */ + 832, /* GL_MODELVIEW8_ARB */ + 833, /* GL_MODELVIEW9_ARB */ + 803, /* GL_MODELVIEW10_ARB */ + 804, /* GL_MODELVIEW11_ARB */ + 805, /* GL_MODELVIEW12_ARB */ + 806, /* GL_MODELVIEW13_ARB */ + 807, /* GL_MODELVIEW14_ARB */ + 808, /* GL_MODELVIEW15_ARB */ + 809, /* GL_MODELVIEW16_ARB */ + 810, /* GL_MODELVIEW17_ARB */ + 811, /* GL_MODELVIEW18_ARB */ + 812, /* GL_MODELVIEW19_ARB */ + 814, /* GL_MODELVIEW20_ARB */ + 815, /* GL_MODELVIEW21_ARB */ + 816, /* GL_MODELVIEW22_ARB */ + 817, /* GL_MODELVIEW23_ARB */ + 818, /* GL_MODELVIEW24_ARB */ + 819, /* GL_MODELVIEW25_ARB */ + 820, /* GL_MODELVIEW26_ARB */ + 821, /* GL_MODELVIEW27_ARB */ + 822, /* GL_MODELVIEW28_ARB */ + 823, /* GL_MODELVIEW29_ARB */ + 825, /* GL_MODELVIEW30_ARB */ + 826, /* GL_MODELVIEW31_ARB */ + 322, /* GL_DOT3_RGB_EXT */ + 320, /* GL_DOT3_RGBA_EXT */ + 797, /* GL_MIRROR_CLAMP_EXT */ + 800, /* GL_MIRROR_CLAMP_TO_EDGE_EXT */ + 838, /* GL_MODULATE_ADD_ATI */ + 839, /* GL_MODULATE_SIGNED_ADD_ATI */ + 840, /* GL_MODULATE_SUBTRACT_ATI */ + 1608, /* GL_YCBCR_MESA */ + 929, /* GL_PACK_INVERT_MESA */ + 97, /* GL_BUFFER_SIZE */ + 99, /* GL_BUFFER_USAGE */ + 432, /* GL_FRAGMENT_PROGRAM_ARB */ + 1062, /* GL_PROGRAM_ALU_INSTRUCTIONS_ARB */ + 1090, /* GL_PROGRAM_TEX_INSTRUCTIONS_ARB */ + 1089, /* GL_PROGRAM_TEX_INDIRECTIONS_ARB */ + 1074, /* GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */ + 1080, /* GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */ + 1079, /* GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */ + 739, /* GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB */ + 762, /* GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB */ + 761, /* GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB */ + 752, /* GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB */ + 758, /* GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB */ + 757, /* GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB */ + 724, /* GL_MAX_DRAW_BUFFERS_ARB */ + 326, /* GL_DRAW_BUFFER0_ARB */ + 340, /* GL_DRAW_BUFFER1_ARB */ + 342, /* GL_DRAW_BUFFER2_ARB */ + 344, /* GL_DRAW_BUFFER3_ARB */ + 346, /* GL_DRAW_BUFFER4_ARB */ + 348, /* GL_DRAW_BUFFER5_ARB */ + 350, /* GL_DRAW_BUFFER6_ARB */ + 352, /* GL_DRAW_BUFFER7_ARB */ + 354, /* GL_DRAW_BUFFER8_ARB */ + 356, /* GL_DRAW_BUFFER9_ARB */ + 328, /* GL_DRAW_BUFFER10_ARB */ + 330, /* GL_DRAW_BUFFER11_ARB */ + 332, /* GL_DRAW_BUFFER12_ARB */ + 334, /* GL_DRAW_BUFFER13_ARB */ + 336, /* GL_DRAW_BUFFER14_ARB */ + 338, /* GL_DRAW_BUFFER15_ARB */ + 77, /* GL_BLEND_EQUATION_ALPHA_EXT */ + 706, /* GL_MATRIX_PALETTE_ARB */ + 733, /* GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB */ + 736, /* GL_MAX_PALETTE_MATRICES_ARB */ + 266, /* GL_CURRENT_PALETTE_MATRIX_ARB */ + 700, /* GL_MATRIX_INDEX_ARRAY_ARB */ + 261, /* GL_CURRENT_MATRIX_INDEX_ARB */ + 702, /* GL_MATRIX_INDEX_ARRAY_SIZE_ARB */ + 704, /* GL_MATRIX_INDEX_ARRAY_TYPE_ARB */ + 703, /* GL_MATRIX_INDEX_ARRAY_STRIDE_ARB */ + 701, /* GL_MATRIX_INDEX_ARRAY_POINTER_ARB */ + 1452, /* GL_TEXTURE_DEPTH_SIZE */ + 310, /* GL_DEPTH_TEXTURE_MODE */ + 1418, /* GL_TEXTURE_COMPARE_MODE */ + 1416, /* GL_TEXTURE_COMPARE_FUNC */ + 196, /* GL_COMPARE_R_TO_TEXTURE */ + 997, /* GL_POINT_SPRITE_ARB */ + 244, /* GL_COORD_REPLACE_ARB */ + 1000, /* GL_POINT_SPRITE_R_MODE_NV */ + 1115, /* GL_QUERY_COUNTER_BITS */ + 267, /* GL_CURRENT_QUERY */ + 1117, /* GL_QUERY_RESULT */ + 1119, /* GL_QUERY_RESULT_AVAILABLE */ + 780, /* GL_MAX_VERTEX_ATTRIBS_ARB */ + 1578, /* GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB */ + 308, /* GL_DEPTH_STENCIL_TO_RGBA_NV */ + 307, /* GL_DEPTH_STENCIL_TO_BGRA_NV */ + 769, /* GL_MAX_TEXTURE_COORDS_ARB */ + 770, /* GL_MAX_TEXTURE_IMAGE_UNITS_ARB */ + 1067, /* GL_PROGRAM_ERROR_STRING_ARB */ + 1069, /* GL_PROGRAM_FORMAT_ASCII_ARB */ + 1068, /* GL_PROGRAM_FORMAT_ARB */ + 1497, /* GL_TEXTURE_UNSIGNED_REMAP_MODE_NV */ + 289, /* GL_DEPTH_BOUNDS_TEST_EXT */ + 288, /* GL_DEPTH_BOUNDS_EXT */ + 48, /* GL_ARRAY_BUFFER */ + 373, /* GL_ELEMENT_ARRAY_BUFFER */ + 50, /* GL_ARRAY_BUFFER_BINDING */ + 375, /* GL_ELEMENT_ARRAY_BUFFER_BINDING */ + 1553, /* GL_VERTEX_ARRAY_BUFFER_BINDING */ + 864, /* GL_NORMAL_ARRAY_BUFFER_BINDING */ + 130, /* GL_COLOR_ARRAY_BUFFER_BINDING */ + 499, /* GL_INDEX_ARRAY_BUFFER_BINDING */ + 1431, /* GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING */ + 369, /* GL_EDGE_FLAG_ARRAY_BUFFER_BINDING */ + 1216, /* GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING */ + 410, /* GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING */ + 1596, /* GL_WEIGHT_ARRAY_BUFFER_BINDING */ + 1575, /* GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING */ + 1070, /* GL_PROGRAM_INSTRUCTIONS_ARB */ + 745, /* GL_MAX_PROGRAM_INSTRUCTIONS_ARB */ + 1076, /* GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB */ + 754, /* GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB */ + 1088, /* GL_PROGRAM_TEMPORARIES_ARB */ + 760, /* GL_MAX_PROGRAM_TEMPORARIES_ARB */ + 1078, /* GL_PROGRAM_NATIVE_TEMPORARIES_ARB */ + 756, /* GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB */ + 1082, /* GL_PROGRAM_PARAMETERS_ARB */ + 759, /* GL_MAX_PROGRAM_PARAMETERS_ARB */ + 1077, /* GL_PROGRAM_NATIVE_PARAMETERS_ARB */ + 755, /* GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB */ + 1063, /* GL_PROGRAM_ATTRIBS_ARB */ + 740, /* GL_MAX_PROGRAM_ATTRIBS_ARB */ + 1075, /* GL_PROGRAM_NATIVE_ATTRIBS_ARB */ + 753, /* GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB */ + 1061, /* GL_PROGRAM_ADDRESS_REGISTERS_ARB */ + 738, /* GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB */ + 1073, /* GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */ + 751, /* GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB */ + 746, /* GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB */ + 742, /* GL_MAX_PROGRAM_ENV_PARAMETERS_ARB */ + 1091, /* GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB */ + 1507, /* GL_TRANSPOSE_CURRENT_MATRIX_ARB */ + 1125, /* GL_READ_ONLY */ + 1604, /* GL_WRITE_ONLY */ + 1127, /* GL_READ_WRITE */ + 91, /* GL_BUFFER_ACCESS */ + 93, /* GL_BUFFER_MAPPED */ + 95, /* GL_BUFFER_MAP_POINTER */ + 660, /* GL_MATRIX0_ARB */ + 672, /* GL_MATRIX1_ARB */ + 684, /* GL_MATRIX2_ARB */ + 688, /* GL_MATRIX3_ARB */ + 690, /* GL_MATRIX4_ARB */ + 692, /* GL_MATRIX5_ARB */ + 694, /* GL_MATRIX6_ARB */ + 696, /* GL_MATRIX7_ARB */ + 698, /* GL_MATRIX8_ARB */ + 699, /* GL_MATRIX9_ARB */ + 662, /* GL_MATRIX10_ARB */ + 663, /* GL_MATRIX11_ARB */ + 664, /* GL_MATRIX12_ARB */ + 665, /* GL_MATRIX13_ARB */ + 666, /* GL_MATRIX14_ARB */ + 667, /* GL_MATRIX15_ARB */ + 668, /* GL_MATRIX16_ARB */ + 669, /* GL_MATRIX17_ARB */ + 670, /* GL_MATRIX18_ARB */ + 671, /* GL_MATRIX19_ARB */ + 674, /* GL_MATRIX20_ARB */ + 675, /* GL_MATRIX21_ARB */ + 676, /* GL_MATRIX22_ARB */ + 677, /* GL_MATRIX23_ARB */ + 678, /* GL_MATRIX24_ARB */ + 679, /* GL_MATRIX25_ARB */ + 680, /* GL_MATRIX26_ARB */ + 681, /* GL_MATRIX27_ARB */ + 682, /* GL_MATRIX28_ARB */ + 683, /* GL_MATRIX29_ARB */ + 686, /* GL_MATRIX30_ARB */ + 687, /* GL_MATRIX31_ARB */ + 1308, /* GL_STREAM_DRAW */ + 1310, /* GL_STREAM_READ */ + 1306, /* GL_STREAM_COPY */ + 1281, /* GL_STATIC_DRAW */ + 1283, /* GL_STATIC_READ */ + 1279, /* GL_STATIC_COPY */ + 363, /* GL_DYNAMIC_DRAW */ + 365, /* GL_DYNAMIC_READ */ + 361, /* GL_DYNAMIC_COPY */ + 970, /* GL_PIXEL_PACK_BUFFER_EXT */ + 972, /* GL_PIXEL_UNPACK_BUFFER_EXT */ + 969, /* GL_PIXEL_PACK_BUFFER_BINDING_EXT */ + 971, /* GL_PIXEL_UNPACK_BUFFER_BINDING_EXT */ + 743, /* GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */ + 741, /* GL_MAX_PROGRAM_CALL_DEPTH_NV */ + 744, /* GL_MAX_PROGRAM_IF_DEPTH_NV */ + 748, /* GL_MAX_PROGRAM_LOOP_DEPTH_NV */ + 747, /* GL_MAX_PROGRAM_LOOP_COUNT_NV */ + 1302, /* GL_STENCIL_TEST_TWO_SIDE_EXT */ + 15, /* GL_ACTIVE_STENCIL_FACE_EXT */ + 798, /* GL_MIRROR_CLAMP_TO_BORDER_EXT */ + 1197, /* GL_SAMPLES_PASSED */ + 433, /* GL_FRAGMENT_SHADER_ARB */ + 1591, /* GL_VERTEX_SHADER_ARB */ + 1081, /* GL_PROGRAM_OBJECT_ARB */ + 1229, /* GL_SHADER_OBJECT_ARB */ + 730, /* GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB */ + 782, /* GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB */ + 779, /* GL_MAX_VARYING_FLOATS_ARB */ + 781, /* GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */ + 717, /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB */ + 889, /* GL_OBJECT_TYPE_ARB */ + 888, /* GL_OBJECT_SUBTYPE_ARB */ + 401, /* GL_FLOAT_VEC2_ARB */ + 402, /* GL_FLOAT_VEC3_ARB */ + 403, /* GL_FLOAT_VEC4_ARB */ + 525, /* GL_INT_VEC2_ARB */ + 526, /* GL_INT_VEC3_ARB */ + 527, /* GL_INT_VEC4_ARB */ + 87, /* GL_BOOL_ARB */ + 88, /* GL_BOOL_VEC2_ARB */ + 89, /* GL_BOOL_VEC3_ARB */ + 90, /* GL_BOOL_VEC4_ARB */ + 398, /* GL_FLOAT_MAT2_ARB */ + 399, /* GL_FLOAT_MAT3_ARB */ + 400, /* GL_FLOAT_MAT4_ARB */ + 882, /* GL_OBJECT_DELETE_STATUS_ARB */ + 881, /* GL_OBJECT_COMPILE_STATUS_ARB */ + 885, /* GL_OBJECT_LINK_STATUS_ARB */ + 890, /* GL_OBJECT_VALIDATE_STATUS_ARB */ + 883, /* GL_OBJECT_INFO_LOG_LENGTH_ARB */ + 880, /* GL_OBJECT_ATTACHED_OBJECTS_ARB */ + 878, /* GL_OBJECT_ACTIVE_UNIFORMS_ARB */ + 879, /* GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB */ + 887, /* GL_OBJECT_SHADER_SOURCE_LENGTH_ARB */ + 876, /* GL_OBJECT_ACTIVE_ATTRIBUTES_ARB */ + 877, /* GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB */ + 938, /* GL_PALETTE4_RGB8_OES */ + 940, /* GL_PALETTE4_RGBA8_OES */ + 936, /* GL_PALETTE4_R5_G6_B5_OES */ + 939, /* GL_PALETTE4_RGBA4_OES */ + 937, /* GL_PALETTE4_RGB5_A1_OES */ + 943, /* GL_PALETTE8_RGB8_OES */ + 945, /* GL_PALETTE8_RGBA8_OES */ + 941, /* GL_PALETTE8_R5_G6_B5_OES */ + 944, /* GL_PALETTE8_RGBA4_OES */ + 942, /* GL_PALETTE8_RGB5_A1_OES */ + 494, /* GL_IMPLEMENTATION_COLOR_READ_TYPE_OES */ + 493, /* GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES */ + 998, /* GL_POINT_SPRITE_COORD_ORIGIN */ + 439, /* GL_FRAMEBUFFER_BINDING_EXT */ + 1139, /* GL_RENDERBUFFER_BINDING_EXT */ + 435, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT */ + 434, /* GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT */ + 438, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT */ + 437, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT */ + 436, /* GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT */ + 440, /* GL_FRAMEBUFFER_COMPLETE_EXT */ + 442, /* GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT */ + 447, /* GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT */ + 445, /* GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT */ + 443, /* GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT */ + 446, /* GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT */ + 444, /* GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT */ + 448, /* GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT */ + 450, /* GL_FRAMEBUFFER_UNSUPPORTED_EXT */ + 449, /* GL_FRAMEBUFFER_STATUS_ERROR_EXT */ + 714, /* GL_MAX_COLOR_ATTACHMENTS_EXT */ + 136, /* GL_COLOR_ATTACHMENT0_EXT */ + 143, /* GL_COLOR_ATTACHMENT1_EXT */ + 144, /* GL_COLOR_ATTACHMENT2_EXT */ + 145, /* GL_COLOR_ATTACHMENT3_EXT */ + 146, /* GL_COLOR_ATTACHMENT4_EXT */ + 147, /* GL_COLOR_ATTACHMENT5_EXT */ + 148, /* GL_COLOR_ATTACHMENT6_EXT */ + 149, /* GL_COLOR_ATTACHMENT7_EXT */ + 150, /* GL_COLOR_ATTACHMENT8_EXT */ + 151, /* GL_COLOR_ATTACHMENT9_EXT */ + 137, /* GL_COLOR_ATTACHMENT10_EXT */ + 138, /* GL_COLOR_ATTACHMENT11_EXT */ + 139, /* GL_COLOR_ATTACHMENT12_EXT */ + 140, /* GL_COLOR_ATTACHMENT13_EXT */ + 141, /* GL_COLOR_ATTACHMENT14_EXT */ + 142, /* GL_COLOR_ATTACHMENT15_EXT */ + 285, /* GL_DEPTH_ATTACHMENT_EXT */ + 1286, /* GL_STENCIL_ATTACHMENT_EXT */ + 441, /* GL_FRAMEBUFFER_EXT */ + 1140, /* GL_RENDERBUFFER_EXT */ + 1143, /* GL_RENDERBUFFER_WIDTH_EXT */ + 1141, /* GL_RENDERBUFFER_HEIGHT_EXT */ + 1142, /* GL_RENDERBUFFER_INTERNAL_FORMAT_EXT */ + 1297, /* GL_STENCIL_INDEX_EXT */ + 1294, /* GL_STENCIL_INDEX1_EXT */ + 1295, /* GL_STENCIL_INDEX4_EXT */ + 1296, /* GL_STENCIL_INDEX8_EXT */ + 1293, /* GL_STENCIL_INDEX16_EXT */ + 381, /* GL_EVAL_BIT */ + 1123, /* GL_RASTER_POSITION_UNCLIPPED_IBM */ + 576, /* GL_LIST_BIT */ + 1402, /* GL_TEXTURE_BIT */ + 1212, /* GL_SCISSOR_BIT */ + 25, /* GL_ALL_ATTRIB_BITS */ + 845, /* GL_MULTISAMPLE_BIT */ +}; + +#define Elements(x) sizeof(x)/sizeof(*x) + +typedef int (*cfunc)(const void *, const void *); + +/** + * Compare a key name to an element in the \c all_enums array. + * + * \c bsearch always passes the key as the first parameter and the pointer + * to the array element as the second parameter. We can elimiate some + * extra work by taking advantage of that fact. + * + * \param a Pointer to the desired enum name. + * \param b Pointer to an element of the \c all_enums array. + */ +static int compar_name( const char *a, const enum_elt *b ) +{ + return _mesa_strcmp( a, & enum_string_table[ b->offset ] ); +} + +/** + * Compare a key enum value to an element in the \c all_enums array. + * + * \c bsearch always passes the key as the first parameter and the pointer + * to the array element as the second parameter. We can elimiate some + * extra work by taking advantage of that fact. + * + * \param a Pointer to the desired enum name. + * \param b Pointer to an index into the \c all_enums array. + */ +static int compar_nr( const int *a, const unsigned *b ) +{ + return a[0] - all_enums[*b].n; +} + + +static char token_tmp[20]; + +const char *_mesa_lookup_enum_by_nr( int nr ) +{ + unsigned * i; + + i = (unsigned *)bsearch( & nr, reduced_enums, Elements(reduced_enums), + sizeof(reduced_enums[0]), (cfunc) compar_nr ); + + if ( i != NULL ) { + return & enum_string_table[ all_enums[ *i ].offset ]; + } + else { + /* this is not re-entrant safe, no big deal here */ + _mesa_sprintf(token_tmp, "0x%x", nr); + return token_tmp; + } +} + +int _mesa_lookup_enum_by_name( const char *symbol ) +{ + enum_elt * f = NULL; + + if ( symbol != NULL ) { + f = (enum_elt *)bsearch( symbol, all_enums, Elements(all_enums), + sizeof( enum_elt ), (cfunc) compar_name ); + } + + return (f != NULL) ? f->n : -1; +} + + diff --git a/src/mesa/main/enums.h b/src/mesa/main/enums.h new file mode 100644 index 00000000000..7e8d4ee94fc --- /dev/null +++ b/src/mesa/main/enums.h @@ -0,0 +1,55 @@ +/** + * \file enums.h + * Enumeration name/number lookup functions. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* $XFree86: xc/extras/Mesa/src/mesa/main/enums.h,v 1.2 2004/06/23 19:40:14 tsi Exp $ */ + +#ifndef _ENUMS_H_ +#define _ENUMS_H_ + + +#if defined(_HAVE_FULL_GL) && _HAVE_FULL_GL + +extern const char *_mesa_lookup_enum_by_nr( int nr ); +extern int _mesa_lookup_enum_by_name( const char *symbol ); + +#else + +/** No-op */ +#define _mesa_lookup_enum_by_name( s ) 0 + +/** No-op */ +#define _mesa_lookup_enum_by_nr( n ) "unknown" + +#endif + +#endif diff --git a/src/mesa/main/eval.c b/src/mesa/main/eval.c new file mode 100644 index 00000000000..3f89f9c1eae --- /dev/null +++ b/src/mesa/main/eval.c @@ -0,0 +1,962 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * eval.c was written by + * Bernd Barsuhn ([email protected]) and + * Volker Weiss ([email protected]). + * + * My original implementation of evaluators was simplistic and didn't + * compute surface normal vectors properly. Bernd and Volker applied + * used more sophisticated methods to get better results. + * + * Thanks guys! + */ + + +#include "glheader.h" +#include "imports.h" +#include "colormac.h" +#include "context.h" +#include "eval.h" +#include "macros.h" +#include "mtypes.h" + + +/* + * Return the number of components per control point for any type of + * evaluator. Return 0 if bad target. + * See table 5.1 in the OpenGL 1.2 spec. + */ +GLuint _mesa_evaluator_components( GLenum target ) +{ + switch (target) { + case GL_MAP1_VERTEX_3: return 3; + case GL_MAP1_VERTEX_4: return 4; + case GL_MAP1_INDEX: return 1; + case GL_MAP1_COLOR_4: return 4; + case GL_MAP1_NORMAL: return 3; + case GL_MAP1_TEXTURE_COORD_1: return 1; + case GL_MAP1_TEXTURE_COORD_2: return 2; + case GL_MAP1_TEXTURE_COORD_3: return 3; + case GL_MAP1_TEXTURE_COORD_4: return 4; + case GL_MAP2_VERTEX_3: return 3; + case GL_MAP2_VERTEX_4: return 4; + case GL_MAP2_INDEX: return 1; + case GL_MAP2_COLOR_4: return 4; + case GL_MAP2_NORMAL: return 3; + case GL_MAP2_TEXTURE_COORD_1: return 1; + case GL_MAP2_TEXTURE_COORD_2: return 2; + case GL_MAP2_TEXTURE_COORD_3: return 3; + case GL_MAP2_TEXTURE_COORD_4: return 4; + default: break; + } + + /* XXX need to check for the vertex program extension + if (!ctx->Extensions.NV_vertex_program) + return 0; + */ + + if (target >= GL_MAP1_VERTEX_ATTRIB0_4_NV && + target <= GL_MAP1_VERTEX_ATTRIB15_4_NV) + return 4; + + if (target >= GL_MAP2_VERTEX_ATTRIB0_4_NV && + target <= GL_MAP2_VERTEX_ATTRIB15_4_NV) + return 4; + + return 0; +} + + +/* + * Return pointer to the gl_1d_map struct for the named target. + */ +static struct gl_1d_map * +get_1d_map( GLcontext *ctx, GLenum target ) +{ + switch (target) { + case GL_MAP1_VERTEX_3: + return &ctx->EvalMap.Map1Vertex3; + case GL_MAP1_VERTEX_4: + return &ctx->EvalMap.Map1Vertex4; + case GL_MAP1_INDEX: + return &ctx->EvalMap.Map1Index; + case GL_MAP1_COLOR_4: + return &ctx->EvalMap.Map1Color4; + case GL_MAP1_NORMAL: + return &ctx->EvalMap.Map1Normal; + case GL_MAP1_TEXTURE_COORD_1: + return &ctx->EvalMap.Map1Texture1; + case GL_MAP1_TEXTURE_COORD_2: + return &ctx->EvalMap.Map1Texture2; + case GL_MAP1_TEXTURE_COORD_3: + return &ctx->EvalMap.Map1Texture3; + case GL_MAP1_TEXTURE_COORD_4: + return &ctx->EvalMap.Map1Texture4; + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + if (!ctx->Extensions.NV_vertex_program) + return NULL; + return &ctx->EvalMap.Map1Attrib[target - GL_MAP1_VERTEX_ATTRIB0_4_NV]; + default: + return NULL; + } +} + + +/* + * Return pointer to the gl_2d_map struct for the named target. + */ +static struct gl_2d_map * +get_2d_map( GLcontext *ctx, GLenum target ) +{ + switch (target) { + case GL_MAP2_VERTEX_3: + return &ctx->EvalMap.Map2Vertex3; + case GL_MAP2_VERTEX_4: + return &ctx->EvalMap.Map2Vertex4; + case GL_MAP2_INDEX: + return &ctx->EvalMap.Map2Index; + case GL_MAP2_COLOR_4: + return &ctx->EvalMap.Map2Color4; + case GL_MAP2_NORMAL: + return &ctx->EvalMap.Map2Normal; + case GL_MAP2_TEXTURE_COORD_1: + return &ctx->EvalMap.Map2Texture1; + case GL_MAP2_TEXTURE_COORD_2: + return &ctx->EvalMap.Map2Texture2; + case GL_MAP2_TEXTURE_COORD_3: + return &ctx->EvalMap.Map2Texture3; + case GL_MAP2_TEXTURE_COORD_4: + return &ctx->EvalMap.Map2Texture4; + case GL_MAP2_VERTEX_ATTRIB0_4_NV: + case GL_MAP2_VERTEX_ATTRIB1_4_NV: + case GL_MAP2_VERTEX_ATTRIB2_4_NV: + case GL_MAP2_VERTEX_ATTRIB3_4_NV: + case GL_MAP2_VERTEX_ATTRIB4_4_NV: + case GL_MAP2_VERTEX_ATTRIB5_4_NV: + case GL_MAP2_VERTEX_ATTRIB6_4_NV: + case GL_MAP2_VERTEX_ATTRIB7_4_NV: + case GL_MAP2_VERTEX_ATTRIB8_4_NV: + case GL_MAP2_VERTEX_ATTRIB9_4_NV: + case GL_MAP2_VERTEX_ATTRIB10_4_NV: + case GL_MAP2_VERTEX_ATTRIB11_4_NV: + case GL_MAP2_VERTEX_ATTRIB12_4_NV: + case GL_MAP2_VERTEX_ATTRIB13_4_NV: + case GL_MAP2_VERTEX_ATTRIB14_4_NV: + case GL_MAP2_VERTEX_ATTRIB15_4_NV: + if (!ctx->Extensions.NV_vertex_program) + return NULL; + return &ctx->EvalMap.Map2Attrib[target - GL_MAP2_VERTEX_ATTRIB0_4_NV]; + default: + return NULL; + } +} + + +/**********************************************************************/ +/*** Copy and deallocate control points ***/ +/**********************************************************************/ + + +/* + * Copy 1-parametric evaluator control points from user-specified + * memory space to a buffer of contiguous control points. + * \param see glMap1f for details + * \return pointer to buffer of contiguous control points or NULL if out + * of memory. + */ +GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder, + const GLfloat *points ) +{ + GLfloat *buffer, *p; + GLint i, k, size = _mesa_evaluator_components(target); + + if (!points || !size) + return NULL; + + buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat)); + + if (buffer) + for (i = 0, p = buffer; i < uorder; i++, points += ustride) + for (k = 0; k < size; k++) + *p++ = points[k]; + + return buffer; +} + + + +/* + * Same as above but convert doubles to floats. + */ +GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder, + const GLdouble *points ) +{ + GLfloat *buffer, *p; + GLint i, k, size = _mesa_evaluator_components(target); + + if (!points || !size) + return NULL; + + buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat)); + + if (buffer) + for (i = 0, p = buffer; i < uorder; i++, points += ustride) + for (k = 0; k < size; k++) + *p++ = (GLfloat) points[k]; + + return buffer; +} + + + +/* + * Copy 2-parametric evaluator control points from user-specified + * memory space to a buffer of contiguous control points. + * Additional memory is allocated to be used by the horner and + * de Casteljau evaluation schemes. + * + * \param see glMap2f for details + * \return pointer to buffer of contiguous control points or NULL if out + * of memory. + */ +GLfloat *_mesa_copy_map_points2f( GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLfloat *points ) +{ + GLfloat *buffer, *p; + GLint i, j, k, size, dsize, hsize; + GLint uinc; + + size = _mesa_evaluator_components(target); + + if (!points || size==0) { + return NULL; + } + + /* max(uorder, vorder) additional points are used in */ + /* horner evaluation and uorder*vorder additional */ + /* values are needed for de Casteljau */ + dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder; + hsize = (uorder > vorder ? uorder : vorder)*size; + + if(hsize>dsize) + buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat)); + else + buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat)); + + /* compute the increment value for the u-loop */ + uinc = ustride - vorder*vstride; + + if (buffer) + for (i=0, p=buffer; i<uorder; i++, points += uinc) + for (j=0; j<vorder; j++, points += vstride) + for (k=0; k<size; k++) + *p++ = points[k]; + + return buffer; +} + + + +/* + * Same as above but convert doubles to floats. + */ +GLfloat *_mesa_copy_map_points2d(GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLdouble *points ) +{ + GLfloat *buffer, *p; + GLint i, j, k, size, hsize, dsize; + GLint uinc; + + size = _mesa_evaluator_components(target); + + if (!points || size==0) { + return NULL; + } + + /* max(uorder, vorder) additional points are used in */ + /* horner evaluation and uorder*vorder additional */ + /* values are needed for de Casteljau */ + dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder; + hsize = (uorder > vorder ? uorder : vorder)*size; + + if(hsize>dsize) + buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat)); + else + buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat)); + + /* compute the increment value for the u-loop */ + uinc = ustride - vorder*vstride; + + if (buffer) + for (i=0, p=buffer; i<uorder; i++, points += uinc) + for (j=0; j<vorder; j++, points += vstride) + for (k=0; k<size; k++) + *p++ = (GLfloat) points[k]; + + return buffer; +} + + + + +/**********************************************************************/ +/*** API entry points ***/ +/**********************************************************************/ + + +/* + * This does the work of glMap1[fd]. + */ +static void +map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, + GLint uorder, const GLvoid *points, GLenum type ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint k; + GLfloat *pnts; + struct gl_1d_map *map = NULL; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + ASSERT(type == GL_FLOAT || type == GL_DOUBLE); + + if (u1 == u2) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" ); + return; + } + if (uorder < 1 || uorder > MAX_EVAL_ORDER) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" ); + return; + } + if (!points) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" ); + return; + } + + k = _mesa_evaluator_components( target ); + if (k == 0) { + _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" ); + } + + if (ustride < k) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" ); + return; + } + + if (ctx->Texture.CurrentUnit != 0) { + /* See OpenGL 1.2.1 spec, section F.2.13 */ + _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" ); + return; + } + + map = get_1d_map(ctx, target); + if (!map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" ); + return; + } + + /* make copy of the control points */ + if (type == GL_FLOAT) + pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points); + else + pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points); + + + FLUSH_VERTICES(ctx, _NEW_EVAL); + map->Order = uorder; + map->u1 = u1; + map->u2 = u2; + map->du = 1.0F / (u2 - u1); + if (map->Points) + FREE( map->Points ); + map->Points = pnts; +} + + + +void GLAPIENTRY +_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride, + GLint order, const GLfloat *points ) +{ + map1(target, u1, u2, stride, order, points, GL_FLOAT); +} + + +void GLAPIENTRY +_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride, + GLint order, const GLdouble *points ) +{ + map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE); +} + + +static void +map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLvoid *points, GLenum type ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint k; + GLfloat *pnts; + struct gl_2d_map *map = NULL; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + ASSERT(type == GL_FLOAT || type == GL_DOUBLE); + + if (u1==u2) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" ); + return; + } + + if (v1==v2) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" ); + return; + } + + if (uorder<1 || uorder>MAX_EVAL_ORDER) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" ); + return; + } + + if (vorder<1 || vorder>MAX_EVAL_ORDER) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" ); + return; + } + + k = _mesa_evaluator_components( target ); + if (k==0) { + _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" ); + } + + if (ustride < k) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" ); + return; + } + if (vstride < k) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" ); + return; + } + + if (ctx->Texture.CurrentUnit != 0) { + /* See OpenGL 1.2.1 spec, section F.2.13 */ + _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" ); + return; + } + + map = get_2d_map(ctx, target); + if (!map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" ); + return; + } + + /* make copy of the control points */ + if (type == GL_FLOAT) + pnts = _mesa_copy_map_points2f(target, ustride, uorder, + vstride, vorder, (GLfloat*) points); + else + pnts = _mesa_copy_map_points2d(target, ustride, uorder, + vstride, vorder, (GLdouble*) points); + + + FLUSH_VERTICES(ctx, _NEW_EVAL); + map->Uorder = uorder; + map->u1 = u1; + map->u2 = u2; + map->du = 1.0F / (u2 - u1); + map->Vorder = vorder; + map->v1 = v1; + map->v2 = v2; + map->dv = 1.0F / (v2 - v1); + if (map->Points) + FREE( map->Points ); + map->Points = pnts; +} + + +void GLAPIENTRY +_mesa_Map2f( GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points) +{ + map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, + points, GL_FLOAT); +} + + +void GLAPIENTRY +_mesa_Map2d( GLenum target, + GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, + GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, + const GLdouble *points ) +{ + map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder, + (GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE); +} + + + +void GLAPIENTRY +_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_1d_map *map1d; + struct gl_2d_map *map2d; + GLint i, n; + GLfloat *data; + GLuint comps; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + comps = _mesa_evaluator_components(target); + if (!comps) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" ); + return; + } + + map1d = get_1d_map(ctx, target); + map2d = get_2d_map(ctx, target); + ASSERT(map1d || map2d); + + switch (query) { + case GL_COEFF: + if (map1d) { + data = map1d->Points; + n = map1d->Order * comps; + } + else { + data = map2d->Points; + n = map2d->Uorder * map2d->Vorder * comps; + } + if (data) { + for (i=0;i<n;i++) { + v[i] = data[i]; + } + } + break; + case GL_ORDER: + if (map1d) { + v[0] = (GLdouble) map1d->Order; + } + else { + v[0] = (GLdouble) map2d->Uorder; + v[1] = (GLdouble) map2d->Vorder; + } + break; + case GL_DOMAIN: + if (map1d) { + v[0] = (GLdouble) map1d->u1; + v[1] = (GLdouble) map1d->u2; + } + else { + v[0] = (GLdouble) map2d->u1; + v[1] = (GLdouble) map2d->u2; + v[2] = (GLdouble) map2d->v1; + v[3] = (GLdouble) map2d->v2; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" ); + } +} + + +void GLAPIENTRY +_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_1d_map *map1d; + struct gl_2d_map *map2d; + GLint i, n; + GLfloat *data; + GLuint comps; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + comps = _mesa_evaluator_components(target); + if (!comps) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" ); + return; + } + + map1d = get_1d_map(ctx, target); + map2d = get_2d_map(ctx, target); + ASSERT(map1d || map2d); + + switch (query) { + case GL_COEFF: + if (map1d) { + data = map1d->Points; + n = map1d->Order * comps; + } + else { + data = map2d->Points; + n = map2d->Uorder * map2d->Vorder * comps; + } + if (data) { + for (i=0;i<n;i++) { + v[i] = data[i]; + } + } + break; + case GL_ORDER: + if (map1d) { + v[0] = (GLfloat) map1d->Order; + } + else { + v[0] = (GLfloat) map2d->Uorder; + v[1] = (GLfloat) map2d->Vorder; + } + break; + case GL_DOMAIN: + if (map1d) { + v[0] = map1d->u1; + v[1] = map1d->u2; + } + else { + v[0] = map2d->u1; + v[1] = map2d->u2; + v[2] = map2d->v1; + v[3] = map2d->v2; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" ); + } +} + + +void GLAPIENTRY +_mesa_GetMapiv( GLenum target, GLenum query, GLint *v ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_1d_map *map1d; + struct gl_2d_map *map2d; + GLuint i, n; + GLfloat *data; + GLuint comps; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + comps = _mesa_evaluator_components(target); + if (!comps) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" ); + return; + } + + map1d = get_1d_map(ctx, target); + map2d = get_2d_map(ctx, target); + ASSERT(map1d || map2d); + + switch (query) { + case GL_COEFF: + if (map1d) { + data = map1d->Points; + n = map1d->Order * comps; + } + else { + data = map2d->Points; + n = map2d->Uorder * map2d->Vorder * comps; + } + if (data) { + for (i=0;i<n;i++) { + v[i] = IROUND(data[i]); + } + } + break; + case GL_ORDER: + if (map1d) { + v[0] = map1d->Order; + } + else { + v[0] = map2d->Uorder; + v[1] = map2d->Vorder; + } + break; + case GL_DOMAIN: + if (map1d) { + v[0] = IROUND(map1d->u1); + v[1] = IROUND(map1d->u2); + } + else { + v[0] = IROUND(map2d->u1); + v[1] = IROUND(map2d->u2); + v[2] = IROUND(map2d->v1); + v[3] = IROUND(map2d->v2); + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" ); + } +} + + + +void GLAPIENTRY +_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (un<1) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" ); + return; + } + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.MapGrid1un = un; + ctx->Eval.MapGrid1u1 = u1; + ctx->Eval.MapGrid1u2 = u2; + ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un; +} + + +void GLAPIENTRY +_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 ) +{ + _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 ); +} + + +void GLAPIENTRY +_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (un<1) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" ); + return; + } + if (vn<1) { + _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" ); + return; + } + + FLUSH_VERTICES(ctx, _NEW_EVAL); + ctx->Eval.MapGrid2un = un; + ctx->Eval.MapGrid2u1 = u1; + ctx->Eval.MapGrid2u2 = u2; + ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un; + ctx->Eval.MapGrid2vn = vn; + ctx->Eval.MapGrid2v1 = v1; + ctx->Eval.MapGrid2v2 = v2; + ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn; +} + + +void GLAPIENTRY +_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2, + GLint vn, GLdouble v1, GLdouble v2 ) +{ + _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2, + vn, (GLfloat) v1, (GLfloat) v2 ); +} + + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +/** + * Initialize a 1-D evaluator map. + */ +static void +init_1d_map( struct gl_1d_map *map, int n, const float *initial ) +{ + map->Order = 1; + map->u1 = 0.0; + map->u2 = 1.0; + map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat)); + if (map->Points) { + GLint i; + for (i=0;i<n;i++) + map->Points[i] = initial[i]; + } +} + + +/** + * Initialize a 2-D evaluator map + */ +static void +init_2d_map( struct gl_2d_map *map, int n, const float *initial ) +{ + map->Uorder = 1; + map->Vorder = 1; + map->u1 = 0.0; + map->u2 = 1.0; + map->v1 = 0.0; + map->v2 = 1.0; + map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat)); + if (map->Points) { + GLint i; + for (i=0;i<n;i++) + map->Points[i] = initial[i]; + } +} + + +void _mesa_init_eval( GLcontext *ctx ) +{ + int i; + + /* Evaluators group */ + ctx->Eval.Map1Color4 = GL_FALSE; + ctx->Eval.Map1Index = GL_FALSE; + ctx->Eval.Map1Normal = GL_FALSE; + ctx->Eval.Map1TextureCoord1 = GL_FALSE; + ctx->Eval.Map1TextureCoord2 = GL_FALSE; + ctx->Eval.Map1TextureCoord3 = GL_FALSE; + ctx->Eval.Map1TextureCoord4 = GL_FALSE; + ctx->Eval.Map1Vertex3 = GL_FALSE; + ctx->Eval.Map1Vertex4 = GL_FALSE; + MEMSET(ctx->Eval.Map1Attrib, 0, sizeof(ctx->Eval.Map1Attrib)); + ctx->Eval.Map2Color4 = GL_FALSE; + ctx->Eval.Map2Index = GL_FALSE; + ctx->Eval.Map2Normal = GL_FALSE; + ctx->Eval.Map2TextureCoord1 = GL_FALSE; + ctx->Eval.Map2TextureCoord2 = GL_FALSE; + ctx->Eval.Map2TextureCoord3 = GL_FALSE; + ctx->Eval.Map2TextureCoord4 = GL_FALSE; + ctx->Eval.Map2Vertex3 = GL_FALSE; + ctx->Eval.Map2Vertex4 = GL_FALSE; + MEMSET(ctx->Eval.Map2Attrib, 0, sizeof(ctx->Eval.Map2Attrib)); + ctx->Eval.AutoNormal = GL_FALSE; + ctx->Eval.MapGrid1un = 1; + ctx->Eval.MapGrid1u1 = 0.0; + ctx->Eval.MapGrid1u2 = 1.0; + ctx->Eval.MapGrid2un = 1; + ctx->Eval.MapGrid2vn = 1; + ctx->Eval.MapGrid2u1 = 0.0; + ctx->Eval.MapGrid2u2 = 1.0; + ctx->Eval.MapGrid2v1 = 0.0; + ctx->Eval.MapGrid2v2 = 1.0; + + /* Evaluator data */ + { + static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 }; + static GLfloat normal[3] = { 0.0, 0.0, 1.0 }; + static GLfloat index[1] = { 1.0 }; + static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 }; + static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 }; + static GLfloat attrib[4] = { 0.0, 0.0, 0.0, 1.0 }; + + init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex ); + init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex ); + init_1d_map( &ctx->EvalMap.Map1Index, 1, index ); + init_1d_map( &ctx->EvalMap.Map1Color4, 4, color ); + init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal ); + init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord ); + init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord ); + init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord ); + init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord ); + for (i = 0; i < 16; i++) + init_1d_map( ctx->EvalMap.Map1Attrib + i, 4, attrib ); + + init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex ); + init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex ); + init_2d_map( &ctx->EvalMap.Map2Index, 1, index ); + init_2d_map( &ctx->EvalMap.Map2Color4, 4, color ); + init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal ); + init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord ); + init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord ); + init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord ); + init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord ); + for (i = 0; i < 16; i++) + init_2d_map( ctx->EvalMap.Map2Attrib + i, 4, attrib ); + } +} + + +void _mesa_free_eval_data( GLcontext *ctx ) +{ + int i; + + /* Free evaluator data */ + if (ctx->EvalMap.Map1Vertex3.Points) + FREE( ctx->EvalMap.Map1Vertex3.Points ); + if (ctx->EvalMap.Map1Vertex4.Points) + FREE( ctx->EvalMap.Map1Vertex4.Points ); + if (ctx->EvalMap.Map1Index.Points) + FREE( ctx->EvalMap.Map1Index.Points ); + if (ctx->EvalMap.Map1Color4.Points) + FREE( ctx->EvalMap.Map1Color4.Points ); + if (ctx->EvalMap.Map1Normal.Points) + FREE( ctx->EvalMap.Map1Normal.Points ); + if (ctx->EvalMap.Map1Texture1.Points) + FREE( ctx->EvalMap.Map1Texture1.Points ); + if (ctx->EvalMap.Map1Texture2.Points) + FREE( ctx->EvalMap.Map1Texture2.Points ); + if (ctx->EvalMap.Map1Texture3.Points) + FREE( ctx->EvalMap.Map1Texture3.Points ); + if (ctx->EvalMap.Map1Texture4.Points) + FREE( ctx->EvalMap.Map1Texture4.Points ); + for (i = 0; i < 16; i++) + FREE((ctx->EvalMap.Map1Attrib[i].Points)); + + if (ctx->EvalMap.Map2Vertex3.Points) + FREE( ctx->EvalMap.Map2Vertex3.Points ); + if (ctx->EvalMap.Map2Vertex4.Points) + FREE( ctx->EvalMap.Map2Vertex4.Points ); + if (ctx->EvalMap.Map2Index.Points) + FREE( ctx->EvalMap.Map2Index.Points ); + if (ctx->EvalMap.Map2Color4.Points) + FREE( ctx->EvalMap.Map2Color4.Points ); + if (ctx->EvalMap.Map2Normal.Points) + FREE( ctx->EvalMap.Map2Normal.Points ); + if (ctx->EvalMap.Map2Texture1.Points) + FREE( ctx->EvalMap.Map2Texture1.Points ); + if (ctx->EvalMap.Map2Texture2.Points) + FREE( ctx->EvalMap.Map2Texture2.Points ); + if (ctx->EvalMap.Map2Texture3.Points) + FREE( ctx->EvalMap.Map2Texture3.Points ); + if (ctx->EvalMap.Map2Texture4.Points) + FREE( ctx->EvalMap.Map2Texture4.Points ); + for (i = 0; i < 16; i++) + FREE((ctx->EvalMap.Map2Attrib[i].Points)); +} diff --git a/src/mesa/main/eval.h b/src/mesa/main/eval.h new file mode 100644 index 00000000000..b3ff0a96f82 --- /dev/null +++ b/src/mesa/main/eval.h @@ -0,0 +1,128 @@ +/** + * \file eval.h + * Eval operations. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef EVAL_H +#define EVAL_H + + +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void _mesa_init_eval( GLcontext *ctx ); +extern void _mesa_free_eval_data( GLcontext *ctx ); + + +extern GLuint _mesa_evaluator_components( GLenum target ); + + +extern void gl_free_control_points( GLcontext *ctx, + GLenum target, GLfloat *data ); + + +extern GLfloat *_mesa_copy_map_points1f( GLenum target, + GLint ustride, GLint uorder, + const GLfloat *points ); + +extern GLfloat *_mesa_copy_map_points1d( GLenum target, + GLint ustride, GLint uorder, + const GLdouble *points ); + +extern GLfloat *_mesa_copy_map_points2f( GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLfloat *points ); + +extern GLfloat *_mesa_copy_map_points2d(GLenum target, + GLint ustride, GLint uorder, + GLint vstride, GLint vorder, + const GLdouble *points ); + + + +extern void GLAPIENTRY +_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride, + GLint order, const GLfloat *points ); + +extern void GLAPIENTRY +_mesa_Map2f( GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points ); + +extern void GLAPIENTRY +_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride, + GLint order, const GLdouble *points ); + +extern void GLAPIENTRY +_mesa_Map2d( GLenum target, + GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, + GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, + const GLdouble *points ); + +extern void GLAPIENTRY +_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 ); + +extern void GLAPIENTRY +_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 ); + +extern void GLAPIENTRY +_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ); + +extern void GLAPIENTRY +_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2, + GLint vn, GLdouble v1, GLdouble v2 ); + +extern void GLAPIENTRY +_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v ); + +extern void GLAPIENTRY +_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v ); + +extern void GLAPIENTRY +_mesa_GetMapiv( GLenum target, GLenum query, GLint *v ); + +#else + +/** No-op */ +#define _mesa_init_eval( c ) ((void)0) + +/** No-op */ +#define _mesa_free_eval_data( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/execmem.c b/src/mesa/main/execmem.c new file mode 100644 index 00000000000..a6b110ae7ea --- /dev/null +++ b/src/mesa/main/execmem.c @@ -0,0 +1,132 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file exemem.c + * Functions for allocating executable memory. + * + * \author Keith Whitwell + */ + + +#include "imports.h" +#include "glthread.h" + + + +#if defined(__linux__) && !defined(XFree86Server) + +/* + * Allocate a large block of memory which can hold code then dole it out + * in pieces by means of the generic memory manager code. +*/ + + +#include <unistd.h> +#include <sys/mman.h> +#include "mm.h" + +#define EXEC_HEAP_SIZE (128*1024) + +_glthread_DECLARE_STATIC_MUTEX(exec_mutex); + +static memHeap_t *exec_heap = NULL; +static unsigned char *exec_mem = NULL; + + +static void +init_heap(void) +{ + if (!exec_heap) + exec_heap = mmInit( 0, EXEC_HEAP_SIZE ); + + if (!exec_mem) + exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE, + PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +} + + +void * +_mesa_exec_malloc(GLuint size) +{ + PMemBlock block = NULL; + void *addr = NULL; + + _glthread_LOCK_MUTEX(exec_mutex); + + init_heap(); + + if (exec_heap) { + size = (size + 31) & ~31; + block = mmAllocMem( exec_heap, size, 32, 0 ); + } + + if (block) + addr = exec_mem + block->ofs; + + _glthread_UNLOCK_MUTEX(exec_mutex); + + return addr; +} + + +void +_mesa_exec_free(void *addr) +{ + _glthread_LOCK_MUTEX(exec_mutex); + + if (exec_heap) { + PMemBlock block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem); + + if (block) + mmFreeMem(block); + } + + _glthread_UNLOCK_MUTEX(exec_mutex); +} + + +#else + +/* + * Just use regular memory. + */ + +void * +_mesa_exec_malloc(GLuint size) +{ + return _mesa_malloc( size ); +} + + +void +_mesa_exec_free(void *addr) +{ + _mesa_free(addr); +} + + +#endif diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c new file mode 100644 index 00000000000..fae98416511 --- /dev/null +++ b/src/mesa/main/extensions.c @@ -0,0 +1,516 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "extensions.h" +#include "simple_list.h" +#include "mtypes.h" + + +#define F(x) (int)(uintptr_t)&(((struct gl_extensions *)0)->x) +#define ON GL_TRUE +#define OFF GL_FALSE + + +/* + * Note: The GL_MESAX_* extensions are placeholders for future ARB extensions. + */ +static const struct { + GLboolean enabled; + const char *name; + int flag_offset; +} default_extensions[] = { + { OFF, "GL_ARB_depth_texture", F(ARB_depth_texture) }, + { OFF, "GL_ARB_draw_buffers", F(ARB_draw_buffers) }, + { OFF, "GL_ARB_fragment_program", F(ARB_fragment_program) }, + { OFF, "GL_ARB_fragment_shader", F(ARB_fragment_shader) }, + { OFF, "GL_MESAX_half_float_pixel", F(ARB_half_float_pixel) }, + { OFF, "GL_ARB_imaging", F(ARB_imaging) }, + { OFF, "GL_ARB_multisample", F(ARB_multisample) }, + { OFF, "GL_ARB_multitexture", F(ARB_multitexture) }, + { OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) }, + { OFF, "GL_ARB_pixel_buffer_object", F(EXT_pixel_buffer_object) }, + { OFF, "GL_ARB_point_parameters", F(EXT_point_parameters) }, + { OFF, "GL_ARB_point_sprite", F(ARB_point_sprite) }, + { OFF, "GL_ARB_shader_objects", F(ARB_shader_objects) }, + { OFF, "GL_ARB_shading_language_100", F(ARB_shading_language_100) }, + { OFF, "GL_ARB_shadow", F(ARB_shadow) }, + { OFF, "GL_ARB_shadow_ambient", F(SGIX_shadow_ambient) }, + { OFF, "GL_ARB_texture_border_clamp", F(ARB_texture_border_clamp) }, + { OFF, "GL_ARB_texture_compression", F(ARB_texture_compression) }, + { OFF, "GL_ARB_texture_cube_map", F(ARB_texture_cube_map) }, + { OFF, "GL_ARB_texture_env_add", F(EXT_texture_env_add) }, + { OFF, "GL_ARB_texture_env_combine", F(ARB_texture_env_combine) }, + { OFF, "GL_ARB_texture_env_crossbar", F(ARB_texture_env_crossbar) }, + { OFF, "GL_ARB_texture_env_dot3", F(ARB_texture_env_dot3) }, + { OFF, "GL_MESAX_texture_float", F(ARB_texture_float) }, + { OFF, "GL_ARB_texture_mirrored_repeat", F(ARB_texture_mirrored_repeat)}, + { OFF, "GL_ARB_texture_non_power_of_two", F(ARB_texture_non_power_of_two)}, + { OFF, "GL_ARB_texture_rectangle", F(NV_texture_rectangle) }, + { ON, "GL_ARB_transpose_matrix", F(ARB_transpose_matrix) }, + { OFF, "GL_ARB_vertex_buffer_object", F(ARB_vertex_buffer_object) }, + { OFF, "GL_ARB_vertex_program", F(ARB_vertex_program) }, + { OFF, "GL_ARB_vertex_shader", F(ARB_vertex_shader) }, + { ON, "GL_ARB_window_pos", F(ARB_window_pos) }, + { ON, "GL_EXT_abgr", F(EXT_abgr) }, + { ON, "GL_EXT_bgra", F(EXT_bgra) }, + { OFF, "GL_EXT_blend_color", F(EXT_blend_color) }, + { OFF, "GL_EXT_blend_equation_separate", F(EXT_blend_equation_separate) }, + { OFF, "GL_EXT_blend_func_separate", F(EXT_blend_func_separate) }, + { OFF, "GL_EXT_blend_logic_op", F(EXT_blend_logic_op) }, + { OFF, "GL_EXT_blend_minmax", F(EXT_blend_minmax) }, + { OFF, "GL_EXT_blend_subtract", F(EXT_blend_subtract) }, + { ON, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) }, + { OFF, "GL_EXT_cull_vertex", F(EXT_cull_vertex) }, + { ON, "GL_EXT_compiled_vertex_array", F(EXT_compiled_vertex_array) }, + { OFF, "GL_EXT_convolution", F(EXT_convolution) }, + { ON, "GL_EXT_copy_texture", F(EXT_copy_texture) }, + { OFF, "GL_EXT_depth_bounds_test", F(EXT_depth_bounds_test) }, + { ON, "GL_EXT_draw_range_elements", F(EXT_draw_range_elements) }, + { OFF, "GL_EXT_framebuffer_object", F(EXT_framebuffer_object) }, + { OFF, "GL_EXT_fog_coord", F(EXT_fog_coord) }, + { OFF, "GL_EXT_histogram", F(EXT_histogram) }, + { OFF, "GL_EXT_multi_draw_arrays", F(EXT_multi_draw_arrays) }, + { ON, "GL_EXT_packed_pixels", F(EXT_packed_pixels) }, + { OFF, "GL_EXT_paletted_texture", F(EXT_paletted_texture) }, + { OFF, "GL_EXT_pixel_buffer_object", F(EXT_pixel_buffer_object) }, + { OFF, "GL_EXT_point_parameters", F(EXT_point_parameters) }, + { ON, "GL_EXT_polygon_offset", F(EXT_polygon_offset) }, + { ON, "GL_EXT_rescale_normal", F(EXT_rescale_normal) }, + { OFF, "GL_EXT_secondary_color", F(EXT_secondary_color) }, + { ON, "GL_EXT_separate_specular_color", F(EXT_separate_specular_color) }, + { OFF, "GL_EXT_shadow_funcs", F(EXT_shadow_funcs) }, + { OFF, "GL_EXT_shared_texture_palette", F(EXT_shared_texture_palette) }, + { OFF, "GL_EXT_stencil_two_side", F(EXT_stencil_two_side) }, + { OFF, "GL_EXT_stencil_wrap", F(EXT_stencil_wrap) }, + { ON, "GL_EXT_subtexture", F(EXT_subtexture) }, + { ON, "GL_EXT_texture", F(EXT_texture) }, + { ON, "GL_EXT_texture3D", F(EXT_texture3D) }, + { OFF, "GL_EXT_texture_compression_s3tc", F(EXT_texture_compression_s3tc) }, + { ON, "GL_EXT_texture_edge_clamp", F(SGIS_texture_edge_clamp) }, + { OFF, "GL_EXT_texture_env_add", F(EXT_texture_env_add) }, + { OFF, "GL_EXT_texture_env_combine", F(EXT_texture_env_combine) }, + { OFF, "GL_EXT_texture_env_dot3", F(EXT_texture_env_dot3) }, + { OFF, "GL_EXT_texture_filter_anisotropic", F(EXT_texture_filter_anisotropic) }, + { OFF, "GL_EXT_texture_lod_bias", F(EXT_texture_lod_bias) }, + { OFF, "GL_EXT_texture_mirror_clamp", F(EXT_texture_mirror_clamp) }, + { ON, "GL_EXT_texture_object", F(EXT_texture_object) }, + { OFF, "GL_EXT_texture_rectangle", F(NV_texture_rectangle) }, + { ON, "GL_EXT_vertex_array", F(EXT_vertex_array) }, + { OFF, "GL_EXT_vertex_array_set", F(EXT_vertex_array_set) }, + { OFF, "GL_3DFX_texture_compression_FXT1", F(TDFX_texture_compression_FXT1) }, + { OFF, "GL_APPLE_client_storage", F(APPLE_client_storage) }, + { ON, "GL_APPLE_packed_pixels", F(APPLE_packed_pixels) }, + { OFF, "GL_ATI_blend_equation_separate", F(EXT_blend_equation_separate) }, + { OFF, "GL_ATI_texture_env_combine3", F(ATI_texture_env_combine3)}, + { OFF, "GL_ATI_texture_mirror_once", F(ATI_texture_mirror_once)}, + { OFF, "GL_ATI_fragment_shader", F(ATI_fragment_shader)}, + { OFF, "GL_HP_occlusion_test", F(HP_occlusion_test) }, + { OFF, "GL_IBM_multimode_draw_arrays", F(IBM_multimode_draw_arrays) }, + { ON, "GL_IBM_rasterpos_clip", F(IBM_rasterpos_clip) }, + { OFF, "GL_IBM_texture_mirrored_repeat", F(ARB_texture_mirrored_repeat)}, + { OFF, "GL_INGR_blend_func_separate", F(EXT_blend_func_separate) }, + { OFF, "GL_MESA_pack_invert", F(MESA_pack_invert) }, + { OFF, "GL_MESA_packed_depth_stencil", F(MESA_packed_depth_stencil) }, + { OFF, "GL_MESA_program_debug", F(MESA_program_debug) }, + { OFF, "GL_MESA_resize_buffers", F(MESA_resize_buffers) }, + { OFF, "GL_MESA_ycbcr_texture", F(MESA_ycbcr_texture) }, + { ON, "GL_MESA_window_pos", F(ARB_window_pos) }, + { OFF, "GL_NV_blend_square", F(NV_blend_square) }, + { OFF, "GL_NV_fragment_program", F(NV_fragment_program) }, + { ON, "GL_NV_light_max_exponent", F(NV_light_max_exponent) }, + { OFF, "GL_NV_point_sprite", F(NV_point_sprite) }, + { OFF, "GL_NV_texture_rectangle", F(NV_texture_rectangle) }, + { ON, "GL_NV_texgen_reflection", F(NV_texgen_reflection) }, + { OFF, "GL_NV_vertex_program", F(NV_vertex_program) }, + { OFF, "GL_NV_vertex_program1_1", F(NV_vertex_program1_1) }, + { ON, "GL_OES_read_format", F(OES_read_format) }, + { OFF, "GL_SGI_color_matrix", F(SGI_color_matrix) }, + { OFF, "GL_SGI_color_table", F(SGI_color_table) }, + { OFF, "GL_SGI_texture_color_table", F(SGI_texture_color_table) }, + { OFF, "GL_SGIS_generate_mipmap", F(SGIS_generate_mipmap) }, + { OFF, "GL_SGIS_pixel_texture", F(SGIS_pixel_texture) }, + { OFF, "GL_SGIS_texture_border_clamp", F(ARB_texture_border_clamp) }, + { ON, "GL_SGIS_texture_edge_clamp", F(SGIS_texture_edge_clamp) }, + { ON, "GL_SGIS_texture_lod", F(SGIS_texture_lod) }, + { OFF, "GL_SGIX_depth_texture", F(SGIX_depth_texture) }, + { OFF, "GL_SGIX_pixel_texture", F(SGIX_pixel_texture) }, + { OFF, "GL_SGIX_shadow", F(SGIX_shadow) }, + { OFF, "GL_SGIX_shadow_ambient", F(SGIX_shadow_ambient) }, + { OFF, "GL_SUN_multi_draw_arrays", F(EXT_multi_draw_arrays) }, + { OFF, "GL_S3_s3tc", F(S3_s3tc) }, +}; + + + +/** + * Enable all extensions suitable for a software-only renderer. + * This is a convenience function used by the XMesa, OSMesa, GGI drivers, etc. + */ +void +_mesa_enable_sw_extensions(GLcontext *ctx) +{ + ctx->Extensions.ARB_depth_texture = GL_TRUE; + ctx->Extensions.ARB_draw_buffers = GL_TRUE; +#if FEATURE_ARB_fragment_program + ctx->Extensions.ARB_fragment_program = GL_TRUE; +#endif +#if 0 && FEATURE_ARB_fragment_shader + ctx->Extensions.ARB_fragment_shader = GL_TRUE; +#endif + /*ctx->Extensions.ARB_half_float_pixel = GL_TRUE;*/ + ctx->Extensions.ARB_imaging = GL_TRUE; + ctx->Extensions.ARB_multitexture = GL_TRUE; +#if FEATURE_ARB_occlusion_query + ctx->Extensions.ARB_occlusion_query = GL_TRUE; +#endif + ctx->Extensions.ARB_point_sprite = GL_TRUE; +#if 0 && FEATURE_ARB_shader_objects + ctx->Extensions.ARB_shader_objects = GL_TRUE; +#endif +#if 0 && FEATURE_ARB_shading_language_100 + ctx->Extensions.ARB_shading_language_100 = GL_TRUE; +#endif + ctx->Extensions.ARB_shadow = GL_TRUE; + ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; + ctx->Extensions.ARB_texture_cube_map = GL_TRUE; + ctx->Extensions.ARB_texture_env_combine = GL_TRUE; + ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; + ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; + /*ctx->Extensions.ARB_texture_float = GL_TRUE;*/ + ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE; + ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; +#if FEATURE_ARB_vertex_program + ctx->Extensions.ARB_vertex_program = GL_TRUE; +#endif +#if 0 && FEATURE_ARB_vertex_shader + ctx->Extensions.ARB_vertex_shader = GL_TRUE; +#endif +#if FEATURE_ARB_vertex_buffer_object + ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE; +#endif +#if FEATURE_ATI_fragment_shader + ctx->Extensions.ATI_fragment_shader = GL_TRUE; +#endif + ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE; + ctx->Extensions.ATI_texture_mirror_once = GL_TRUE; + ctx->Extensions.EXT_blend_color = GL_TRUE; + ctx->Extensions.EXT_blend_equation_separate = GL_TRUE; + ctx->Extensions.EXT_blend_func_separate = GL_TRUE; + ctx->Extensions.EXT_blend_logic_op = GL_TRUE; + ctx->Extensions.EXT_blend_minmax = GL_TRUE; + ctx->Extensions.EXT_blend_subtract = GL_TRUE; + ctx->Extensions.EXT_convolution = GL_TRUE; + ctx->Extensions.EXT_depth_bounds_test = GL_TRUE; + ctx->Extensions.EXT_fog_coord = GL_TRUE; +#if FEATURE_EXT_framebuffer_object + ctx->Extensions.EXT_framebuffer_object = GL_TRUE; +#endif + ctx->Extensions.EXT_histogram = GL_TRUE; + ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE; + ctx->Extensions.EXT_paletted_texture = GL_TRUE; +#if FEATURE_EXT_pixel_buffer_object + ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; +#endif + ctx->Extensions.EXT_point_parameters = GL_TRUE; + ctx->Extensions.EXT_shadow_funcs = GL_TRUE; + ctx->Extensions.EXT_secondary_color = GL_TRUE; + ctx->Extensions.EXT_shared_texture_palette = GL_TRUE; + ctx->Extensions.EXT_stencil_wrap = GL_TRUE; + ctx->Extensions.EXT_stencil_two_side = GL_TRUE; + ctx->Extensions.EXT_texture_env_add = GL_TRUE; + ctx->Extensions.EXT_texture_env_combine = GL_TRUE; + ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; + ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE; + ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; + ctx->Extensions.HP_occlusion_test = GL_TRUE; + ctx->Extensions.IBM_multimode_draw_arrays = GL_TRUE; + ctx->Extensions.MESA_pack_invert = GL_TRUE; +#if FEATURE_MESA_program_debug + ctx->Extensions.MESA_program_debug = GL_TRUE; +#endif + ctx->Extensions.MESA_resize_buffers = GL_TRUE; + ctx->Extensions.MESA_ycbcr_texture = GL_TRUE; + ctx->Extensions.NV_blend_square = GL_TRUE; + /*ctx->Extensions.NV_light_max_exponent = GL_TRUE;*/ + ctx->Extensions.NV_point_sprite = GL_TRUE; + ctx->Extensions.NV_texture_rectangle = GL_TRUE; + /*ctx->Extensions.NV_texgen_reflection = GL_TRUE;*/ +#if FEATURE_NV_vertex_program + ctx->Extensions.NV_vertex_program = GL_TRUE; + ctx->Extensions.NV_vertex_program1_1 = GL_TRUE; +#endif +#if FEATURE_NV_fragment_program + ctx->Extensions.NV_fragment_program = GL_TRUE; +#endif + ctx->Extensions.SGI_color_matrix = GL_TRUE; + ctx->Extensions.SGI_color_table = GL_TRUE; + ctx->Extensions.SGI_texture_color_table = GL_TRUE; + ctx->Extensions.SGIS_generate_mipmap = GL_TRUE; + ctx->Extensions.SGIS_pixel_texture = GL_TRUE; + ctx->Extensions.SGIS_texture_edge_clamp = GL_TRUE; + ctx->Extensions.SGIX_depth_texture = GL_TRUE; + ctx->Extensions.SGIX_pixel_texture = GL_TRUE; + ctx->Extensions.SGIX_shadow = GL_TRUE; + ctx->Extensions.SGIX_shadow_ambient = GL_TRUE; +} + + +/** + * Enable GL_ARB_imaging and all the EXT extensions that are subsets of it. + */ +void +_mesa_enable_imaging_extensions(GLcontext *ctx) +{ + ctx->Extensions.ARB_imaging = GL_TRUE; + ctx->Extensions.EXT_blend_color = GL_TRUE; + ctx->Extensions.EXT_blend_minmax = GL_TRUE; + ctx->Extensions.EXT_blend_subtract = GL_TRUE; + ctx->Extensions.EXT_convolution = GL_TRUE; + ctx->Extensions.EXT_histogram = GL_TRUE; + ctx->Extensions.SGI_color_matrix = GL_TRUE; + ctx->Extensions.SGI_color_table = GL_TRUE; +} + + + +/** + * Enable all OpenGL 1.3 features and extensions. + * A convenience function to be called by drivers. + */ +void +_mesa_enable_1_3_extensions(GLcontext *ctx) +{ + ctx->Extensions.ARB_multisample = GL_TRUE; + ctx->Extensions.ARB_multitexture = GL_TRUE; + ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; + ctx->Extensions.ARB_texture_compression = GL_TRUE; + ctx->Extensions.ARB_texture_cube_map = GL_TRUE; + ctx->Extensions.ARB_texture_env_combine = GL_TRUE; + ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; + ctx->Extensions.EXT_texture_env_add = GL_TRUE; + /*ctx->Extensions.ARB_transpose_matrix = GL_TRUE;*/ +} + + + +/** + * Enable all OpenGL 1.4 features and extensions. + * A convenience function to be called by drivers. + */ +void +_mesa_enable_1_4_extensions(GLcontext *ctx) +{ + ctx->Extensions.ARB_depth_texture = GL_TRUE; + ctx->Extensions.ARB_shadow = GL_TRUE; + ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; + ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE; + ctx->Extensions.ARB_window_pos = GL_TRUE; + ctx->Extensions.EXT_blend_color = GL_TRUE; + ctx->Extensions.EXT_blend_func_separate = GL_TRUE; + ctx->Extensions.EXT_blend_logic_op = GL_TRUE; + ctx->Extensions.EXT_blend_minmax = GL_TRUE; + ctx->Extensions.EXT_blend_subtract = GL_TRUE; + ctx->Extensions.EXT_fog_coord = GL_TRUE; + ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE; + ctx->Extensions.EXT_point_parameters = GL_TRUE; + ctx->Extensions.EXT_secondary_color = GL_TRUE; + ctx->Extensions.EXT_stencil_wrap = GL_TRUE; + ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; + ctx->Extensions.SGIS_generate_mipmap = GL_TRUE; +} + + +/** + * Enable all OpenGL 1.5 features and extensions. + * A convenience function to be called by drivers. + */ +void +_mesa_enable_1_5_extensions(GLcontext *ctx) +{ + ctx->Extensions.ARB_occlusion_query = GL_TRUE; + ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE; + ctx->Extensions.EXT_shadow_funcs = GL_TRUE; +} + + +/** + * Enable all OpenGL 2.0 features and extensions. + * A convenience function to be called by drivers. + */ +void +_mesa_enable_2_0_extensions(GLcontext *ctx) +{ + ctx->Extensions.ARB_draw_buffers = GL_TRUE; +#if 0 && FEATURE_ARB_fragment_shader + ctx->Extensions.ARB_fragment_shader = GL_TRUE; +#endif + ctx->Extensions.ARB_point_sprite = GL_TRUE; + ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; +#if 0 && FEATURE_ARB_shader_objects + ctx->Extensions.ARB_shader_objects = GL_TRUE; +#endif +#if 0 && FEATURE_ARB_shading_language_100 + ctx->Extensions.ARB_shading_language_100 = GL_TRUE; +#endif + ctx->Extensions.EXT_stencil_two_side = GL_TRUE; +#if 0 && FEATURE_ARB_vertex_shader + ctx->Extensions.ARB_vertex_shader = GL_TRUE; +#endif +} + + + +/** + * Either enable or disable the named extension. + */ +static void +set_extension( GLcontext *ctx, const char *name, GLboolean state ) +{ + GLboolean *base = (GLboolean *) &ctx->Extensions; + GLuint i; + + if (ctx->Extensions.String) { + /* The string was already queried - can't change it now! */ + _mesa_problem(ctx, "Trying to enable/disable extension after glGetString(GL_EXTENSIONS): %s", name); + return; + } + + for (i = 0 ; i < Elements(default_extensions) ; i++) { + if (_mesa_strcmp(default_extensions[i].name, name) == 0) { + if (default_extensions[i].flag_offset) { + GLboolean *enabled = base + default_extensions[i].flag_offset; + *enabled = state; + } + return; + } + } + _mesa_problem(ctx, "Trying to enable unknown extension: %s", name); +} + + +/** + * Enable the named extension. + * Typically called by drivers. + */ +void +_mesa_enable_extension( GLcontext *ctx, const char *name ) +{ + set_extension(ctx, name, GL_TRUE); +} + + +/** + * Disable the named extension. + * XXX is this really needed??? + */ +void +_mesa_disable_extension( GLcontext *ctx, const char *name ) +{ + set_extension(ctx, name, GL_FALSE); +} + + +/** + * Test if the named extension is enabled in this context. + */ +GLboolean +_mesa_extension_is_enabled( GLcontext *ctx, const char *name ) +{ + const GLboolean *base = (const GLboolean *) &ctx->Extensions; + GLuint i; + + for (i = 0 ; i < Elements(default_extensions) ; i++) { + if (_mesa_strcmp(default_extensions[i].name, name) == 0) { + if (!default_extensions[i].flag_offset) + return GL_TRUE; + return *(base + default_extensions[i].flag_offset); + } + } + return GL_FALSE; +} + + +/** + * Run through the default_extensions array above and set the + * ctx->Extensions.ARB/EXT_* flags accordingly. + * To be called during context initialization. + */ +void +_mesa_init_extensions( GLcontext *ctx ) +{ + GLboolean *base = (GLboolean *) &ctx->Extensions; + GLuint i; + + for (i = 0 ; i < Elements(default_extensions) ; i++) { + if (default_extensions[i].enabled && + default_extensions[i].flag_offset) { + *(base + default_extensions[i].flag_offset) = GL_TRUE; + } + } +} + + +/** + * Construct the GL_EXTENSIONS string. Called the first time that + * glGetString(GL_EXTENSIONS) is called. + */ +GLubyte * +_mesa_make_extension_string( GLcontext *ctx ) +{ + const GLboolean *base = (const GLboolean *) &ctx->Extensions; + GLuint extStrLen = 0; + GLubyte *s; + GLuint i; + + /* first, compute length of the extension string */ + for (i = 0 ; i < Elements(default_extensions) ; i++) { + if (!default_extensions[i].flag_offset || + *(base + default_extensions[i].flag_offset)) { + extStrLen += (GLuint)_mesa_strlen(default_extensions[i].name) + 1; + } + } + s = (GLubyte *) _mesa_malloc(extStrLen); + + /* second, build the extension string */ + extStrLen = 0; + for (i = 0 ; i < Elements(default_extensions) ; i++) { + if (!default_extensions[i].flag_offset || + *(base + default_extensions[i].flag_offset)) { + GLuint len = (GLuint)_mesa_strlen(default_extensions[i].name); + _mesa_memcpy(s + extStrLen, default_extensions[i].name, len); + extStrLen += len; + s[extStrLen] = (GLubyte) ' '; + extStrLen++; + } + } + ASSERT(extStrLen > 0); + + s[extStrLen - 1] = 0; + + return s; +} diff --git a/src/mesa/main/extensions.h b/src/mesa/main/extensions.h new file mode 100644 index 00000000000..9d843a8b6b6 --- /dev/null +++ b/src/mesa/main/extensions.h @@ -0,0 +1,84 @@ +/** + * \file extensions.h + * Extension handling. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _EXTENSIONS_H_ +#define _EXTENSIONS_H_ + +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void _mesa_enable_sw_extensions(GLcontext *ctx); + +extern void _mesa_enable_imaging_extensions(GLcontext *ctx); + +extern void _mesa_enable_1_3_extensions(GLcontext *ctx); + +extern void _mesa_enable_1_4_extensions(GLcontext *ctx); + +extern void _mesa_enable_1_5_extensions(GLcontext *ctx); + +extern void _mesa_enable_2_0_extensions(GLcontext *ctx); + +extern void _mesa_enable_extension(GLcontext *ctx, const char *name); + +extern void _mesa_disable_extension(GLcontext *ctx, const char *name); + +extern GLboolean _mesa_extension_is_enabled(GLcontext *ctx, const char *name); + +extern void _mesa_init_extensions(GLcontext *ctx); + +extern GLubyte *_mesa_make_extension_string(GLcontext *ctx); + +#else + +/** No-op */ +#define _mesa_extensions_dtr( ctx ) ((void)0) + +/** No-op */ +#define _mesa_extensions_ctr( ctx ) ((void)0) + +/** No-op */ +#define _mesa_extensions_get_string( ctx ) "GL_EXT_texture_object" + +/** No-op */ +#define _mesa_enable_imaging_extensions( c ) ((void)0) + +/** No-op */ +#define _mesa_enable_extension( c, n ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c new file mode 100644 index 00000000000..b16e13a2209 --- /dev/null +++ b/src/mesa/main/fbobject.c @@ -0,0 +1,1357 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Authors: + * Brian Paul + */ + + +#include "context.h" +#include "fbobject.h" +#include "framebuffer.h" +#include "hash.h" +#include "renderbuffer.h" +#include "teximage.h" +#include "texstore.h" + + +/** + * Notes: + * + * None of the GL_EXT_framebuffer_object functions are compiled into + * display lists. + */ + + + +/* + * When glGenRender/FramebuffersEXT() is called we insert pointers to + * these placeholder objects into the hash table. + * Later, when the object ID is first bound, we replace the placeholder + * with the real frame/renderbuffer. + */ +static struct gl_framebuffer DummyFramebuffer; +static struct gl_renderbuffer DummyRenderbuffer; + + +#define IS_CUBE_FACE(TARGET) \ + ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \ + (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) + + +/** + * Helper routine for getting a gl_renderbuffer. + */ +static struct gl_renderbuffer * +lookup_renderbuffer(GLcontext *ctx, GLuint id) +{ + struct gl_renderbuffer *rb; + + if (id == 0) + return NULL; + + rb = (struct gl_renderbuffer *) + _mesa_HashLookup(ctx->Shared->RenderBuffers, id); + return rb; +} + + +/** + * Helper routine for getting a gl_framebuffer. + */ +static struct gl_framebuffer * +lookup_framebuffer(GLcontext *ctx, GLuint id) +{ + struct gl_framebuffer *fb; + + if (id == 0) + return NULL; + + fb = (struct gl_framebuffer *) + _mesa_HashLookup(ctx->Shared->FrameBuffers, id); + return fb; +} + + +/** + * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding + * gl_renderbuffer_attachment object. + */ +static struct gl_renderbuffer_attachment * +get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment) +{ + GLuint i; + + switch (attachment) { + case GL_COLOR_ATTACHMENT0_EXT: + case GL_COLOR_ATTACHMENT1_EXT: + case GL_COLOR_ATTACHMENT2_EXT: + case GL_COLOR_ATTACHMENT3_EXT: + case GL_COLOR_ATTACHMENT4_EXT: + case GL_COLOR_ATTACHMENT5_EXT: + case GL_COLOR_ATTACHMENT6_EXT: + case GL_COLOR_ATTACHMENT7_EXT: + case GL_COLOR_ATTACHMENT8_EXT: + case GL_COLOR_ATTACHMENT9_EXT: + case GL_COLOR_ATTACHMENT10_EXT: + case GL_COLOR_ATTACHMENT11_EXT: + case GL_COLOR_ATTACHMENT12_EXT: + case GL_COLOR_ATTACHMENT13_EXT: + case GL_COLOR_ATTACHMENT14_EXT: + case GL_COLOR_ATTACHMENT15_EXT: + i = attachment - GL_COLOR_ATTACHMENT0_EXT; + if (i >= ctx->Const.MaxColorAttachments) { + return NULL; + } + return &fb->Attachment[BUFFER_COLOR0 + i]; + case GL_DEPTH_ATTACHMENT_EXT: + return &fb->Attachment[BUFFER_DEPTH]; + case GL_STENCIL_ATTACHMENT_EXT: + return &fb->Attachment[BUFFER_STENCIL]; + default: + return NULL; + } +} + + +/** + * Remove any texture or renderbuffer attached to the given attachment + * point. Update reference counts, etc. + */ +void +_mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) +{ + if (att->Type == GL_TEXTURE) { + ASSERT(att->Texture); + if (att->Renderbuffer) { + /* delete/remove the 'wrapper' renderbuffer */ + /* XXX do we really want to do this??? */ + att->Renderbuffer->Delete(att->Renderbuffer); + att->Renderbuffer = NULL; + } + att->Texture->RefCount--; + if (att->Texture->RefCount == 0) { + ctx->Driver.DeleteTexture(ctx, att->Texture); + } + att->Texture = NULL; + } + else if (att->Type == GL_RENDERBUFFER_EXT) { + ASSERT(att->Renderbuffer); + ASSERT(!att->Texture); + att->Renderbuffer->RefCount--; + if (att->Renderbuffer->RefCount == 0) { + att->Renderbuffer->Delete(att->Renderbuffer); + } + att->Renderbuffer = NULL; + } + att->Type = GL_NONE; + att->Complete = GL_TRUE; +} + + +/** + * Bind a texture object to an attachment point. + * The previous binding, if any, will be removed first. + */ +void +_mesa_set_texture_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset) +{ + _mesa_remove_attachment(ctx, att); + att->Type = GL_TEXTURE; + att->Texture = texObj; + att->TextureLevel = level; + if (IS_CUBE_FACE(texTarget)) { + att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X; + } + else { + att->CubeMapFace = 0; + } + att->Zoffset = zoffset; + att->Complete = GL_FALSE; + + texObj->RefCount++; + + /* XXX when we attach to a texture, we should probably set the + * att->Renderbuffer pointer to a "wrapper renderbuffer" which + * makes the texture image look like renderbuffer. + */ +} + + +/** + * Bind a renderbuffer to an attachment point. + * The previous binding, if any, will be removed first. + */ +void +_mesa_set_renderbuffer_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) +{ + _mesa_remove_attachment(ctx, att); + att->Type = GL_RENDERBUFFER_EXT; + att->Renderbuffer = rb; + att->Texture = NULL; /* just to be safe */ + att->Complete = GL_FALSE; + rb->RefCount++; +} + + +/** + * Fallback for ctx->Driver.FramebufferRenderbuffer() + * Sets a framebuffer attachment to a particular renderbuffer. + * The framebuffer in question is ctx->DrawBuffer. + * \sa _mesa_renderbuffer_texture + */ +void +_mesa_framebuffer_renderbuffer(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) +{ + if (rb) { + _mesa_set_renderbuffer_attachment(ctx, att, rb); + } + else { + _mesa_remove_attachment(ctx, att); + } +} + + +/** + * Test if an attachment point is complete and update its Complete field. + * \param format if GL_COLOR, this is a color attachment point, + * if GL_DEPTH, this is a depth component attachment point, + * if GL_STENCIL, this is a stencil component attachment point. + */ +static void +test_attachment_completeness(const GLcontext *ctx, GLenum format, + struct gl_renderbuffer_attachment *att) +{ + assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL); + + /* assume complete */ + att->Complete = GL_TRUE; + + /* Look for reasons why the attachment might be incomplete */ + if (att->Type == GL_TEXTURE) { + const struct gl_texture_object *texObj = att->Texture; + struct gl_texture_image *texImage; + + if (!texObj) { + att->Complete = GL_FALSE; + return; + } + + texImage = texObj->Image[att->CubeMapFace][att->TextureLevel]; + if (!texImage) { + att->Complete = GL_FALSE; + return; + } + if (texImage->Width < 1 || texImage->Height < 1) { + att->Complete = GL_FALSE; + return; + } + if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) { + att->Complete = GL_FALSE; + return; + } + + if (format == GL_COLOR) { + if (texImage->TexFormat->BaseFormat != GL_RGB && + texImage->TexFormat->BaseFormat != GL_RGBA) { + att->Complete = GL_FALSE; + return; + } + } + else if (format == GL_DEPTH) { + if (texImage->TexFormat->BaseFormat != GL_DEPTH_COMPONENT) { + att->Complete = GL_FALSE; + return; + } + } + else { + /* no such thing as stencil textures */ + att->Complete = GL_FALSE; + return; + } + } + else if (att->Type == GL_RENDERBUFFER_EXT) { + if (att->Renderbuffer->Width < 1 || att->Renderbuffer->Height < 1) { + att->Complete = GL_FALSE; + return; + } + if (format == GL_COLOR) { + if (att->Renderbuffer->_BaseFormat != GL_RGB && + att->Renderbuffer->_BaseFormat != GL_RGBA) { + att->Complete = GL_FALSE; + return; + } + } + else if (format == GL_DEPTH) { + if (att->Renderbuffer->_BaseFormat != GL_DEPTH_COMPONENT) { + att->Complete = GL_FALSE; + return; + } + } + else { + assert(format == GL_STENCIL); + if (att->Renderbuffer->_BaseFormat != GL_STENCIL_INDEX) { + att->Complete = GL_FALSE; + return; + } + } + } + else { + ASSERT(att->Type == GL_NONE); + /* complete */ + return; + } +} + + +/** + * Test if the given framebuffer object is complete and update its + * Status field with the results. + * Also update the framebuffer's Width and Height fields if the + * framebuffer is complete. + */ +void +_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb) +{ + GLuint numImages, width = 0, height = 0; + GLenum intFormat = GL_NONE; + GLuint w = 0, h = 0; + GLint i; + + assert(fb->Name != 0); + + numImages = 0; + fb->Width = 0; + fb->Height = 0; + + /* Start at -2 to more easily loop over all attachment points */ + for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { + struct gl_renderbuffer_attachment *att; + GLenum f; + + if (i == -2) { + att = &fb->Attachment[BUFFER_DEPTH]; + test_attachment_completeness(ctx, GL_DEPTH, att); + if (!att->Complete) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + return; + } + } + else if (i == -1) { + att = &fb->Attachment[BUFFER_STENCIL]; + test_attachment_completeness(ctx, GL_STENCIL, att); + if (!att->Complete) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + return; + } + } + else { + att = &fb->Attachment[BUFFER_COLOR0 + i]; + test_attachment_completeness(ctx, GL_COLOR, att); + if (!att->Complete) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + return; + } + } + + if (att->Type == GL_TEXTURE) { + w = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Width; + h = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Height; + f = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Format; + numImages++; + if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; + return; + } + } + else if (att->Type == GL_RENDERBUFFER_EXT) { + w = att->Renderbuffer->Width; + h = att->Renderbuffer->Height; + f = att->Renderbuffer->InternalFormat; + numImages++; + } + else { + assert(att->Type == GL_NONE); + continue; + } + + if (numImages == 1) { + /* set required width, height and format */ + width = w; + height = h; + if (i >= 0) + intFormat = f; + } + else { + /* check that width, height, format are same */ + if (w != width || h != height) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; + return; + } + if (intFormat != GL_NONE && f != intFormat) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; + return; + } + } + } + + /* Check that all DrawBuffers are present */ + for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { + if (fb->ColorDrawBuffer[i] != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorDrawBuffer[i]); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; + return; + } + } + } + + /* Check that the ReadBuffer is present */ + if (fb->ColorReadBuffer != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ColorReadBuffer); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; + return; + } + } + + /* Check if any renderbuffer is attached more than once */ + for (i = 0; i < BUFFER_COUNT - 1; i++) { + struct gl_renderbuffer *rb_i = fb->Attachment[i].Renderbuffer; + if (rb_i) { + GLint j; + for (j = i + 1; j < BUFFER_COUNT; j++) { + struct gl_renderbuffer *rb_j = fb->Attachment[j].Renderbuffer; + if (rb_i == rb_j) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT; + return; + } + } + } + } + + + if (numImages == 0) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; + return; + } + + /* + * If we get here, the framebuffer is complete! + */ + fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + fb->Width = w; + fb->Height = h; +} + + +GLboolean GLAPIENTRY +_mesa_IsRenderbufferEXT(GLuint renderbuffer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (renderbuffer) { + struct gl_renderbuffer *rb = lookup_renderbuffer(ctx, renderbuffer); + if (rb != NULL && rb != &DummyRenderbuffer) + return GL_TRUE; + } + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) +{ + struct gl_renderbuffer *newRb, *oldRb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glBindRenderbufferEXT(target)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (renderbuffer) { + newRb = lookup_renderbuffer(ctx, renderbuffer); + if (newRb == &DummyRenderbuffer) { + /* ID was reserved, but no real renderbuffer object made yet */ + newRb = NULL; + } + if (!newRb) { + /* create new renderbuffer object */ + newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); + if (!newRb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); + return; + } + ASSERT(newRb->AllocStorage); + _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); + } + newRb->RefCount++; + } + else { + newRb = NULL; + } + + oldRb = ctx->CurrentRenderbuffer; + if (oldRb) { + oldRb->RefCount--; + if (oldRb->RefCount == 0) { + oldRb->Delete(oldRb); + } + } + + ASSERT(newRb != &DummyRenderbuffer); + + ctx->CurrentRenderbuffer = newRb; +} + + +void GLAPIENTRY +_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + for (i = 0; i < n; i++) { + if (renderbuffers[i] > 0) { + struct gl_renderbuffer *rb; + rb = lookup_renderbuffer(ctx, renderbuffers[i]); + if (rb) { + /* check if deleting currently bound renderbuffer object */ + if (rb == ctx->CurrentRenderbuffer) { + /* bind default */ + ASSERT(rb->RefCount >= 2); + _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + } + + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); + + if (rb != &DummyRenderbuffer) { + /* But the object will not be freed until it's no longer + * bound in any context. + */ + rb->RefCount--; + if (rb->RefCount == 0) { + rb->Delete(rb); + } + } + } + } + } +} + + +void GLAPIENTRY +_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); + return; + } + + if (!renderbuffers) + return; + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); + + for (i = 0; i < n; i++) { + GLuint name = first + i; + renderbuffers[i] = name; + /* insert dummy placeholder into hash table */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } +} + + +/** + * Given an internal format token for a render buffer, return the + * corresponding base format. + * \return one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT + * or zero if error. + */ +static GLenum +base_internal_format(GLcontext *ctx, GLenum internalFormat) +{ + switch (internalFormat) { + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1_EXT: + case GL_STENCIL_INDEX4_EXT: + case GL_STENCIL_INDEX8_EXT: + case GL_STENCIL_INDEX16_EXT: + return GL_STENCIL_INDEX; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + return GL_DEPTH_COMPONENT; + /* XXX add floating point formats eventually */ + default: + return 0; + } +} + + +void GLAPIENTRY +_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height) +{ + struct gl_renderbuffer *rb; + GLenum baseFormat; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(target)"); + return; + } + + baseFormat = base_internal_format(ctx, internalFormat); + if (baseFormat == 0) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glRenderbufferStorageEXT(internalFormat)"); + return; + } + + if (width < 1 || width > ctx->Const.MaxRenderbufferSize) { + _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(width)"); + return; + } + + if (height < 1 || height > ctx->Const.MaxRenderbufferSize) { + _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(height)"); + return; + } + + rb = ctx->CurrentRenderbuffer; + + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferStorageEXT"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + /* Now allocate the storage */ + ASSERT(rb->AllocStorage); + if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { + /* No error - check/set fields now */ + assert(rb->Width == width); + assert(rb->Height == height); + assert(rb->InternalFormat); + rb->_BaseFormat = baseFormat; + } + else { + /* Probably ran out of memory - clear the fields */ + rb->Width = 0; + rb->Height = 0; + rb->InternalFormat = GL_NONE; + rb->_BaseFormat = GL_NONE; + } + + /* + test_framebuffer_completeness(ctx, fb); + */ + /* XXX if this renderbuffer is attached anywhere, invalidate attachment + * points??? + */ +} + + +void GLAPIENTRY +_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetRenderbufferParameterivEXT(target)"); + return; + } + + if (!ctx->CurrentRenderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetRenderbufferParameterivEXT"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + switch (pname) { + case GL_RENDERBUFFER_WIDTH_EXT: + *params = ctx->CurrentRenderbuffer->Width; + return; + case GL_RENDERBUFFER_HEIGHT_EXT: + *params = ctx->CurrentRenderbuffer->Height; + return; + case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT: + *params = ctx->CurrentRenderbuffer->InternalFormat; + return; + case GL_RENDERBUFFER_RED_SIZE_EXT: + if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB || + ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) { + *params = ctx->CurrentRenderbuffer->ComponentSizes[0]; + } + else { + *params = 0; + } + break; + case GL_RENDERBUFFER_GREEN_SIZE_EXT: + if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB || + ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) { + *params = ctx->CurrentRenderbuffer->ComponentSizes[1]; + } + else { + *params = 0; + } + break; + case GL_RENDERBUFFER_BLUE_SIZE_EXT: + if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB || + ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) { + *params = ctx->CurrentRenderbuffer->ComponentSizes[2]; + } + else { + *params = 0; + } + break; + case GL_RENDERBUFFER_ALPHA_SIZE_EXT: + if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB || + ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) { + *params = ctx->CurrentRenderbuffer->ComponentSizes[3]; + } + else { + *params = 0; + } + break; + case GL_RENDERBUFFER_DEPTH_SIZE_EXT: + if (ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) { + *params = ctx->CurrentRenderbuffer->ComponentSizes[0]; + } + else { + *params = 0; + } + break; + case GL_RENDERBUFFER_STENCIL_SIZE_EXT: + if (ctx->CurrentRenderbuffer->_BaseFormat == GL_STENCIL_INDEX) { + *params = ctx->CurrentRenderbuffer->ComponentSizes[0]; + } + else { + *params = 0; + } + break; + + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetRenderbufferParameterivEXT(target)"); + return; + } +} + + +GLboolean GLAPIENTRY +_mesa_IsFramebufferEXT(GLuint framebuffer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (framebuffer) { + struct gl_framebuffer *rb = lookup_framebuffer(ctx, framebuffer); + if (rb != NULL && rb != &DummyFramebuffer) + return GL_TRUE; + } + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) +{ + struct gl_framebuffer *newFb, *newReadFb, *oldFb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_FRAMEBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glBindFramebufferEXT(target)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (framebuffer) { + /* Binding a user-created framebuffer object */ + newFb = lookup_framebuffer(ctx, framebuffer); + if (newFb == &DummyFramebuffer) { + /* ID was reserved, but no real framebuffer object made yet */ + newFb = NULL; + } + if (!newFb) { + /* create new framebuffer object */ + newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); + if (!newFb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); + return; + } + _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb); + } + newFb->RefCount++; + newReadFb = newFb; + } + else { + /* Binding the window system framebuffer (which was originally set + * with MakeCurrent). + */ + newFb = ctx->WinSysDrawBuffer; + newReadFb = ctx->WinSysReadBuffer; + } + + oldFb = ctx->DrawBuffer; + if (oldFb && oldFb->Name != 0) { + oldFb->RefCount--; + if (oldFb->RefCount == 0) { + oldFb->Delete(oldFb); + } + } + + ASSERT(newFb != &DummyFramebuffer); + + /* Note, we set both the GL_DRAW_BUFFER and GL_READ_BUFFER state: */ + ctx->DrawBuffer = newFb; + ctx->ReadBuffer = newReadFb; +} + + +void GLAPIENTRY +_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + for (i = 0; i < n; i++) { + if (framebuffers[i] > 0) { + struct gl_framebuffer *fb; + fb = lookup_framebuffer(ctx, framebuffers[i]); + if (fb) { + ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); + + /* check if deleting currently bound framebuffer object */ + if (fb == ctx->DrawBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); + + if (fb != &DummyFramebuffer) { + /* But the object will not be freed until it's no longer + * bound in any context. + */ + fb->RefCount--; + if (fb->RefCount == 0) { + fb->Delete(fb); + } + } + } + } + } +} + + +void GLAPIENTRY +_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); + return; + } + + if (!framebuffers) + return; + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n); + + for (i = 0; i < n; i++) { + GLuint name = first + i; + framebuffers[i] = name; + /* insert dummy placeholder into hash table */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } +} + + + +GLenum GLAPIENTRY +_mesa_CheckFramebufferStatusEXT(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); + + if (target != GL_FRAMEBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); + return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */ + } + + if (ctx->DrawBuffer->Name == 0) { + /* The window system / default framebuffer is always complete */ + return GL_FRAMEBUFFER_COMPLETE_EXT; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer); + return ctx->DrawBuffer->_Status; +} + + + +/** + * Do error checking common to glFramebufferTexture1D/2D/3DEXT. + * \return GL_TRUE if any error, GL_FALSE otherwise + */ +static GLboolean +error_check_framebuffer_texture(GLcontext *ctx, GLuint dims, + GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + ASSERT(dims >= 1 && dims <= 3); + + if (target != GL_FRAMEBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture%dDEXT(target)", dims); + return GL_TRUE; + } + + /* check framebuffer binding */ + if (ctx->DrawBuffer->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%dDEXT", dims); + return GL_TRUE; + } + + /* only check textarget, level if texture ID is non-zero */ + if (texture) { + if ((dims == 1 && textarget != GL_TEXTURE_1D) || + (dims == 3 && textarget != GL_TEXTURE_3D) || + (dims == 2 && textarget != GL_TEXTURE_2D && + textarget != GL_TEXTURE_RECTANGLE_ARB && + !IS_CUBE_FACE(textarget))) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%dDEXT(textarget)", dims); + return GL_TRUE; + } + + if ((level < 0) || level >= _mesa_max_texture_levels(ctx, textarget)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%dDEXT(level)", dims); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (error_check_framebuffer_texture(ctx, 1, target, attachment, + textarget, texture, level)) + return; + + ASSERT(textarget == GL_TEXTURE_1D); + + att = get_attachment(ctx, ctx->DrawBuffer, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture1DEXT(attachment)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (texture) { + texObj = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texture); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture1DEXT(texture)"); + return; + } + if (texObj->Target != textarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ + "glFramebufferTexture1DEXT(texture target)"); + return; + } + } + else { + /* remove texture attachment */ + texObj = NULL; + } + ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0); +} + + +void GLAPIENTRY +_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (error_check_framebuffer_texture(ctx, 2, target, attachment, + textarget, texture, level)) + return; + + ASSERT(textarget == GL_TEXTURE_2D || + textarget == GL_TEXTURE_RECTANGLE_ARB || + IS_CUBE_FACE(textarget)); + + att = get_attachment(ctx, ctx->DrawBuffer, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture2DEXT(attachment)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (texture) { + texObj = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texture); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture2DEXT(texture)"); + return; + } + if ((texObj->Target == GL_TEXTURE_2D && textarget != GL_TEXTURE_2D) || + (texObj->Target == GL_TEXTURE_RECTANGLE_ARB + && textarget != GL_TEXTURE_RECTANGLE_ARB) || + (texObj->Target == GL_TEXTURE_CUBE_MAP + && !IS_CUBE_FACE(textarget))) { + _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ + "glFramebufferTexture2DEXT(texture target)"); + return; + } + } + else { + /* remove texture attachment */ + texObj = NULL; + } + ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0); +} + + +void GLAPIENTRY +_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level, GLint zoffset) +{ + struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (error_check_framebuffer_texture(ctx, 3, target, attachment, + textarget, texture, level)) + return; + + ASSERT(textarget == GL_TEXTURE_3D); + + att = get_attachment(ctx, ctx->DrawBuffer, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture1DEXT(attachment)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (texture) { + const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + texObj = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texture); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture3DEXT(texture)"); + return; + } + if (texObj->Target != textarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ + "glFramebufferTexture3DEXT(texture target)"); + return; + } + if (zoffset < 0 || zoffset >= maxSize) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture3DEXT(zoffset)"); + return; + } + } + else { + /* remove texture attachment */ + texObj = NULL; + } + ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, + level, zoffset); +} + + +void GLAPIENTRY +_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, + GLenum renderbufferTarget, + GLuint renderbuffer) +{ + struct gl_renderbuffer_attachment *att; + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_FRAMEBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(target)"); + return; + } + + if (renderbufferTarget != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(renderbufferTarget)"); + return; + } + + if (ctx->DrawBuffer->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); + return; + } + + att = get_attachment(ctx, ctx->DrawBuffer, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(attachment)"); + return; + } + + if (renderbuffer) { + rb = lookup_renderbuffer(ctx, renderbuffer); + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbufferEXT(renderbuffer)"); + return; + } + } + else { + /* remove renderbuffer attachment */ + rb = NULL; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + assert(ctx->Driver.FramebufferRenderbuffer); + ctx->Driver.FramebufferRenderbuffer(ctx, att, rb); +} + + +void GLAPIENTRY +_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, + GLenum pname, GLint *params) +{ + const struct gl_renderbuffer_attachment *att; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_FRAMEBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(target)"); + return; + } + + if (ctx->DrawBuffer->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferAttachmentParameterivEXT"); + return; + } + + att = get_attachment(ctx, ctx->DrawBuffer, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(attachment)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: + *params = att->Type; + return; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: + if (att->Type == GL_RENDERBUFFER_EXT) { + *params = att->Renderbuffer->Name; + } + else if (att->Type == GL_TEXTURE) { + *params = att->Texture->Name; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: + if (att->Type == GL_TEXTURE) { + *params = att->TextureLevel; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: + if (att->Type == GL_TEXTURE) { + *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: + if (att->Type == GL_TEXTURE) { + *params = att->Zoffset; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GenerateMipmapEXT(GLenum target) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + /* OK, legal value */ + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + + /* XXX this might not handle cube maps correctly */ + _mesa_generate_mipmap(ctx, target, texUnit, texObj); +} diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h new file mode 100644 index 00000000000..2c86ef93726 --- /dev/null +++ b/src/mesa/main/fbobject.h @@ -0,0 +1,114 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef FBOBJECT_H +#define FBOBJECT_H + + +extern void +_mesa_remove_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att); + +extern void +_mesa_set_texture_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset); + +extern void +_mesa_set_renderbuffer_attachment(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb); + +extern void +_mesa_framebuffer_renderbuffer(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb); + +extern void +_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb); + +extern GLboolean GLAPIENTRY +_mesa_IsRenderbufferEXT(GLuint renderbuffer); + +extern void GLAPIENTRY +_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer); + +extern void GLAPIENTRY +_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers); + +extern void GLAPIENTRY +_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers); + +extern void GLAPIENTRY +_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalformat, + GLsizei width, GLsizei height); + +extern void GLAPIENTRY +_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, + GLint *params); + +extern GLboolean GLAPIENTRY +_mesa_IsFramebufferEXT(GLuint framebuffer); + +extern void GLAPIENTRY +_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer); + +extern void GLAPIENTRY +_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers); + +extern void GLAPIENTRY +_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers); + +extern GLenum GLAPIENTRY +_mesa_CheckFramebufferStatusEXT(GLenum target); + +extern void GLAPIENTRY +_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level); + +extern void GLAPIENTRY +_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level); + +extern void GLAPIENTRY +_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level, GLint zoffset); + +extern void GLAPIENTRY +_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + +extern void GLAPIENTRY +_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, + GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GenerateMipmapEXT(GLenum target); + + +#endif /* FBOBJECT_H */ diff --git a/src/mesa/main/feedback.c b/src/mesa/main/feedback.c new file mode 100644 index 00000000000..48c2ccbff30 --- /dev/null +++ b/src/mesa/main/feedback.c @@ -0,0 +1,541 @@ +/** + * \file feedback.c + * Selection and feedback modes functions. + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "enums.h" +#include "feedback.h" +#include "macros.h" +#include "mtypes.h" + + +#if _HAVE_FULL_GL + + +#define FB_3D 0x01 +#define FB_4D 0x02 +#define FB_INDEX 0x04 +#define FB_COLOR 0x08 +#define FB_TEXTURE 0X10 + + + +void GLAPIENTRY +_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->RenderMode==GL_FEEDBACK) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" ); + return; + } + if (size<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" ); + return; + } + if (!buffer) { + _mesa_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" ); + ctx->Feedback.BufferSize = 0; + return; + } + + switch (type) { + case GL_2D: + ctx->Feedback._Mask = 0; + break; + case GL_3D: + ctx->Feedback._Mask = FB_3D; + break; + case GL_3D_COLOR: + ctx->Feedback._Mask = (FB_3D | + (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX)); + break; + case GL_3D_COLOR_TEXTURE: + ctx->Feedback._Mask = (FB_3D | + (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX) | + FB_TEXTURE); + break; + case GL_4D_COLOR_TEXTURE: + ctx->Feedback._Mask = (FB_3D | FB_4D | + (ctx->Visual.rgbMode ? FB_COLOR : FB_INDEX) | + FB_TEXTURE); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" ); + return; + } + + FLUSH_VERTICES(ctx, _NEW_RENDERMODE); /* Always flush */ + ctx->Feedback.Type = type; + ctx->Feedback.BufferSize = size; + ctx->Feedback.Buffer = buffer; + ctx->Feedback.Count = 0; /* Becaues of this. */ +} + + +void GLAPIENTRY +_mesa_PassThrough( GLfloat token ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->RenderMode==GL_FEEDBACK) { + FLUSH_VERTICES(ctx, 0); + FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN ); + FEEDBACK_TOKEN( ctx, token ); + } +} + + + +/* + * Put a vertex into the feedback buffer. + */ +void _mesa_feedback_vertex( GLcontext *ctx, + const GLfloat win[4], + const GLfloat color[4], + GLfloat index, + const GLfloat texcoord[4] ) +{ +#if 0 + { + /* snap window x, y to fractional pixel position */ + const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); + GLfixed x, y; + x = FloatToFixed(win[0]) & snapMask; + y = FloatToFixed(win[1]) & snapMask; + FEEDBACK_TOKEN(ctx, FixedToFloat(x)); + FEEDBACK_TOKEN(ctx, FixedToFloat(y) ); + } +#else + FEEDBACK_TOKEN( ctx, win[0] ); + FEEDBACK_TOKEN( ctx, win[1] ); +#endif + if (ctx->Feedback._Mask & FB_3D) { + FEEDBACK_TOKEN( ctx, win[2] ); + } + if (ctx->Feedback._Mask & FB_4D) { + FEEDBACK_TOKEN( ctx, win[3] ); + } + if (ctx->Feedback._Mask & FB_INDEX) { + FEEDBACK_TOKEN( ctx, (GLfloat) index ); + } + if (ctx->Feedback._Mask & FB_COLOR) { + FEEDBACK_TOKEN( ctx, color[0] ); + FEEDBACK_TOKEN( ctx, color[1] ); + FEEDBACK_TOKEN( ctx, color[2] ); + FEEDBACK_TOKEN( ctx, color[3] ); + } + if (ctx->Feedback._Mask & FB_TEXTURE) { + FEEDBACK_TOKEN( ctx, texcoord[0] ); + FEEDBACK_TOKEN( ctx, texcoord[1] ); + FEEDBACK_TOKEN( ctx, texcoord[2] ); + FEEDBACK_TOKEN( ctx, texcoord[3] ); + } +} + +#endif + + +/**********************************************************************/ +/** \name Selection */ +/*@{*/ + +/** + * Establish a buffer for selection mode values. + * + * \param size buffer size. + * \param buffer buffer. + * + * \sa glSelectBuffer(). + * + * \note this function can't be put in a display list. + * + * Verifies we're not in selection mode, flushes the vertices and initialize + * the fields in __GLcontextRec::Select with the given buffer. + */ +void GLAPIENTRY +_mesa_SelectBuffer( GLsizei size, GLuint *buffer ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->RenderMode==GL_SELECT) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" ); + return; /* KW: added return */ + } + + FLUSH_VERTICES(ctx, _NEW_RENDERMODE); + ctx->Select.Buffer = buffer; + ctx->Select.BufferSize = size; + ctx->Select.BufferCount = 0; + ctx->Select.HitFlag = GL_FALSE; + ctx->Select.HitMinZ = 1.0; + ctx->Select.HitMaxZ = 0.0; +} + + +/** + * Write a value of a record into the selection buffer. + * + * \param CTX GL context. + * \param V value. + * + * Verifies there is free space in the buffer to write the value and + * increments the pointer. + */ +#define WRITE_RECORD( CTX, V ) \ + if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \ + CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \ + } \ + CTX->Select.BufferCount++; + + +/** + * Update the hit flag and the maximum and minimum depth values. + * + * \param ctx GL context. + * \param z depth. + * + * Sets gl_selection::HitFlag and updates gl_selection::HitMinZ and + * gl_selection::HitMaxZ. + */ +void _mesa_update_hitflag( GLcontext *ctx, GLfloat z ) +{ + ctx->Select.HitFlag = GL_TRUE; + if (z < ctx->Select.HitMinZ) { + ctx->Select.HitMinZ = z; + } + if (z > ctx->Select.HitMaxZ) { + ctx->Select.HitMaxZ = z; + } +} + + +/** + * Write the hit record. + * + * \param ctx GL context. + * + * Write the hit record, i.e., the number of names in the stack, the minimum and + * maximum depth values and the number of names in the name stack at the time + * of the event. Resets the hit flag. + * + * \sa gl_selection. + */ +static void write_hit_record( GLcontext *ctx ) +{ + GLuint i; + GLuint zmin, zmax, zscale = (~0u); + + /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */ + /* 2^32-1 and round to nearest unsigned integer. */ + + assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */ + zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ); + zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ); + + WRITE_RECORD( ctx, ctx->Select.NameStackDepth ); + WRITE_RECORD( ctx, zmin ); + WRITE_RECORD( ctx, zmax ); + for (i = 0; i < ctx->Select.NameStackDepth; i++) { + WRITE_RECORD( ctx, ctx->Select.NameStack[i] ); + } + + ctx->Select.Hits++; + ctx->Select.HitFlag = GL_FALSE; + ctx->Select.HitMinZ = 1.0; + ctx->Select.HitMaxZ = -1.0; +} + + +/** + * Initialize the name stack. + * + * Verifies we are in select mode and resets the name stack depth and resets + * the hit record data in gl_selection. Marks new render mode in + * __GLcontextRec::NewState. + */ +void GLAPIENTRY +_mesa_InitNames( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + /* Record the hit before the HitFlag is wiped out again. */ + if (ctx->RenderMode == GL_SELECT) { + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + } + ctx->Select.NameStackDepth = 0; + ctx->Select.HitFlag = GL_FALSE; + ctx->Select.HitMinZ = 1.0; + ctx->Select.HitMaxZ = 0.0; + ctx->NewState |= _NEW_RENDERMODE; +} + + +/** + * Load the top-most name of the name stack. + * + * \param name name. + * + * Verifies we are in selection mode and that the name stack is not empty. + * Flushes vertices. If there is a hit flag writes it (via write_hit_record()), + * and replace the top-most name in the stack. + * + * sa __GLcontextRec::Select. + */ +void GLAPIENTRY +_mesa_LoadName( GLuint name ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->RenderMode != GL_SELECT) { + return; + } + if (ctx->Select.NameStackDepth == 0) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glLoadName" ); + return; + } + + FLUSH_VERTICES(ctx, _NEW_RENDERMODE); + + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.NameStackDepth < MAX_NAME_STACK_DEPTH) { + ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name; + } + else { + ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name; + } +} + + +/** + * Push a name into the name stack. + * + * \param name name. + * + * Verifies we are in selection mode and that the name stack is not full. + * Flushes vertices. If there is a hit flag writes it (via write_hit_record()), + * and adds the name to the top of the name stack. + * + * sa __GLcontextRec::Select. + */ +void GLAPIENTRY +_mesa_PushName( GLuint name ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->RenderMode != GL_SELECT) { + return; + } + + FLUSH_VERTICES(ctx, _NEW_RENDERMODE); + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.NameStackDepth >= MAX_NAME_STACK_DEPTH) { + _mesa_error( ctx, GL_STACK_OVERFLOW, "glPushName" ); + } + else + ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name; +} + + +/** + * Pop a name into the name stack. + * + * Verifies we are in selection mode and that the name stack is not empty. + * Flushes vertices. If there is a hit flag writes it (via write_hit_record()), + * and removes top-most name in the name stack. + * + * sa __GLcontextRec::Select. + */ +void GLAPIENTRY +_mesa_PopName( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->RenderMode != GL_SELECT) { + return; + } + + FLUSH_VERTICES(ctx, _NEW_RENDERMODE); + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.NameStackDepth == 0) { + _mesa_error( ctx, GL_STACK_UNDERFLOW, "glPopName" ); + } + else + ctx->Select.NameStackDepth--; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Render Mode */ +/*@{*/ + +/** + * Set rasterization mode. + * + * \param mode rasterization mode. + * + * \note this function can't be put in a display list. + * + * \sa glRenderMode(). + * + * Flushes the vertices and do the necessary cleanup according to the previous + * rasterization mode, such as writing the hit record or resent the select + * buffer index when exiting the select mode. Updates + * __GLcontextRec::RenderMode and notifies the driver via the + * dd_function_table::RenderMode callback. + */ +GLint GLAPIENTRY +_mesa_RenderMode( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint result; + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glRenderMode %s\n", _mesa_lookup_enum_by_nr(mode)); + + FLUSH_VERTICES(ctx, _NEW_RENDERMODE); + + switch (ctx->RenderMode) { + case GL_RENDER: + result = 0; + break; + case GL_SELECT: + if (ctx->Select.HitFlag) { + write_hit_record( ctx ); + } + if (ctx->Select.BufferCount > ctx->Select.BufferSize) { + /* overflow */ +#ifdef DEBUG + _mesa_warning(ctx, "Feedback buffer overflow"); +#endif + result = -1; + } + else { + result = ctx->Select.Hits; + } + ctx->Select.BufferCount = 0; + ctx->Select.Hits = 0; + ctx->Select.NameStackDepth = 0; + break; +#if _HAVE_FULL_GL + case GL_FEEDBACK: + if (ctx->Feedback.Count > ctx->Feedback.BufferSize) { + /* overflow */ + result = -1; + } + else { + result = ctx->Feedback.Count; + } + ctx->Feedback.Count = 0; + break; +#endif + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" ); + return 0; + } + + switch (mode) { + case GL_RENDER: + break; + case GL_SELECT: + if (ctx->Select.BufferSize==0) { + /* haven't called glSelectBuffer yet */ + _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" ); + } + break; +#if _HAVE_FULL_GL + case GL_FEEDBACK: + if (ctx->Feedback.BufferSize==0) { + /* haven't called glFeedbackBuffer yet */ + _mesa_error( ctx, GL_INVALID_OPERATION, "glRenderMode" ); + } + break; +#endif + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glRenderMode" ); + return 0; + } + + ctx->RenderMode = mode; + if (ctx->Driver.RenderMode) + ctx->Driver.RenderMode( ctx, mode ); + + return result; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Initialization */ +/*@{*/ + +/** + * Initialize context feedback data. + */ +void _mesa_init_feedback( GLcontext * ctx ) +{ + /* Feedback */ + ctx->Feedback.Type = GL_2D; /* TODO: verify */ + ctx->Feedback.Buffer = NULL; + ctx->Feedback.BufferSize = 0; + ctx->Feedback.Count = 0; + + /* Selection/picking */ + ctx->Select.Buffer = NULL; + ctx->Select.BufferSize = 0; + ctx->Select.BufferCount = 0; + ctx->Select.Hits = 0; + ctx->Select.NameStackDepth = 0; + + /* Miscellaneous */ + ctx->RenderMode = GL_RENDER; +} + +/*@}*/ diff --git a/src/mesa/main/feedback.h b/src/mesa/main/feedback.h new file mode 100644 index 00000000000..6c448ad631b --- /dev/null +++ b/src/mesa/main/feedback.h @@ -0,0 +1,82 @@ +/** + * \file feedback.h + * Selection and feedback modes functions. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef FEEDBACK_H +#define FEEDBACK_H + + +#include "mtypes.h" + + +#define FEEDBACK_TOKEN( CTX, T ) \ + if (CTX->Feedback.Count < CTX->Feedback.BufferSize) { \ + CTX->Feedback.Buffer[CTX->Feedback.Count] = (GLfloat) (T); \ + } \ + CTX->Feedback.Count++; + + +extern void _mesa_init_feedback( GLcontext * ctx ); + +extern void _mesa_feedback_vertex( GLcontext *ctx, + const GLfloat win[4], + const GLfloat color[4], + GLfloat index, + const GLfloat texcoord[4] ); + + +extern void _mesa_update_hitflag( GLcontext *ctx, GLfloat z ); + + +extern void GLAPIENTRY +_mesa_PassThrough( GLfloat token ); + +extern void GLAPIENTRY +_mesa_FeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer ); + +extern void GLAPIENTRY +_mesa_SelectBuffer( GLsizei size, GLuint *buffer ); + +extern void GLAPIENTRY +_mesa_InitNames( void ); + +extern void GLAPIENTRY +_mesa_LoadName( GLuint name ); + +extern void GLAPIENTRY +_mesa_PushName( GLuint name ); + +extern void GLAPIENTRY +_mesa_PopName( void ); + +extern GLint GLAPIENTRY +_mesa_RenderMode( GLenum mode ); + + +#endif diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c new file mode 100644 index 00000000000..d3b8a923aae --- /dev/null +++ b/src/mesa/main/fog.c @@ -0,0 +1,177 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "fog.h" +#include "mtypes.h" + + + +void GLAPIENTRY +_mesa_Fogf(GLenum pname, GLfloat param) +{ + _mesa_Fogfv(pname, ¶m); +} + + +void GLAPIENTRY +_mesa_Fogi(GLenum pname, GLint param ) +{ + GLfloat fparam = (GLfloat) param; + _mesa_Fogfv(pname, &fparam); +} + + +void GLAPIENTRY +_mesa_Fogiv(GLenum pname, const GLint *params ) +{ + GLfloat p[4]; + switch (pname) { + case GL_FOG_MODE: + case GL_FOG_DENSITY: + case GL_FOG_START: + case GL_FOG_END: + case GL_FOG_INDEX: + case GL_FOG_COORDINATE_SOURCE_EXT: + p[0] = (GLfloat) *params; + break; + case GL_FOG_COLOR: + p[0] = INT_TO_FLOAT( params[0] ); + p[1] = INT_TO_FLOAT( params[1] ); + p[2] = INT_TO_FLOAT( params[2] ); + p[3] = INT_TO_FLOAT( params[3] ); + break; + default: + /* Error will be caught later in _mesa_Fogfv */ + ; + } + _mesa_Fogfv(pname, p); +} + + +void GLAPIENTRY +_mesa_Fogfv( GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLenum m; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (pname) { + case GL_FOG_MODE: + m = (GLenum) (GLint) *params; + switch (m) { + case GL_LINEAR: + case GL_EXP: + case GL_EXP2: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glFog" ); + return; + } + if (ctx->Fog.Mode == m) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.Mode = m; + break; + case GL_FOG_DENSITY: + if (*params<0.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glFog" ); + return; + } + if (ctx->Fog.Density == *params) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.Density = *params; + break; + case GL_FOG_START: + if (ctx->Fog.Start == *params) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.Start = *params; + break; + case GL_FOG_END: + if (ctx->Fog.End == *params) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.End = *params; + break; + case GL_FOG_INDEX: + if (ctx->Fog.Index == *params) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.Index = *params; + break; + case GL_FOG_COLOR: + if (TEST_EQ_4V(ctx->Fog.Color, params)) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.Color[0] = CLAMP(params[0], 0.0F, 1.0F); + ctx->Fog.Color[1] = CLAMP(params[1], 0.0F, 1.0F); + ctx->Fog.Color[2] = CLAMP(params[2], 0.0F, 1.0F); + ctx->Fog.Color[3] = CLAMP(params[3], 0.0F, 1.0F); + break; + case GL_FOG_COORDINATE_SOURCE_EXT: { + GLenum p = (GLenum) (GLint) *params; + if (!ctx->Extensions.EXT_fog_coord || + (p != GL_FOG_COORDINATE_EXT && p != GL_FRAGMENT_DEPTH_EXT)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glFog"); + return; + } + if (ctx->Fog.FogCoordinateSource == p) + return; + FLUSH_VERTICES(ctx, _NEW_FOG); + ctx->Fog.FogCoordinateSource = p; + break; + } + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glFog" ); + return; + } + + if (ctx->Driver.Fogfv) { + (*ctx->Driver.Fogfv)( ctx, pname, params ); + } +} + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +void _mesa_init_fog( GLcontext * ctx ) +{ + /* Fog group */ + ctx->Fog.Enabled = GL_FALSE; + ctx->Fog.Mode = GL_EXP; + ASSIGN_4V( ctx->Fog.Color, 0.0, 0.0, 0.0, 0.0 ); + ctx->Fog.Index = 0.0; + ctx->Fog.Density = 1.0; + ctx->Fog.Start = 0.0; + ctx->Fog.End = 1.0; + ctx->Fog.ColorSumEnabled = GL_FALSE; + ctx->Fog.FogCoordinateSource = GL_FRAGMENT_DEPTH_EXT; +} diff --git a/src/mesa/main/fog.h b/src/mesa/main/fog.h new file mode 100644 index 00000000000..a14d19cdb39 --- /dev/null +++ b/src/mesa/main/fog.h @@ -0,0 +1,66 @@ +/** + * \file fog.h + * Fog operations. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef FOG_H +#define FOG_H + + +#include "mtypes.h" + + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_Fogf(GLenum pname, GLfloat param); + +extern void GLAPIENTRY +_mesa_Fogi(GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_Fogfv(GLenum pname, const GLfloat *params ); + +extern void GLAPIENTRY +_mesa_Fogiv(GLenum pname, const GLint *params ); + +extern void _mesa_init_fog( GLcontext * ctx ); + +#else + +/** No-op */ +#define _mesa_init_fog( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/framebuffer.c b/src/mesa/main/framebuffer.c new file mode 100644 index 00000000000..c3c9ca5ed2a --- /dev/null +++ b/src/mesa/main/framebuffer.c @@ -0,0 +1,527 @@ +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * Functions for allocating/managing framebuffers and renderbuffers. + * Also, routines for reading/writing renderbuffer data as ubytes, + * ushorts, uints, etc. + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "mtypes.h" +#include "fbobject.h" +#include "framebuffer.h" +#include "renderbuffer.h" + + + +/** + * Compute/set the _DepthMax field for the given framebuffer. + * This value depends on the Z buffer resolution. + */ +static void +compute_depth_max(struct gl_framebuffer *fb) +{ + if (fb->Visual.depthBits == 0) { + /* Special case. Even if we don't have a depth buffer we need + * good values for DepthMax for Z vertex transformation purposes + * and for per-fragment fog computation. + */ + fb->_DepthMax = (1 << 16) - 1; + } + else if (fb->Visual.depthBits < 32) { + fb->_DepthMax = (1 << fb->Visual.depthBits) - 1; + } + else { + /* Special case since shift values greater than or equal to the + * number of bits in the left hand expression's type are undefined. + */ + fb->_DepthMax = 0xffffffff; + } + fb->_DepthMaxF = (GLfloat) fb->_DepthMax; + fb->_MRD = 1.0; /* Minimum resolvable depth value, for polygon offset */ +} + + +/** + * Create and initialize a gl_framebuffer object. + * This is intended for creating _window_system_ framebuffers, not generic + * framebuffer objects ala GL_EXT_framebuffer_object. + * + * \sa _mesa_new_framebuffer + */ +struct gl_framebuffer * +_mesa_create_framebuffer(const GLvisual *visual) +{ + struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); + assert(visual); + if (fb) { + _mesa_initialize_framebuffer(fb, visual); + } + return fb; +} + + +/** + * Allocate a new gl_framebuffer object. + * This is the default function for ctx->Driver.NewFramebuffer(). + * This is for allocating user-created framebuffers, not window-system + * framebuffers! + * \sa _mesa_create_framebuffer + */ +struct gl_framebuffer * +_mesa_new_framebuffer(GLcontext *ctx, GLuint name) +{ + struct gl_framebuffer *fb; + assert(name != 0); + fb = CALLOC_STRUCT(gl_framebuffer); + if (fb) { + fb->Name = name; + fb->RefCount = 1; + fb->Delete = _mesa_destroy_framebuffer; + fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT; + fb->_ColorDrawBufferMask[0] = BUFFER_BIT_COLOR0; + fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; + fb->_ColorReadBufferMask = BUFFER_BIT_COLOR0; + fb->Delete = _mesa_destroy_framebuffer; + } + return fb; +} + + +/** + * Initialize a gl_framebuffer object. + * \sa _mesa_create_framebuffer + */ +void +_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual) +{ + assert(fb); + assert(visual); + + _mesa_bzero(fb, sizeof(struct gl_framebuffer)); + + /* save the visual */ + fb->Visual = *visual; + + /* Init glRead/DrawBuffer state */ + if (visual->doubleBufferMode) { + fb->ColorDrawBuffer[0] = GL_BACK; + fb->_ColorDrawBufferMask[0] = BUFFER_BIT_BACK_LEFT; + fb->ColorReadBuffer = GL_BACK; + fb->_ColorReadBufferMask = BUFFER_BIT_BACK_LEFT; + } + else { + fb->ColorDrawBuffer[0] = GL_FRONT; + fb->_ColorDrawBufferMask[0] = BUFFER_BIT_FRONT_LEFT; + fb->ColorReadBuffer = GL_FRONT; + fb->_ColorReadBufferMask = BUFFER_BIT_FRONT_LEFT; + } + + fb->Delete = _mesa_destroy_framebuffer; + fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + + compute_depth_max(fb); +} + + +/** + * Create/attach software-based renderbuffers to the given framebuffer. + * This is a helper routine for device drivers. Drivers can just as well + * call the individual _mesa_add_*_renderbuffer() routines directly. + */ +void +_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb, + GLboolean color, + GLboolean depth, + GLboolean stencil, + GLboolean accum, + GLboolean alpha, + GLboolean aux) +{ + GLboolean frontLeft = GL_TRUE; + GLboolean backLeft = fb->Visual.doubleBufferMode; + GLboolean frontRight = fb->Visual.stereoMode; + GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode; + + if (color) { + if (fb->Visual.rgbMode) { + assert(fb->Visual.redBits == fb->Visual.greenBits); + assert(fb->Visual.redBits == fb->Visual.blueBits); + _mesa_add_color_renderbuffers(NULL, fb, + fb->Visual.redBits, + fb->Visual.alphaBits, + frontLeft, backLeft, + frontRight, backRight); + } + else { + _mesa_add_color_index_renderbuffers(NULL, fb, + fb->Visual.indexBits, + frontLeft, backLeft, + frontRight, backRight); + } + } + + if (depth) { + assert(fb->Visual.depthBits > 0); + _mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits); + } + + if (stencil) { + assert(fb->Visual.stencilBits > 0); + _mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits); + } + + if (accum) { + assert(fb->Visual.rgbMode); + assert(fb->Visual.accumRedBits > 0); + assert(fb->Visual.accumGreenBits > 0); + assert(fb->Visual.accumBlueBits > 0); + _mesa_add_accum_renderbuffer(NULL, fb, + fb->Visual.accumRedBits, + fb->Visual.accumGreenBits, + fb->Visual.accumBlueBits, + fb->Visual.accumAlphaBits); + } + + if (aux) { + assert(fb->Visual.rgbMode); + assert(fb->Visual.numAuxBuffers > 0); + _mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits, + fb->Visual.numAuxBuffers); + } + +#if 1 + if (alpha) { + assert(fb->Visual.rgbMode); + assert(fb->Visual.alphaBits > 0); + _mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits, + frontLeft, backLeft, + frontRight, backRight); + } +#endif + +#if 0 + if (multisample) { + /* maybe someday */ + } +#endif +} + + +/** + * Deallocate buffer and everything attached to it. + */ +void +_mesa_destroy_framebuffer(struct gl_framebuffer *buffer) +{ + if (buffer) { + _mesa_free_framebuffer_data(buffer); + FREE(buffer); + } +} + + +/** + * Free all the data hanging off the given gl_framebuffer, but don't free + * the gl_framebuffer object itself. + */ +void +_mesa_free_framebuffer_data(struct gl_framebuffer *fb) +{ + GLuint i; + + assert(fb); + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { + struct gl_renderbuffer *rb = att->Renderbuffer; + rb->RefCount--; + if (rb->RefCount == 0) { + rb->Delete(rb); + } + } + att->Type = GL_NONE; + att->Renderbuffer = NULL; + } +} + + +/** + * Resize the given framebuffer's renderbuffers to the new width and height. + * This should only be used for window-system framebuffers, not + * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object). + * This will typically be called via ctx->Driver.ResizeBuffers() + */ +void +_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint width, GLuint height) +{ + GLuint i; + + /* For window system framebuffers, Name is zero */ + assert(fb->Name == 0); + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { + struct gl_renderbuffer *rb = att->Renderbuffer; + /* only resize if size is changing */ + if (rb->Width != width || rb->Height != height) { + if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { + rb->Width = width; + rb->Height = height; + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + } + } + } + } + + fb->Width = width; + fb->Height = height; + + /* to update scissor / window bounds */ + ctx->NewState |= _NEW_BUFFERS; +} + + +/** + * Examine all the framebuffer's renderbuffers to update the Width/Height + * fields of the framebuffer. If we have renderbuffers with different + * sizes, set the framebuffer's width and height to zero. + * Note: this is only intended for user-created framebuffers, not + * window-system framebuffes. + */ +static void +update_framebuffer_size(struct gl_framebuffer *fb) +{ + GLboolean haveSize = GL_FALSE; + GLuint i; + + /* user-created framebuffers only */ + assert(fb->Name); + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + const struct gl_renderbuffer *rb = att->Renderbuffer; + if (rb) { + if (haveSize) { + if (rb->Width != fb->Width && rb->Height != fb->Height) { + /* size mismatch! */ + fb->Width = 0; + fb->Height = 0; + return; + } + } + else { + fb->Width = rb->Width; + fb->Height = rb->Height; + haveSize = GL_TRUE; + } + } + } +} + + +/** + * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields. + * These values are computed from the buffer's width and height and + * the scissor box, if it's enabled. + * \param ctx the GL context. + */ +void +_mesa_update_draw_buffer_bounds(GLcontext *ctx) +{ + struct gl_framebuffer *buffer = ctx->DrawBuffer; + + if (buffer->Name) { + /* user-created framebuffer size depends on the renderbuffers */ + update_framebuffer_size(buffer); + } + + buffer->_Xmin = 0; + buffer->_Ymin = 0; + buffer->_Xmax = buffer->Width; + buffer->_Ymax = buffer->Height; + + if (ctx->Scissor.Enabled) { + if (ctx->Scissor.X > buffer->_Xmin) { + buffer->_Xmin = ctx->Scissor.X; + } + if (ctx->Scissor.Y > buffer->_Ymin) { + buffer->_Ymin = ctx->Scissor.Y; + } + if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) { + buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width; + } + if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) { + buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height; + } + /* finally, check for empty region */ + if (buffer->_Xmin > buffer->_Xmax) { + buffer->_Xmin = buffer->_Xmax; + } + if (buffer->_Ymin > buffer->_Ymax) { + buffer->_Ymin = buffer->_Ymax; + } + } + + ASSERT(buffer->_Xmin <= buffer->_Xmax); + ASSERT(buffer->_Ymin <= buffer->_Ymax); +} + + +/** + * The glGet queries of the framebuffer red/green/blue size, stencil size, + * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can + * change depending on the renderbuffer bindings. This function update's + * the given framebuffer's Visual from the current renderbuffer bindings. + * This is only intended for user-created framebuffers. + */ +void +_mesa_update_framebuffer_visual(struct gl_framebuffer *fb) +{ + GLuint i; + + assert(fb->Name != 0); + + _mesa_bzero(&fb->Visual, sizeof(fb->Visual)); + fb->Visual.rgbMode = GL_TRUE; + + /* find first RGB or CI renderbuffer */ + for (i = 0; i < BUFFER_COUNT; i++) { + if (fb->Attachment[i].Renderbuffer) { + const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; + if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) { + fb->Visual.redBits = rb->ComponentSizes[0]; + fb->Visual.greenBits = rb->ComponentSizes[1]; + fb->Visual.blueBits = rb->ComponentSizes[2]; + fb->Visual.alphaBits = rb->ComponentSizes[3]; + fb->Visual.floatMode = GL_FALSE; + break; + } + else if (rb->_BaseFormat == GL_COLOR_INDEX) { + fb->Visual.indexBits = rb->ComponentSizes[0]; + fb->Visual.rgbMode = GL_FALSE; + break; + } + } + } + + if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { + fb->Visual.haveDepthBuffer = GL_TRUE; + fb->Visual.depthBits + = fb->Attachment[BUFFER_DEPTH].Renderbuffer->ComponentSizes[0]; + } + + if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { + fb->Visual.haveStencilBuffer = GL_TRUE; + fb->Visual.stencilBits + = fb->Attachment[BUFFER_STENCIL].Renderbuffer->ComponentSizes[0]; + } + + compute_depth_max(fb); +} + + +/** + * Given a framebuffer and a buffer bit (like BUFFER_BIT_FRONT_LEFT), return + * the corresponding renderbuffer. + */ +static struct gl_renderbuffer * +get_renderbuffer(struct gl_framebuffer *fb, GLuint bufferBit) +{ + GLuint index; + for (index = 0; index < BUFFER_COUNT; index++) { + if ((1 << index) == bufferBit) { + return fb->Attachment[index].Renderbuffer; + } + } + _mesa_problem(NULL, "Bad bufferBit in get_renderbuffer"); + return NULL; +} + + +/** + * Update state related to the current draw/read framebuffers. + * If the current framebuffer is user-created, make sure it's complete. + */ +void +_mesa_update_framebuffer(GLcontext *ctx) +{ + struct gl_framebuffer *fb = ctx->DrawBuffer; + GLuint output; + + /* Completeness only matters for user-created framebuffers */ + if (fb->Name != 0) { + _mesa_test_framebuffer_completeness(ctx, fb); + _mesa_update_framebuffer_visual(fb); + } + + /* + * Update the list of drawing renderbuffer pointers. + * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers + * writing colors. We have a loop because glDrawBuffer(GL_FRONT_AND_BACK) + * can specify writing to two or four color buffers. + */ + for (output = 0; output < ctx->Const.MaxDrawBuffers; output++) { + GLuint bufferMask = fb->_ColorDrawBufferMask[output]; + GLuint count = 0; + GLuint bufferBit; + /* for each bit that's set in the bufferMask... */ + for (bufferBit = 1; bufferMask; bufferBit <<= 1) { + if (bufferBit & bufferMask) { + struct gl_renderbuffer *rb = get_renderbuffer(fb, bufferBit); + if (rb) { + fb->_ColorDrawBuffers[output][count] = rb; + fb->_ColorDrawBit[output][count] = bufferBit; + count++; + } + else { + /*_mesa_warning(ctx, "DrawBuffer names a missing buffer!");*/ + } + bufferMask &= ~bufferBit; + } + } + fb->_NumColorDrawBuffers[output] = count; + } + + /* + * Update the read renderbuffer pointer. + * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. + */ + if (fb->_ColorReadBufferMask == 0x0) + fb->_ColorReadBuffer = NULL; /* legal! */ + else + fb->_ColorReadBuffer = get_renderbuffer(fb, fb->_ColorReadBufferMask); + + compute_depth_max(fb); +} diff --git a/src/mesa/main/framebuffer.h b/src/mesa/main/framebuffer.h new file mode 100644 index 00000000000..11b002877c9 --- /dev/null +++ b/src/mesa/main/framebuffer.h @@ -0,0 +1,67 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef FRAMEBUFFER_H +#define FRAMEBUFFER_H + + +extern struct gl_framebuffer * +_mesa_create_framebuffer(const GLvisual *visual); + +extern struct gl_framebuffer * +_mesa_new_framebuffer(GLcontext *ctx, GLuint name); + +extern void +_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual); + +extern void +_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb, + GLboolean color, + GLboolean depth, + GLboolean stencil, + GLboolean accum, + GLboolean alpha, + GLboolean aux); + +extern void +_mesa_destroy_framebuffer(struct gl_framebuffer *buffer); + +extern void +_mesa_free_framebuffer_data(struct gl_framebuffer *buffer); + +extern void +_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *b, + GLuint width, GLuint height); + +extern void +_mesa_update_draw_buffer_bounds(GLcontext *ctx); + +extern void +_mesa_update_framebuffer_visual(struct gl_framebuffer *fb); + +extern void +_mesa_update_framebuffer(GLcontext *ctx); + +#endif /* FRAMEBUFFER_H */ diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c new file mode 100644 index 00000000000..f5b98196746 --- /dev/null +++ b/src/mesa/main/get.c @@ -0,0 +1,5646 @@ + +/*** + *** NOTE!!! DO NOT EDIT THIS FILE!!! IT IS GENERATED BY get_gen.py + ***/ + +#include "glheader.h" +#include "context.h" +#include "enable.h" +#include "extensions.h" +#include "fbobject.h" +#include "get.h" +#include "macros.h" +#include "mtypes.h" +#include "state.h" +#include "texcompress.h" + + +#define FLOAT_TO_BOOLEAN(X) ( (X) ? GL_TRUE : GL_FALSE ) + +#define INT_TO_BOOLEAN(I) ( (I) ? GL_TRUE : GL_FALSE ) + +#define ENUM_TO_BOOLEAN(E) ( (E) ? GL_TRUE : GL_FALSE ) +#define ENUM_TO_INT(E) ( (GLint) (E) ) +#define ENUM_TO_FLOAT(E) ( (GLfloat) (E) ) + +#define BOOLEAN_TO_INT(B) ( (GLint) (B) ) +#define BOOLEAN_TO_FLOAT(B) ( (B) ? 1.0F : 0.0F ) + + +/* Check if named extension is enabled, if not generate error and return */ + +#define CHECK1(E1, str, PNAME) \ + if (!ctx->Extensions.E1) { \ + _mesa_error(ctx, GL_INVALID_VALUE, \ + "glGet" str "v(0x%x)", (int) PNAME); \ + return; \ + } + +#define CHECK2(E1, E2, str, PNAME) \ + if (!ctx->Extensions.E1 && !ctx->Extensions.E2) { \ + _mesa_error(ctx, GL_INVALID_VALUE, \ + "glGet" str "v(0x%x)", (int) PNAME); \ + return; \ + } + +#define CHECK_EXTENSION_B(EXTNAME, PNAME) \ + CHECK1(EXTNAME, "Boolean", PNAME ) + +#define CHECK_EXTENSION_I(EXTNAME, PNAME) \ + CHECK1(EXTNAME, "Integer", PNAME ) + +#define CHECK_EXTENSION_F(EXTNAME, PNAME) \ + CHECK1(EXTNAME, "Float", PNAME ) + + +/** + * Helper routine. + */ +static GLenum +pixel_texgen_mode(const GLcontext *ctx) +{ + if (ctx->Pixel.FragmentRgbSource == GL_CURRENT_RASTER_POSITION) { + if (ctx->Pixel.FragmentAlphaSource == GL_CURRENT_RASTER_POSITION) { + return GL_RGBA; + } + else { + return GL_RGB; + } + } + else { + if (ctx->Pixel.FragmentAlphaSource == GL_CURRENT_RASTER_POSITION) { + return GL_ALPHA; + } + else { + return GL_NONE; + } + } +} + +void GLAPIENTRY +_mesa_GetBooleanv( GLenum pname, GLboolean *params ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!params) + return; + + if (ctx->NewState) + _mesa_update_state(ctx); + + if (ctx->Driver.GetBooleanv && + ctx->Driver.GetBooleanv(ctx, pname, params)) + return; + + switch (pname) { + case GL_ACCUM_RED_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumRedBits); + break; + case GL_ACCUM_GREEN_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumGreenBits); + break; + case GL_ACCUM_BLUE_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumBlueBits); + break; + case GL_ACCUM_ALPHA_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.accumAlphaBits); + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Accum.ClearColor[3]); + break; + case GL_ALPHA_BIAS: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.AlphaBias); + break; + case GL_ALPHA_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.alphaBits); + break; + case GL_ALPHA_SCALE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.AlphaScale); + break; + case GL_ALPHA_TEST: + params[0] = ctx->Color.AlphaEnabled; + break; + case GL_ALPHA_TEST_FUNC: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.AlphaFunc); + break; + case GL_ALPHA_TEST_REF: + params[0] = FLOAT_TO_BOOLEAN(ctx->Color.AlphaRef); + break; + case GL_ATTRIB_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(ctx->AttribStackDepth); + break; + case GL_AUTO_NORMAL: + params[0] = ctx->Eval.AutoNormal; + break; + case GL_AUX_BUFFERS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.numAuxBuffers); + break; + case GL_BLEND: + params[0] = ctx->Color.BlendEnabled; + break; + case GL_BLEND_DST: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_SRC_RGB_EXT: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_DST_RGB_EXT: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC_ALPHA_EXT: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendSrcA); + break; + case GL_BLEND_DST_ALPHA_EXT: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendDstA); + break; + case GL_BLEND_EQUATION: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendEquationRGB ); + break; + case GL_BLEND_EQUATION_ALPHA_EXT: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.BlendEquationA ); + break; + case GL_BLEND_COLOR_EXT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Color.BlendColor[3]); + break; + case GL_BLUE_BIAS: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.BlueBias); + break; + case GL_BLUE_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.blueBits); + break; + case GL_BLUE_SCALE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.BlueScale); + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(ctx->ClientAttribStackDepth); + break; + case GL_CLIP_PLANE0: + params[0] = (ctx->Transform.ClipPlanesEnabled >> 0) & 1; + break; + case GL_CLIP_PLANE1: + params[0] = (ctx->Transform.ClipPlanesEnabled >> 1) & 1; + break; + case GL_CLIP_PLANE2: + params[0] = (ctx->Transform.ClipPlanesEnabled >> 2) & 1; + break; + case GL_CLIP_PLANE3: + params[0] = (ctx->Transform.ClipPlanesEnabled >> 3) & 1; + break; + case GL_CLIP_PLANE4: + params[0] = (ctx->Transform.ClipPlanesEnabled >> 4) & 1; + break; + case GL_CLIP_PLANE5: + params[0] = (ctx->Transform.ClipPlanesEnabled >> 5) & 1; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Color.ClearColor[3]); + break; + case GL_COLOR_MATERIAL: + params[0] = ctx->Light.ColorMaterialEnabled; + break; + case GL_COLOR_MATERIAL_FACE: + params[0] = ENUM_TO_BOOLEAN(ctx->Light.ColorMaterialFace); + break; + case GL_COLOR_MATERIAL_PARAMETER: + params[0] = ENUM_TO_BOOLEAN(ctx->Light.ColorMaterialMode); + break; + case GL_COLOR_WRITEMASK: + params[0] = INT_TO_BOOLEAN(ctx->Color.ColorMask[RCOMP] ? 1 : 0); + params[1] = INT_TO_BOOLEAN(ctx->Color.ColorMask[GCOMP] ? 1 : 0); + params[2] = INT_TO_BOOLEAN(ctx->Color.ColorMask[BCOMP] ? 1 : 0); + params[3] = INT_TO_BOOLEAN(ctx->Color.ColorMask[ACOMP] ? 1 : 0); + break; + case GL_CULL_FACE: + params[0] = ctx->Polygon.CullFlag; + break; + case GL_CULL_FACE_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->Polygon.CullFaceMode); + break; + case GL_CURRENT_COLOR: + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]); + } + break; + case GL_CURRENT_INDEX: + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Index); + } + break; + case GL_CURRENT_NORMAL: + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]); + } + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterColor[3]); + break; + case GL_CURRENT_RASTER_DISTANCE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterDistance); + break; + case GL_CURRENT_RASTER_INDEX: + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterIndex); + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterPos[3]); + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + { + const GLuint texUnit = ctx->Texture.CurrentUnit; + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Current.RasterTexCoords[texUnit][3]); + } + break; + case GL_CURRENT_RASTER_POSITION_VALID: + params[0] = ctx->Current.RasterPosValid; + break; + case GL_CURRENT_TEXTURE_COORDS: + { + const GLuint texUnit = ctx->Texture.CurrentUnit; + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]); + } + break; + case GL_DEPTH_BIAS: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.DepthBias); + break; + case GL_DEPTH_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.depthBits); + break; + case GL_DEPTH_CLEAR_VALUE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Depth.Clear); + break; + case GL_DEPTH_FUNC: + params[0] = ENUM_TO_BOOLEAN(ctx->Depth.Func); + break; + case GL_DEPTH_RANGE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Viewport.Near); + params[1] = FLOAT_TO_BOOLEAN(ctx->Viewport.Far); + break; + case GL_DEPTH_SCALE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.DepthScale); + break; + case GL_DEPTH_TEST: + params[0] = ctx->Depth.Test; + break; + case GL_DEPTH_WRITEMASK: + params[0] = ctx->Depth.Mask; + break; + case GL_DITHER: + params[0] = ctx->Color.DitherFlag; + break; + case GL_DOUBLEBUFFER: + params[0] = ctx->DrawBuffer->Visual.doubleBufferMode; + break; + case GL_DRAW_BUFFER: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.DrawBuffer[0]); + break; + case GL_EDGE_FLAG: + { + FLUSH_CURRENT(ctx, 0); + params[0] = ctx->Current.EdgeFlag; + } + break; + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Feedback.BufferSize); + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = ENUM_TO_BOOLEAN(ctx->Feedback.Type); + break; + case GL_FOG: + params[0] = ctx->Fog.Enabled; + break; + case GL_FOG_COLOR: + params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Fog.Color[3]); + break; + case GL_FOG_DENSITY: + params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Density); + break; + case GL_FOG_END: + params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.End); + break; + case GL_FOG_HINT: + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.Fog); + break; + case GL_FOG_INDEX: + params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Index); + break; + case GL_FOG_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->Fog.Mode); + break; + case GL_FOG_START: + params[0] = FLOAT_TO_BOOLEAN(ctx->Fog.Start); + break; + case GL_FRONT_FACE: + params[0] = ENUM_TO_BOOLEAN(ctx->Polygon.FrontFace); + break; + case GL_GREEN_BIAS: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.GreenBias); + break; + case GL_GREEN_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.greenBits); + break; + case GL_GREEN_SCALE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.GreenScale); + break; + case GL_INDEX_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.indexBits); + break; + case GL_INDEX_CLEAR_VALUE: + params[0] = INT_TO_BOOLEAN(ctx->Color.ClearIndex); + break; + case GL_INDEX_MODE: + params[0] = !ctx->DrawBuffer->Visual.rgbMode; + break; + case GL_INDEX_OFFSET: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.IndexOffset); + break; + case GL_INDEX_SHIFT: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.IndexShift); + break; + case GL_INDEX_WRITEMASK: + params[0] = INT_TO_BOOLEAN(ctx->Color.IndexMask); + break; + case GL_LIGHT0: + params[0] = ctx->Light.Light[0].Enabled; + break; + case GL_LIGHT1: + params[0] = ctx->Light.Light[1].Enabled; + break; + case GL_LIGHT2: + params[0] = ctx->Light.Light[2].Enabled; + break; + case GL_LIGHT3: + params[0] = ctx->Light.Light[3].Enabled; + break; + case GL_LIGHT4: + params[0] = ctx->Light.Light[4].Enabled; + break; + case GL_LIGHT5: + params[0] = ctx->Light.Light[5].Enabled; + break; + case GL_LIGHT6: + params[0] = ctx->Light.Light[6].Enabled; + break; + case GL_LIGHT7: + params[0] = ctx->Light.Light[7].Enabled; + break; + case GL_LIGHTING: + params[0] = ctx->Light.Enabled; + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Light.Model.Ambient[3]); + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = ENUM_TO_BOOLEAN(ctx->Light.Model.ColorControl); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + params[0] = ctx->Light.Model.LocalViewer; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + params[0] = ctx->Light.Model.TwoSide; + break; + case GL_LINE_SMOOTH: + params[0] = ctx->Line.SmoothFlag; + break; + case GL_LINE_SMOOTH_HINT: + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.LineSmooth); + break; + case GL_LINE_STIPPLE: + params[0] = ctx->Line.StippleFlag; + break; + case GL_LINE_STIPPLE_PATTERN: + params[0] = INT_TO_BOOLEAN(ctx->Line.StipplePattern); + break; + case GL_LINE_STIPPLE_REPEAT: + params[0] = INT_TO_BOOLEAN(ctx->Line.StippleFactor); + break; + case GL_LINE_WIDTH: + params[0] = FLOAT_TO_BOOLEAN(ctx->Line.Width); + break; + case GL_LINE_WIDTH_GRANULARITY: + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.LineWidthGranularity); + break; + case GL_LINE_WIDTH_RANGE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinLineWidthAA); + params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxLineWidthAA); + break; + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinLineWidth); + params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxLineWidth); + break; + case GL_LIST_BASE: + params[0] = INT_TO_BOOLEAN(ctx->List.ListBase); + break; + case GL_LIST_INDEX: + params[0] = INT_TO_BOOLEAN(ctx->ListState.CurrentListNum); + break; + case GL_LIST_MODE: + { + GLenum mode; + if (!ctx->CompileFlag) + mode = 0; + else if (ctx->ExecuteFlag) + mode = GL_COMPILE_AND_EXECUTE; + else + mode = GL_COMPILE; + params[0] = ENUM_TO_BOOLEAN(mode); + } + break; + case GL_INDEX_LOGIC_OP: + params[0] = ctx->Color.IndexLogicOpEnabled; + break; + case GL_COLOR_LOGIC_OP: + params[0] = ctx->Color.ColorLogicOpEnabled; + break; + case GL_LOGIC_OP_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->Color.LogicOp); + break; + case GL_MAP1_COLOR_4: + params[0] = ctx->Eval.Map1Color4; + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid1u1); + params[1] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid1u2); + break; + case GL_MAP1_GRID_SEGMENTS: + params[0] = INT_TO_BOOLEAN(ctx->Eval.MapGrid1un); + break; + case GL_MAP1_INDEX: + params[0] = ctx->Eval.Map1Index; + break; + case GL_MAP1_NORMAL: + params[0] = ctx->Eval.Map1Normal; + break; + case GL_MAP1_TEXTURE_COORD_1: + params[0] = ctx->Eval.Map1TextureCoord1; + break; + case GL_MAP1_TEXTURE_COORD_2: + params[0] = ctx->Eval.Map1TextureCoord2; + break; + case GL_MAP1_TEXTURE_COORD_3: + params[0] = ctx->Eval.Map1TextureCoord3; + break; + case GL_MAP1_TEXTURE_COORD_4: + params[0] = ctx->Eval.Map1TextureCoord4; + break; + case GL_MAP1_VERTEX_3: + params[0] = ctx->Eval.Map1Vertex3; + break; + case GL_MAP1_VERTEX_4: + params[0] = ctx->Eval.Map1Vertex4; + break; + case GL_MAP2_COLOR_4: + params[0] = ctx->Eval.Map2Color4; + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2u1); + params[1] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2u2); + params[2] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2v1); + params[3] = FLOAT_TO_BOOLEAN(ctx->Eval.MapGrid2v2); + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = INT_TO_BOOLEAN(ctx->Eval.MapGrid2un); + params[1] = INT_TO_BOOLEAN(ctx->Eval.MapGrid2vn); + break; + case GL_MAP2_INDEX: + params[0] = ctx->Eval.Map2Index; + break; + case GL_MAP2_NORMAL: + params[0] = ctx->Eval.Map2Normal; + break; + case GL_MAP2_TEXTURE_COORD_1: + params[0] = ctx->Eval.Map2TextureCoord1; + break; + case GL_MAP2_TEXTURE_COORD_2: + params[0] = ctx->Eval.Map2TextureCoord2; + break; + case GL_MAP2_TEXTURE_COORD_3: + params[0] = ctx->Eval.Map2TextureCoord3; + break; + case GL_MAP2_TEXTURE_COORD_4: + params[0] = ctx->Eval.Map2TextureCoord4; + break; + case GL_MAP2_VERTEX_3: + params[0] = ctx->Eval.Map2Vertex3; + break; + case GL_MAP2_VERTEX_4: + params[0] = ctx->Eval.Map2Vertex4; + break; + case GL_MAP_COLOR: + params[0] = ctx->Pixel.MapColorFlag; + break; + case GL_MAP_STENCIL: + params[0] = ctx->Pixel.MapStencilFlag; + break; + case GL_MATRIX_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->Transform.MatrixMode); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(MAX_ATTRIB_STACK_DEPTH); + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(MAX_CLIENT_ATTRIB_STACK_DEPTH); + break; + case GL_MAX_CLIP_PLANES: + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxClipPlanes); + break; + case GL_MAX_ELEMENTS_VERTICES: + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxArrayLockSize); + break; + case GL_MAX_ELEMENTS_INDICES: + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxArrayLockSize); + break; + case GL_MAX_EVAL_ORDER: + params[0] = INT_TO_BOOLEAN(MAX_EVAL_ORDER); + break; + case GL_MAX_LIGHTS: + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxLights); + break; + case GL_MAX_LIST_NESTING: + params[0] = INT_TO_BOOLEAN(MAX_LIST_NESTING); + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(MAX_MODELVIEW_STACK_DEPTH); + break; + case GL_MAX_NAME_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(MAX_NAME_STACK_DEPTH); + break; + case GL_MAX_PIXEL_MAP_TABLE: + params[0] = INT_TO_BOOLEAN(MAX_PIXEL_MAP_TABLE); + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(MAX_PROJECTION_STACK_DEPTH); + break; + case GL_MAX_TEXTURE_SIZE: + params[0] = INT_TO_BOOLEAN(1 << (ctx->Const.MaxTextureLevels - 1)); + break; + case GL_MAX_3D_TEXTURE_SIZE: + params[0] = INT_TO_BOOLEAN(1 << (ctx->Const.Max3DTextureLevels - 1)); + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(MAX_TEXTURE_STACK_DEPTH); + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxViewportWidth); + params[1] = INT_TO_BOOLEAN(ctx->Const.MaxViewportHeight); + break; + case GL_MODELVIEW_MATRIX: + { + const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[1]); + params[2] = FLOAT_TO_BOOLEAN(matrix[2]); + params[3] = FLOAT_TO_BOOLEAN(matrix[3]); + params[4] = FLOAT_TO_BOOLEAN(matrix[4]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[6]); + params[7] = FLOAT_TO_BOOLEAN(matrix[7]); + params[8] = FLOAT_TO_BOOLEAN(matrix[8]); + params[9] = FLOAT_TO_BOOLEAN(matrix[9]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[11]); + params[12] = FLOAT_TO_BOOLEAN(matrix[12]); + params[13] = FLOAT_TO_BOOLEAN(matrix[13]); + params[14] = FLOAT_TO_BOOLEAN(matrix[14]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_MODELVIEW_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(ctx->ModelviewMatrixStack.Depth + 1); + break; + case GL_NAME_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(ctx->Select.NameStackDepth); + break; + case GL_NORMALIZE: + params[0] = ctx->Transform.Normalize; + break; + case GL_PACK_ALIGNMENT: + params[0] = INT_TO_BOOLEAN(ctx->Pack.Alignment); + break; + case GL_PACK_LSB_FIRST: + params[0] = ctx->Pack.LsbFirst; + break; + case GL_PACK_ROW_LENGTH: + params[0] = INT_TO_BOOLEAN(ctx->Pack.RowLength); + break; + case GL_PACK_SKIP_PIXELS: + params[0] = INT_TO_BOOLEAN(ctx->Pack.SkipPixels); + break; + case GL_PACK_SKIP_ROWS: + params[0] = INT_TO_BOOLEAN(ctx->Pack.SkipRows); + break; + case GL_PACK_SWAP_BYTES: + params[0] = ctx->Pack.SwapBytes; + break; + case GL_PACK_SKIP_IMAGES_EXT: + params[0] = INT_TO_BOOLEAN(ctx->Pack.SkipImages); + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + params[0] = INT_TO_BOOLEAN(ctx->Pack.ImageHeight); + break; + case GL_PACK_INVERT_MESA: + params[0] = ctx->Pack.Invert; + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PerspectiveCorrection); + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapAtoAsize); + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapBtoBsize); + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapGtoGsize); + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoAsize); + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoBsize); + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoGsize); + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoIsize); + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapItoRsize); + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapRtoRsize); + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Pixel.MapStoSsize); + break; + case GL_POINT_SIZE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Size); + break; + case GL_POINT_SIZE_GRANULARITY: + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.PointSizeGranularity); + break; + case GL_POINT_SIZE_RANGE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinPointSizeAA); + params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxPointSizeAA); + break; + case GL_ALIASED_POINT_SIZE_RANGE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MinPointSize); + params[1] = FLOAT_TO_BOOLEAN(ctx->Const.MaxPointSize); + break; + case GL_POINT_SMOOTH: + params[0] = ctx->Point.SmoothFlag; + break; + case GL_POINT_SMOOTH_HINT: + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PointSmooth); + break; + case GL_POINT_SIZE_MIN_EXT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Point.MinSize); + break; + case GL_POINT_SIZE_MAX_EXT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Point.MaxSize); + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Threshold); + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Point.Params[0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Point.Params[1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Point.Params[2]); + break; + case GL_POLYGON_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->Polygon.FrontMode); + params[1] = ENUM_TO_BOOLEAN(ctx->Polygon.BackMode); + break; + case GL_POLYGON_OFFSET_BIAS_EXT: + params[0] = FLOAT_TO_BOOLEAN(ctx->Polygon.OffsetUnits); + break; + case GL_POLYGON_OFFSET_FACTOR: + params[0] = FLOAT_TO_BOOLEAN(ctx->Polygon.OffsetFactor ); + break; + case GL_POLYGON_OFFSET_UNITS: + params[0] = FLOAT_TO_BOOLEAN(ctx->Polygon.OffsetUnits ); + break; + case GL_POLYGON_SMOOTH: + params[0] = ctx->Polygon.SmoothFlag; + break; + case GL_POLYGON_SMOOTH_HINT: + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.PolygonSmooth); + break; + case GL_POLYGON_STIPPLE: + params[0] = ctx->Polygon.StippleFlag; + break; + case GL_PROJECTION_MATRIX: + { + const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[1]); + params[2] = FLOAT_TO_BOOLEAN(matrix[2]); + params[3] = FLOAT_TO_BOOLEAN(matrix[3]); + params[4] = FLOAT_TO_BOOLEAN(matrix[4]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[6]); + params[7] = FLOAT_TO_BOOLEAN(matrix[7]); + params[8] = FLOAT_TO_BOOLEAN(matrix[8]); + params[9] = FLOAT_TO_BOOLEAN(matrix[9]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[11]); + params[12] = FLOAT_TO_BOOLEAN(matrix[12]); + params[13] = FLOAT_TO_BOOLEAN(matrix[13]); + params[14] = FLOAT_TO_BOOLEAN(matrix[14]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_PROJECTION_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(ctx->ProjectionMatrixStack.Depth + 1); + break; + case GL_READ_BUFFER: + params[0] = ENUM_TO_BOOLEAN(ctx->Pixel.ReadBuffer); + break; + case GL_RED_BIAS: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.RedBias); + break; + case GL_RED_BITS: + params[0] = INT_TO_BOOLEAN( ctx->DrawBuffer->Visual.redBits ); + break; + case GL_RED_SCALE: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.RedScale); + break; + case GL_RENDER_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->RenderMode); + break; + case GL_RESCALE_NORMAL: + params[0] = ctx->Transform.RescaleNormals; + break; + case GL_RGBA_MODE: + params[0] = ctx->DrawBuffer->Visual.rgbMode; + break; + case GL_SCISSOR_BOX: + params[0] = INT_TO_BOOLEAN(ctx->Scissor.X); + params[1] = INT_TO_BOOLEAN(ctx->Scissor.Y); + params[2] = INT_TO_BOOLEAN(ctx->Scissor.Width); + params[3] = INT_TO_BOOLEAN(ctx->Scissor.Height); + break; + case GL_SCISSOR_TEST: + params[0] = ctx->Scissor.Enabled; + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Select.BufferSize); + break; + case GL_SHADE_MODEL: + params[0] = ENUM_TO_BOOLEAN(ctx->Light.ShadeModel); + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + params[0] = ctx->Texture.SharedPalette; + break; + case GL_STENCIL_BITS: + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.stencilBits); + break; + case GL_STENCIL_CLEAR_VALUE: + params[0] = INT_TO_BOOLEAN(ctx->Stencil.Clear); + break; + case GL_STENCIL_FAIL: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_FUNC: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.Function[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_PASS_DEPTH_PASS: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_REF: + params[0] = INT_TO_BOOLEAN(ctx->Stencil.Ref[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_TEST: + params[0] = ctx->Stencil.Enabled; + break; + case GL_STENCIL_VALUE_MASK: + params[0] = INT_TO_BOOLEAN(ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_WRITEMASK: + params[0] = INT_TO_BOOLEAN(ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]); + break; + case GL_STEREO: + params[0] = ctx->DrawBuffer->Visual.stereoMode; + break; + case GL_SUBPIXEL_BITS: + params[0] = INT_TO_BOOLEAN(ctx->Const.SubPixelBits); + break; + case GL_TEXTURE_1D: + params[0] = _mesa_IsEnabled(GL_TEXTURE_1D); + break; + case GL_TEXTURE_2D: + params[0] = _mesa_IsEnabled(GL_TEXTURE_2D); + break; + case GL_TEXTURE_3D: + params[0] = _mesa_IsEnabled(GL_TEXTURE_3D); + break; + case GL_TEXTURE_BINDING_1D: + params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name); + break; + case GL_TEXTURE_BINDING_2D: + params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name); + break; + case GL_TEXTURE_BINDING_3D: + params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name); + break; + case GL_TEXTURE_ENV_COLOR: + { + const GLfloat *color = ctx->Texture.Unit[ctx->Texture.CurrentUnit].EnvColor; + params[0] = FLOAT_TO_BOOLEAN(color[0]); + params[1] = FLOAT_TO_BOOLEAN(color[1]); + params[2] = FLOAT_TO_BOOLEAN(color[2]); + params[3] = FLOAT_TO_BOOLEAN(color[3]); + } + break; + case GL_TEXTURE_ENV_MODE: + params[0] = ENUM_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].EnvMode); + break; + case GL_TEXTURE_GEN_S: + params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0); + break; + case GL_TEXTURE_GEN_T: + params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0); + break; + case GL_TEXTURE_GEN_R: + params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0); + break; + case GL_TEXTURE_GEN_Q: + params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0); + break; + case GL_TEXTURE_MATRIX: + { + const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[1]); + params[2] = FLOAT_TO_BOOLEAN(matrix[2]); + params[3] = FLOAT_TO_BOOLEAN(matrix[3]); + params[4] = FLOAT_TO_BOOLEAN(matrix[4]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[6]); + params[7] = FLOAT_TO_BOOLEAN(matrix[7]); + params[8] = FLOAT_TO_BOOLEAN(matrix[8]); + params[9] = FLOAT_TO_BOOLEAN(matrix[9]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[11]); + params[12] = FLOAT_TO_BOOLEAN(matrix[12]); + params[13] = FLOAT_TO_BOOLEAN(matrix[13]); + params[14] = FLOAT_TO_BOOLEAN(matrix[14]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_TEXTURE_STACK_DEPTH: + params[0] = INT_TO_BOOLEAN(ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1); + break; + case GL_UNPACK_ALIGNMENT: + params[0] = INT_TO_BOOLEAN(ctx->Unpack.Alignment); + break; + case GL_UNPACK_LSB_FIRST: + params[0] = ctx->Unpack.LsbFirst; + break; + case GL_UNPACK_ROW_LENGTH: + params[0] = INT_TO_BOOLEAN(ctx->Unpack.RowLength); + break; + case GL_UNPACK_SKIP_PIXELS: + params[0] = INT_TO_BOOLEAN(ctx->Unpack.SkipPixels); + break; + case GL_UNPACK_SKIP_ROWS: + params[0] = INT_TO_BOOLEAN(ctx->Unpack.SkipRows); + break; + case GL_UNPACK_SWAP_BYTES: + params[0] = ctx->Unpack.SwapBytes; + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + params[0] = INT_TO_BOOLEAN(ctx->Unpack.SkipImages); + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + params[0] = INT_TO_BOOLEAN(ctx->Unpack.ImageHeight); + break; + case GL_UNPACK_CLIENT_STORAGE_APPLE: + params[0] = ctx->Unpack.ClientStorage; + break; + case GL_VIEWPORT: + params[0] = INT_TO_BOOLEAN(ctx->Viewport.X); + params[1] = INT_TO_BOOLEAN(ctx->Viewport.Y); + params[2] = INT_TO_BOOLEAN(ctx->Viewport.Width); + params[3] = INT_TO_BOOLEAN(ctx->Viewport.Height); + break; + case GL_ZOOM_X: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.ZoomX); + break; + case GL_ZOOM_Y: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.ZoomY); + break; + case GL_VERTEX_ARRAY: + params[0] = ctx->Array.Vertex.Enabled; + break; + case GL_VERTEX_ARRAY_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Array.Vertex.Size); + break; + case GL_VERTEX_ARRAY_TYPE: + params[0] = ENUM_TO_BOOLEAN(ctx->Array.Vertex.Type); + break; + case GL_VERTEX_ARRAY_STRIDE: + params[0] = INT_TO_BOOLEAN(ctx->Array.Vertex.Stride); + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + params[0] = INT_TO_BOOLEAN(0); + break; + case GL_NORMAL_ARRAY: + params[0] = ENUM_TO_BOOLEAN(ctx->Array.Normal.Enabled); + break; + case GL_NORMAL_ARRAY_TYPE: + params[0] = ENUM_TO_BOOLEAN(ctx->Array.Normal.Type); + break; + case GL_NORMAL_ARRAY_STRIDE: + params[0] = INT_TO_BOOLEAN(ctx->Array.Normal.Stride); + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + params[0] = INT_TO_BOOLEAN(0); + break; + case GL_COLOR_ARRAY: + params[0] = ctx->Array.Color.Enabled; + break; + case GL_COLOR_ARRAY_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Array.Color.Size); + break; + case GL_COLOR_ARRAY_TYPE: + params[0] = ENUM_TO_BOOLEAN(ctx->Array.Color.Type); + break; + case GL_COLOR_ARRAY_STRIDE: + params[0] = INT_TO_BOOLEAN(ctx->Array.Color.Stride); + break; + case GL_COLOR_ARRAY_COUNT_EXT: + params[0] = INT_TO_BOOLEAN(0); + break; + case GL_INDEX_ARRAY: + params[0] = ctx->Array.Index.Enabled; + break; + case GL_INDEX_ARRAY_TYPE: + params[0] = ENUM_TO_BOOLEAN(ctx->Array.Index.Type); + break; + case GL_INDEX_ARRAY_STRIDE: + params[0] = INT_TO_BOOLEAN(ctx->Array.Index.Stride); + break; + case GL_INDEX_ARRAY_COUNT_EXT: + params[0] = INT_TO_BOOLEAN(0); + break; + case GL_TEXTURE_COORD_ARRAY: + params[0] = ctx->Array.TexCoord[ctx->Array.ActiveTexture].Enabled; + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + params[0] = INT_TO_BOOLEAN(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Size); + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + params[0] = ENUM_TO_BOOLEAN(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Type); + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + params[0] = INT_TO_BOOLEAN(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Stride); + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + params[0] = INT_TO_BOOLEAN(0); + break; + case GL_EDGE_FLAG_ARRAY: + params[0] = ctx->Array.EdgeFlag.Enabled; + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + params[0] = INT_TO_BOOLEAN(ctx->Array.EdgeFlag.Stride); + break; + case GL_EDGE_FLAG_ARRAY_COUNT_EXT: + params[0] = INT_TO_BOOLEAN(0); + break; + case GL_MAX_TEXTURE_UNITS_ARB: + CHECK_EXTENSION_B(ARB_multitexture, pname); + params[0] = INT_TO_BOOLEAN(MIN2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits)); + break; + case GL_ACTIVE_TEXTURE_ARB: + CHECK_EXTENSION_B(ARB_multitexture, pname); + params[0] = INT_TO_BOOLEAN(GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit); + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + CHECK_EXTENSION_B(ARB_multitexture, pname); + params[0] = INT_TO_BOOLEAN(GL_TEXTURE0_ARB + ctx->Array.ActiveTexture); + break; + case GL_TEXTURE_CUBE_MAP_ARB: + CHECK_EXTENSION_B(ARB_texture_cube_map, pname); + params[0] = _mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB); + break; + case GL_TEXTURE_BINDING_CUBE_MAP_ARB: + CHECK_EXTENSION_B(ARB_texture_cube_map, pname); + params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name); + break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: + CHECK_EXTENSION_B(ARB_texture_cube_map, pname); + params[0] = INT_TO_BOOLEAN((1 << (ctx->Const.MaxCubeTextureLevels - 1))); + break; + case GL_TEXTURE_COMPRESSION_HINT_ARB: + CHECK_EXTENSION_B(ARB_texture_compression, pname); + params[0] = INT_TO_BOOLEAN(ctx->Hint.TextureCompression); + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB: + CHECK_EXTENSION_B(ARB_texture_compression, pname); + params[0] = INT_TO_BOOLEAN(_mesa_get_compressed_formats(ctx, NULL)); + break; + case GL_COMPRESSED_TEXTURE_FORMATS_ARB: + CHECK_EXTENSION_B(ARB_texture_compression, pname); + { + GLint formats[100]; + GLuint i, n = _mesa_get_compressed_formats(ctx, formats); + ASSERT(n <= 100); + for (i = 0; i < n; i++) + params[i] = ENUM_TO_INT(formats[i]); + } + break; + case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT: + CHECK_EXTENSION_B(EXT_compiled_vertex_array, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.LockFirst); + break; + case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT: + CHECK_EXTENSION_B(EXT_compiled_vertex_array, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.LockCount); + break; + case GL_TRANSPOSE_COLOR_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ColorMatrixStack.Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[4]); + params[2] = FLOAT_TO_BOOLEAN(matrix[8]); + params[3] = FLOAT_TO_BOOLEAN(matrix[12]); + params[4] = FLOAT_TO_BOOLEAN(matrix[1]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[9]); + params[7] = FLOAT_TO_BOOLEAN(matrix[13]); + params[8] = FLOAT_TO_BOOLEAN(matrix[2]); + params[9] = FLOAT_TO_BOOLEAN(matrix[6]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[14]); + params[12] = FLOAT_TO_BOOLEAN(matrix[3]); + params[13] = FLOAT_TO_BOOLEAN(matrix[7]); + params[14] = FLOAT_TO_BOOLEAN(matrix[11]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[4]); + params[2] = FLOAT_TO_BOOLEAN(matrix[8]); + params[3] = FLOAT_TO_BOOLEAN(matrix[12]); + params[4] = FLOAT_TO_BOOLEAN(matrix[1]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[9]); + params[7] = FLOAT_TO_BOOLEAN(matrix[13]); + params[8] = FLOAT_TO_BOOLEAN(matrix[2]); + params[9] = FLOAT_TO_BOOLEAN(matrix[6]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[14]); + params[12] = FLOAT_TO_BOOLEAN(matrix[3]); + params[13] = FLOAT_TO_BOOLEAN(matrix[7]); + params[14] = FLOAT_TO_BOOLEAN(matrix[11]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_TRANSPOSE_PROJECTION_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[4]); + params[2] = FLOAT_TO_BOOLEAN(matrix[8]); + params[3] = FLOAT_TO_BOOLEAN(matrix[12]); + params[4] = FLOAT_TO_BOOLEAN(matrix[1]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[9]); + params[7] = FLOAT_TO_BOOLEAN(matrix[13]); + params[8] = FLOAT_TO_BOOLEAN(matrix[2]); + params[9] = FLOAT_TO_BOOLEAN(matrix[6]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[14]); + params[12] = FLOAT_TO_BOOLEAN(matrix[3]); + params[13] = FLOAT_TO_BOOLEAN(matrix[7]); + params[14] = FLOAT_TO_BOOLEAN(matrix[11]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_TRANSPOSE_TEXTURE_MATRIX_ARB: + { + const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[4]); + params[2] = FLOAT_TO_BOOLEAN(matrix[8]); + params[3] = FLOAT_TO_BOOLEAN(matrix[12]); + params[4] = FLOAT_TO_BOOLEAN(matrix[1]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[9]); + params[7] = FLOAT_TO_BOOLEAN(matrix[13]); + params[8] = FLOAT_TO_BOOLEAN(matrix[2]); + params[9] = FLOAT_TO_BOOLEAN(matrix[6]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[14]); + params[12] = FLOAT_TO_BOOLEAN(matrix[3]); + params[13] = FLOAT_TO_BOOLEAN(matrix[7]); + params[14] = FLOAT_TO_BOOLEAN(matrix[11]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_OCCLUSION_TEST_HP: + CHECK_EXTENSION_B(HP_occlusion_test, pname); + params[0] = ctx->Depth.OcclusionTest; + break; + case GL_OCCLUSION_TEST_RESULT_HP: + CHECK_EXTENSION_B(HP_occlusion_test, pname); + { + FLUSH_VERTICES(ctx, _NEW_DEPTH); + if (ctx->Depth.OcclusionTest) + params[0] = ctx->OcclusionResult; + else + params[0] = ctx->OcclusionResultSaved; + /* reset flag now */ + ctx->OcclusionResult = GL_FALSE; + ctx->OcclusionResultSaved = GL_FALSE; + return; + } + break; + case GL_PIXEL_TEXTURE_SGIS: + CHECK_EXTENSION_B(SGIS_pixel_texture, pname); + params[0] = ctx->Pixel.PixelTextureEnabled; + break; + case GL_PIXEL_TEX_GEN_SGIX: + CHECK_EXTENSION_B(SGIX_pixel_texture, pname); + params[0] = ctx->Pixel.PixelTextureEnabled; + break; + case GL_PIXEL_TEX_GEN_MODE_SGIX: + CHECK_EXTENSION_B(SGIX_pixel_texture, pname); + params[0] = ENUM_TO_BOOLEAN(pixel_texgen_mode(ctx)); + break; + case GL_COLOR_MATRIX_SGI: + { + const GLfloat *matrix = ctx->ColorMatrixStack.Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[1]); + params[2] = FLOAT_TO_BOOLEAN(matrix[2]); + params[3] = FLOAT_TO_BOOLEAN(matrix[3]); + params[4] = FLOAT_TO_BOOLEAN(matrix[4]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[6]); + params[7] = FLOAT_TO_BOOLEAN(matrix[7]); + params[8] = FLOAT_TO_BOOLEAN(matrix[8]); + params[9] = FLOAT_TO_BOOLEAN(matrix[9]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[11]); + params[12] = FLOAT_TO_BOOLEAN(matrix[12]); + params[13] = FLOAT_TO_BOOLEAN(matrix[13]); + params[14] = FLOAT_TO_BOOLEAN(matrix[14]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_COLOR_MATRIX_STACK_DEPTH_SGI: + params[0] = INT_TO_BOOLEAN(ctx->ColorMatrixStack.Depth + 1); + break; + case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI: + params[0] = INT_TO_BOOLEAN(MAX_COLOR_STACK_DEPTH); + break; + case GL_POST_COLOR_MATRIX_RED_SCALE_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[0]); + break; + case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[1]); + break; + case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[2]); + break; + case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixScale[3]); + break; + case GL_POST_COLOR_MATRIX_RED_BIAS_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[0]); + break; + case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[1]); + break; + case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[2]); + break; + case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI: + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostColorMatrixBias[3]); + break; + case GL_CONVOLUTION_1D_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = ctx->Pixel.Convolution1DEnabled; + break; + case GL_CONVOLUTION_2D_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = ctx->Pixel.Convolution2DEnabled; + break; + case GL_SEPARABLE_2D_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = ctx->Pixel.Separable2DEnabled; + break; + case GL_POST_CONVOLUTION_RED_SCALE_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[0]); + break; + case GL_POST_CONVOLUTION_GREEN_SCALE_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[1]); + break; + case GL_POST_CONVOLUTION_BLUE_SCALE_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[2]); + break; + case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionScale[3]); + break; + case GL_POST_CONVOLUTION_RED_BIAS_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[0]); + break; + case GL_POST_CONVOLUTION_GREEN_BIAS_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[1]); + break; + case GL_POST_CONVOLUTION_BLUE_BIAS_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[2]); + break; + case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT: + CHECK_EXTENSION_B(EXT_convolution, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Pixel.PostConvolutionBias[3]); + break; + case GL_HISTOGRAM: + CHECK_EXTENSION_B(EXT_histogram, pname); + params[0] = ctx->Pixel.HistogramEnabled; + break; + case GL_MINMAX: + CHECK_EXTENSION_B(EXT_histogram, pname); + params[0] = ctx->Pixel.MinMaxEnabled; + break; + case GL_COLOR_TABLE_SGI: + CHECK_EXTENSION_B(SGI_color_table, pname); + params[0] = ctx->Pixel.ColorTableEnabled; + break; + case GL_POST_CONVOLUTION_COLOR_TABLE_SGI: + CHECK_EXTENSION_B(SGI_color_table, pname); + params[0] = ctx->Pixel.PostConvolutionColorTableEnabled; + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI: + CHECK_EXTENSION_B(SGI_color_table, pname); + params[0] = ctx->Pixel.PostColorMatrixColorTableEnabled; + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + CHECK_EXTENSION_B(SGI_texture_color_table, pname); + params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled; + break; + case GL_COLOR_SUM_EXT: + CHECK_EXTENSION_B(EXT_secondary_color, pname); + params[0] = ctx->Fog.ColorSumEnabled; + break; + case GL_CURRENT_SECONDARY_COLOR_EXT: + CHECK_EXTENSION_B(EXT_secondary_color, pname); + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]); + params[1] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]); + params[2] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]); + params[3] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]); + } + break; + case GL_SECONDARY_COLOR_ARRAY_EXT: + CHECK_EXTENSION_B(EXT_secondary_color, pname); + params[0] = ctx->Array.SecondaryColor.Enabled; + break; + case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT: + CHECK_EXTENSION_B(EXT_secondary_color, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Array.SecondaryColor.Type); + break; + case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT: + CHECK_EXTENSION_B(EXT_secondary_color, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.SecondaryColor.Stride); + break; + case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT: + CHECK_EXTENSION_B(EXT_secondary_color, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.SecondaryColor.Size); + break; + case GL_CURRENT_FOG_COORDINATE_EXT: + CHECK_EXTENSION_B(EXT_fog_coord, pname); + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_BOOLEAN(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]); + } + break; + case GL_FOG_COORDINATE_ARRAY_EXT: + CHECK_EXTENSION_B(EXT_fog_coord, pname); + params[0] = ctx->Array.FogCoord.Enabled; + break; + case GL_FOG_COORDINATE_ARRAY_TYPE_EXT: + CHECK_EXTENSION_B(EXT_fog_coord, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Array.FogCoord.Type); + break; + case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT: + CHECK_EXTENSION_B(EXT_fog_coord, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.FogCoord.Stride); + break; + case GL_FOG_COORDINATE_SOURCE_EXT: + CHECK_EXTENSION_B(EXT_fog_coord, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Fog.FogCoordinateSource); + break; + case GL_MAX_TEXTURE_LOD_BIAS_EXT: + CHECK_EXTENSION_B(EXT_texture_lod_bias, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxTextureLodBias); + break; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + CHECK_EXTENSION_B(EXT_texture_filter_anisotropic, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxTextureMaxAnisotropy); + break; + case GL_MULTISAMPLE_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = ctx->Multisample.Enabled; + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = ctx->Multisample.SampleAlphaToCoverage; + break; + case GL_SAMPLE_ALPHA_TO_ONE_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = ctx->Multisample.SampleAlphaToOne; + break; + case GL_SAMPLE_COVERAGE_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = ctx->Multisample.SampleCoverage; + break; + case GL_SAMPLE_COVERAGE_VALUE_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Multisample.SampleCoverageValue); + break; + case GL_SAMPLE_COVERAGE_INVERT_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = ctx->Multisample.SampleCoverageInvert; + break; + case GL_SAMPLE_BUFFERS_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.sampleBuffers); + break; + case GL_SAMPLES_ARB: + CHECK_EXTENSION_B(ARB_multisample, pname); + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Visual.samples); + break; + case GL_RASTER_POSITION_UNCLIPPED_IBM: + CHECK_EXTENSION_B(IBM_rasterpos_clip, pname); + params[0] = ctx->Transform.RasterPositionUnclipped; + break; + case GL_POINT_SPRITE_NV: + CHECK_EXTENSION_B(NV_point_sprite, pname); + params[0] = ctx->Point.PointSprite; + break; + case GL_POINT_SPRITE_R_MODE_NV: + CHECK_EXTENSION_B(NV_point_sprite, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Point.SpriteRMode); + break; + case GL_POINT_SPRITE_COORD_ORIGIN: + CHECK_EXTENSION_B(NV_point_sprite, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Point.SpriteOrigin); + break; + case GL_GENERATE_MIPMAP_HINT_SGIS: + CHECK_EXTENSION_B(SGIS_generate_mipmap, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.GenerateMipmap); + break; + case GL_VERTEX_PROGRAM_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->VertexProgram.Enabled; + break; + case GL_VERTEX_PROGRAM_POINT_SIZE_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->VertexProgram.PointSizeEnabled; + break; + case GL_VERTEX_PROGRAM_TWO_SIDE_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->VertexProgram.TwoSideEnabled; + break; + case GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxProgramMatrixStackDepth); + break; + case GL_MAX_TRACK_MATRICES_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxProgramMatrices); + break; + case GL_CURRENT_MATRIX_STACK_DEPTH_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->CurrentStack->Depth + 1; + break; + case GL_CURRENT_MATRIX_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + { + const GLfloat *matrix = ctx->CurrentStack->Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[1]); + params[2] = FLOAT_TO_BOOLEAN(matrix[2]); + params[3] = FLOAT_TO_BOOLEAN(matrix[3]); + params[4] = FLOAT_TO_BOOLEAN(matrix[4]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[6]); + params[7] = FLOAT_TO_BOOLEAN(matrix[7]); + params[8] = FLOAT_TO_BOOLEAN(matrix[8]); + params[9] = FLOAT_TO_BOOLEAN(matrix[9]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[11]); + params[12] = FLOAT_TO_BOOLEAN(matrix[12]); + params[13] = FLOAT_TO_BOOLEAN(matrix[13]); + params[14] = FLOAT_TO_BOOLEAN(matrix[14]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_VERTEX_PROGRAM_BINDING_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = INT_TO_BOOLEAN((ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0)); + break; + case GL_PROGRAM_ERROR_POSITION_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->Program.ErrorPos); + break; + case GL_VERTEX_ATTRIB_ARRAY0_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[0].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY1_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[1].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY2_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[2].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY3_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[3].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[4].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY5_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[5].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY6_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[6].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY7_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[7].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY8_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[8].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY9_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[9].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY10_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[10].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY11_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[11].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY12_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[12].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY13_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[13].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY14_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[14].Enabled; + break; + case GL_VERTEX_ATTRIB_ARRAY15_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Array.VertexAttrib[15].Enabled; + break; + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[0]; + break; + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[1]; + break; + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[2]; + break; + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[3]; + break; + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[4]; + break; + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[5]; + break; + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[6]; + break; + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[7]; + break; + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[8]; + break; + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[9]; + break; + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[10]; + break; + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[11]; + break; + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[12]; + break; + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[13]; + break; + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[14]; + break; + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION_B(NV_vertex_program, pname); + params[0] = ctx->Eval.Map1Attrib[15]; + break; + case GL_FRAGMENT_PROGRAM_NV: + CHECK_EXTENSION_B(NV_fragment_program, pname); + params[0] = ctx->FragmentProgram.Enabled; + break; + case GL_MAX_TEXTURE_COORDS_NV: + CHECK_EXTENSION_B(NV_fragment_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureCoordUnits); + break; + case GL_MAX_TEXTURE_IMAGE_UNITS_NV: + CHECK_EXTENSION_B(NV_fragment_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureImageUnits); + break; + case GL_FRAGMENT_PROGRAM_BINDING_NV: + CHECK_EXTENSION_B(NV_fragment_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0); + break; + case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV: + CHECK_EXTENSION_B(NV_fragment_program, pname); + params[0] = INT_TO_BOOLEAN(MAX_NV_FRAGMENT_PROGRAM_PARAMS); + break; + case GL_TEXTURE_RECTANGLE_NV: + CHECK_EXTENSION_B(NV_texture_rectangle, pname); + params[0] = _mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV); + break; + case GL_TEXTURE_BINDING_RECTANGLE_NV: + CHECK_EXTENSION_B(NV_texture_rectangle, pname); + params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name); + break; + case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV: + CHECK_EXTENSION_B(NV_texture_rectangle, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxTextureRectSize); + break; + case GL_STENCIL_TEST_TWO_SIDE_EXT: + CHECK_EXTENSION_B(EXT_stencil_two_side, pname); + params[0] = ctx->Stencil.TestTwoSide; + break; + case GL_ACTIVE_STENCIL_FACE_EXT: + CHECK_EXTENSION_B(EXT_stencil_two_side, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT); + break; + case GL_MAX_SHININESS_NV: + CHECK_EXTENSION_B(NV_light_max_exponent, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxShininess); + break; + case GL_MAX_SPOT_EXPONENT_NV: + CHECK_EXTENSION_B(NV_light_max_exponent, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Const.MaxSpotExponent); + break; + case GL_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.ArrayBufferObj->Name); + break; + case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.Vertex.BufferObj->Name); + break; + case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.Normal.BufferObj->Name); + break; + case GL_COLOR_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.Color.BufferObj->Name); + break; + case GL_INDEX_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.Index.BufferObj->Name); + break; + case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.TexCoord[ctx->Array.ActiveTexture].BufferObj->Name); + break; + case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.EdgeFlag.BufferObj->Name); + break; + case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.SecondaryColor.BufferObj->Name); + break; + case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.FogCoord.BufferObj->Name); + break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_B(ARB_vertex_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Array.ElementArrayBufferObj->Name); + break; + case GL_PIXEL_PACK_BUFFER_BINDING_EXT: + CHECK_EXTENSION_B(EXT_pixel_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Pack.BufferObj->Name); + break; + case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT: + CHECK_EXTENSION_B(EXT_pixel_buffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Unpack.BufferObj->Name); + break; + case GL_MAX_VERTEX_ATTRIBS_ARB: + CHECK_EXTENSION_B(ARB_vertex_program, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxVertexProgramAttribs); + break; + case GL_FRAGMENT_PROGRAM_ARB: + CHECK_EXTENSION_B(ARB_fragment_program, pname); + params[0] = ctx->FragmentProgram.Enabled; + break; + case GL_TRANSPOSE_CURRENT_MATRIX_ARB: + CHECK_EXTENSION_B(ARB_fragment_program, pname); + { + const GLfloat *matrix = ctx->CurrentStack->Top->m; + params[0] = FLOAT_TO_BOOLEAN(matrix[0]); + params[1] = FLOAT_TO_BOOLEAN(matrix[4]); + params[2] = FLOAT_TO_BOOLEAN(matrix[8]); + params[3] = FLOAT_TO_BOOLEAN(matrix[12]); + params[4] = FLOAT_TO_BOOLEAN(matrix[1]); + params[5] = FLOAT_TO_BOOLEAN(matrix[5]); + params[6] = FLOAT_TO_BOOLEAN(matrix[9]); + params[7] = FLOAT_TO_BOOLEAN(matrix[13]); + params[8] = FLOAT_TO_BOOLEAN(matrix[2]); + params[9] = FLOAT_TO_BOOLEAN(matrix[6]); + params[10] = FLOAT_TO_BOOLEAN(matrix[10]); + params[11] = FLOAT_TO_BOOLEAN(matrix[14]); + params[12] = FLOAT_TO_BOOLEAN(matrix[3]); + params[13] = FLOAT_TO_BOOLEAN(matrix[7]); + params[14] = FLOAT_TO_BOOLEAN(matrix[11]); + params[15] = FLOAT_TO_BOOLEAN(matrix[15]); + } + break; + case GL_DEPTH_BOUNDS_TEST_EXT: + CHECK_EXTENSION_B(EXT_depth_bounds_test, pname); + params[0] = ctx->Depth.BoundsTest; + break; + case GL_DEPTH_BOUNDS_EXT: + CHECK_EXTENSION_B(EXT_depth_bounds_test, pname); + params[0] = FLOAT_TO_BOOLEAN(ctx->Depth.BoundsMin); + params[1] = FLOAT_TO_BOOLEAN(ctx->Depth.BoundsMax); + break; + case GL_FRAGMENT_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION_B(MESA_program_debug, pname); + params[0] = ctx->FragmentProgram.CallbackEnabled; + break; + case GL_VERTEX_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION_B(MESA_program_debug, pname); + params[0] = ctx->VertexProgram.CallbackEnabled; + break; + case GL_FRAGMENT_PROGRAM_POSITION_MESA: + CHECK_EXTENSION_B(MESA_program_debug, pname); + params[0] = INT_TO_BOOLEAN(ctx->FragmentProgram.CurrentPosition); + break; + case GL_VERTEX_PROGRAM_POSITION_MESA: + CHECK_EXTENSION_B(MESA_program_debug, pname); + params[0] = INT_TO_BOOLEAN(ctx->VertexProgram.CurrentPosition); + break; + case GL_MAX_DRAW_BUFFERS_ARB: + CHECK_EXTENSION_B(ARB_draw_buffers, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxDrawBuffers); + break; + case GL_DRAW_BUFFER0_ARB: + CHECK_EXTENSION_B(ARB_draw_buffers, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Color.DrawBuffer[0]); + break; + case GL_DRAW_BUFFER1_ARB: + CHECK_EXTENSION_B(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[1]; + params[0] = ENUM_TO_BOOLEAN(buffer); + } + break; + case GL_DRAW_BUFFER2_ARB: + CHECK_EXTENSION_B(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[2]; + params[0] = ENUM_TO_BOOLEAN(buffer); + } + break; + case GL_DRAW_BUFFER3_ARB: + CHECK_EXTENSION_B(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[3]; + params[0] = ENUM_TO_BOOLEAN(buffer); + } + break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + CHECK_EXTENSION_B(OES_read_format, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.ColorReadType); + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + CHECK_EXTENSION_B(OES_read_format, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.ColorReadFormat); + break; + case GL_NUM_FRAGMENT_REGISTERS_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(6); + break; + case GL_NUM_FRAGMENT_CONSTANTS_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(8); + break; + case GL_NUM_PASSES_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(2); + break; + case GL_NUM_INSTRUCTIONS_PER_PASS_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(8); + break; + case GL_NUM_INSTRUCTIONS_TOTAL_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(16); + break; + case GL_COLOR_ALPHA_PAIRING_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = GL_TRUE; + break; + case GL_NUM_LOOPBACK_COMPONENTS_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(3); + break; + case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI: + CHECK_EXTENSION_B(ATI_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(3); + break; + case GL_STENCIL_BACK_FUNC: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.Function[1]); + break; + case GL_STENCIL_BACK_VALUE_MASK: + params[0] = INT_TO_BOOLEAN(ctx->Stencil.ValueMask[1]); + break; + case GL_STENCIL_BACK_REF: + params[0] = INT_TO_BOOLEAN(ctx->Stencil.Ref[1]); + break; + case GL_STENCIL_BACK_FAIL: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.FailFunc[1]); + break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZFailFunc[1]); + break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + params[0] = ENUM_TO_BOOLEAN(ctx->Stencil.ZPassFunc[1]); + break; + case GL_FRAMEBUFFER_BINDING_EXT: + CHECK_EXTENSION_B(EXT_framebuffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->DrawBuffer->Name); + break; + case GL_RENDERBUFFER_BINDING_EXT: + CHECK_EXTENSION_B(EXT_framebuffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0); + break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: + CHECK_EXTENSION_B(EXT_framebuffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxColorAttachments); + break; + case GL_MAX_RENDERBUFFER_SIZE_EXT: + CHECK_EXTENSION_B(EXT_framebuffer_object, pname); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxRenderbufferSize); + break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB: + CHECK_EXTENSION_B(ARB_fragment_shader, pname); + params[0] = INT_TO_BOOLEAN(MAX_FRAGMENT_UNIFORM_COMPONENTS); + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB: + CHECK_EXTENSION_B(ARB_fragment_shader, pname); + params[0] = ENUM_TO_BOOLEAN(ctx->Hint.FragmentShaderDerivative); + break; + case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB: + CHECK_EXTENSION_B(ARB_vertex_shader, pname); + params[0] = INT_TO_BOOLEAN(MAX_VERTEX_UNIFORM_COMPONENTS); + break; + case GL_MAX_VARYING_FLOATS_ARB: + CHECK_EXTENSION_B(ARB_vertex_shader, pname); + params[0] = INT_TO_BOOLEAN(MAX_VARYING_FLOATS); + break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB: + CHECK_EXTENSION_B(ARB_vertex_shader, pname); + params[0] = INT_TO_BOOLEAN(MAX_VERTEX_TEXTURE_IMAGE_UNITS); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB: + CHECK_EXTENSION_B(ARB_vertex_shader, pname); + params[0] = INT_TO_BOOLEAN(MAX_COMBINED_TEXTURE_IMAGE_UNITS); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname); + } +} + +void GLAPIENTRY +_mesa_GetFloatv( GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!params) + return; + + if (ctx->NewState) + _mesa_update_state(ctx); + + if (ctx->Driver.GetFloatv && + ctx->Driver.GetFloatv(ctx, pname, params)) + return; + + switch (pname) { + case GL_ACCUM_RED_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumRedBits); + break; + case GL_ACCUM_GREEN_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumGreenBits); + break; + case GL_ACCUM_BLUE_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumBlueBits); + break; + case GL_ACCUM_ALPHA_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.accumAlphaBits); + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = ctx->Accum.ClearColor[0]; + params[1] = ctx->Accum.ClearColor[1]; + params[2] = ctx->Accum.ClearColor[2]; + params[3] = ctx->Accum.ClearColor[3]; + break; + case GL_ALPHA_BIAS: + params[0] = ctx->Pixel.AlphaBias; + break; + case GL_ALPHA_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.alphaBits); + break; + case GL_ALPHA_SCALE: + params[0] = ctx->Pixel.AlphaScale; + break; + case GL_ALPHA_TEST: + params[0] = BOOLEAN_TO_FLOAT(ctx->Color.AlphaEnabled); + break; + case GL_ALPHA_TEST_FUNC: + params[0] = ENUM_TO_FLOAT(ctx->Color.AlphaFunc); + break; + case GL_ALPHA_TEST_REF: + params[0] = ctx->Color.AlphaRef; + break; + case GL_ATTRIB_STACK_DEPTH: + params[0] = (GLfloat)(ctx->AttribStackDepth); + break; + case GL_AUTO_NORMAL: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.AutoNormal); + break; + case GL_AUX_BUFFERS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.numAuxBuffers); + break; + case GL_BLEND: + params[0] = BOOLEAN_TO_FLOAT(ctx->Color.BlendEnabled); + break; + case GL_BLEND_DST: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_SRC_RGB_EXT: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_DST_RGB_EXT: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC_ALPHA_EXT: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendSrcA); + break; + case GL_BLEND_DST_ALPHA_EXT: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendDstA); + break; + case GL_BLEND_EQUATION: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendEquationRGB ); + break; + case GL_BLEND_EQUATION_ALPHA_EXT: + params[0] = ENUM_TO_FLOAT(ctx->Color.BlendEquationA ); + break; + case GL_BLEND_COLOR_EXT: + params[0] = ctx->Color.BlendColor[0]; + params[1] = ctx->Color.BlendColor[1]; + params[2] = ctx->Color.BlendColor[2]; + params[3] = ctx->Color.BlendColor[3]; + break; + case GL_BLUE_BIAS: + params[0] = ctx->Pixel.BlueBias; + break; + case GL_BLUE_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.blueBits); + break; + case GL_BLUE_SCALE: + params[0] = ctx->Pixel.BlueScale; + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + params[0] = (GLfloat)(ctx->ClientAttribStackDepth); + break; + case GL_CLIP_PLANE0: + params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 0) & 1); + break; + case GL_CLIP_PLANE1: + params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 1) & 1); + break; + case GL_CLIP_PLANE2: + params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 2) & 1); + break; + case GL_CLIP_PLANE3: + params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 3) & 1); + break; + case GL_CLIP_PLANE4: + params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 4) & 1); + break; + case GL_CLIP_PLANE5: + params[0] = BOOLEAN_TO_FLOAT((ctx->Transform.ClipPlanesEnabled >> 5) & 1); + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = ctx->Color.ClearColor[0]; + params[1] = ctx->Color.ClearColor[1]; + params[2] = ctx->Color.ClearColor[2]; + params[3] = ctx->Color.ClearColor[3]; + break; + case GL_COLOR_MATERIAL: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.ColorMaterialEnabled); + break; + case GL_COLOR_MATERIAL_FACE: + params[0] = ENUM_TO_FLOAT(ctx->Light.ColorMaterialFace); + break; + case GL_COLOR_MATERIAL_PARAMETER: + params[0] = ENUM_TO_FLOAT(ctx->Light.ColorMaterialMode); + break; + case GL_COLOR_WRITEMASK: + params[0] = (GLfloat)(ctx->Color.ColorMask[RCOMP] ? 1 : 0); + params[1] = (GLfloat)(ctx->Color.ColorMask[GCOMP] ? 1 : 0); + params[2] = (GLfloat)(ctx->Color.ColorMask[BCOMP] ? 1 : 0); + params[3] = (GLfloat)(ctx->Color.ColorMask[ACOMP] ? 1 : 0); + break; + case GL_CULL_FACE: + params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.CullFlag); + break; + case GL_CULL_FACE_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Polygon.CullFaceMode); + break; + case GL_CURRENT_COLOR: + { + FLUSH_CURRENT(ctx, 0); + params[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]; + params[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]; + params[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]; + params[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]; + } + break; + case GL_CURRENT_INDEX: + { + FLUSH_CURRENT(ctx, 0); + params[0] = ctx->Current.Index; + } + break; + case GL_CURRENT_NORMAL: + { + FLUSH_CURRENT(ctx, 0); + params[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]; + params[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]; + params[2] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]; + } + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = ctx->Current.RasterColor[0]; + params[1] = ctx->Current.RasterColor[1]; + params[2] = ctx->Current.RasterColor[2]; + params[3] = ctx->Current.RasterColor[3]; + break; + case GL_CURRENT_RASTER_DISTANCE: + params[0] = ctx->Current.RasterDistance; + break; + case GL_CURRENT_RASTER_INDEX: + params[0] = ctx->Current.RasterIndex; + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = ctx->Current.RasterPos[0]; + params[1] = ctx->Current.RasterPos[1]; + params[2] = ctx->Current.RasterPos[2]; + params[3] = ctx->Current.RasterPos[3]; + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + { + const GLuint texUnit = ctx->Texture.CurrentUnit; + params[0] = ctx->Current.RasterTexCoords[texUnit][0]; + params[1] = ctx->Current.RasterTexCoords[texUnit][1]; + params[2] = ctx->Current.RasterTexCoords[texUnit][2]; + params[3] = ctx->Current.RasterTexCoords[texUnit][3]; + } + break; + case GL_CURRENT_RASTER_POSITION_VALID: + params[0] = BOOLEAN_TO_FLOAT(ctx->Current.RasterPosValid); + break; + case GL_CURRENT_TEXTURE_COORDS: + { + const GLuint texUnit = ctx->Texture.CurrentUnit; + params[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]; + params[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]; + params[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]; + params[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]; + } + break; + case GL_DEPTH_BIAS: + params[0] = ctx->Pixel.DepthBias; + break; + case GL_DEPTH_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.depthBits); + break; + case GL_DEPTH_CLEAR_VALUE: + params[0] = ctx->Depth.Clear; + break; + case GL_DEPTH_FUNC: + params[0] = ENUM_TO_FLOAT(ctx->Depth.Func); + break; + case GL_DEPTH_RANGE: + params[0] = ctx->Viewport.Near; + params[1] = ctx->Viewport.Far; + break; + case GL_DEPTH_SCALE: + params[0] = ctx->Pixel.DepthScale; + break; + case GL_DEPTH_TEST: + params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.Test); + break; + case GL_DEPTH_WRITEMASK: + params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.Mask); + break; + case GL_DITHER: + params[0] = BOOLEAN_TO_FLOAT(ctx->Color.DitherFlag); + break; + case GL_DOUBLEBUFFER: + params[0] = BOOLEAN_TO_FLOAT(ctx->DrawBuffer->Visual.doubleBufferMode); + break; + case GL_DRAW_BUFFER: + params[0] = ENUM_TO_FLOAT(ctx->Color.DrawBuffer[0]); + break; + case GL_EDGE_FLAG: + { + FLUSH_CURRENT(ctx, 0); + params[0] = BOOLEAN_TO_FLOAT(ctx->Current.EdgeFlag); + } + break; + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = (GLfloat)(ctx->Feedback.BufferSize); + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = ENUM_TO_FLOAT(ctx->Feedback.Type); + break; + case GL_FOG: + params[0] = BOOLEAN_TO_FLOAT(ctx->Fog.Enabled); + break; + case GL_FOG_COLOR: + params[0] = ctx->Fog.Color[0]; + params[1] = ctx->Fog.Color[1]; + params[2] = ctx->Fog.Color[2]; + params[3] = ctx->Fog.Color[3]; + break; + case GL_FOG_DENSITY: + params[0] = ctx->Fog.Density; + break; + case GL_FOG_END: + params[0] = ctx->Fog.End; + break; + case GL_FOG_HINT: + params[0] = ENUM_TO_FLOAT(ctx->Hint.Fog); + break; + case GL_FOG_INDEX: + params[0] = ctx->Fog.Index; + break; + case GL_FOG_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Fog.Mode); + break; + case GL_FOG_START: + params[0] = ctx->Fog.Start; + break; + case GL_FRONT_FACE: + params[0] = ENUM_TO_FLOAT(ctx->Polygon.FrontFace); + break; + case GL_GREEN_BIAS: + params[0] = ctx->Pixel.GreenBias; + break; + case GL_GREEN_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.greenBits); + break; + case GL_GREEN_SCALE: + params[0] = ctx->Pixel.GreenScale; + break; + case GL_INDEX_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.indexBits); + break; + case GL_INDEX_CLEAR_VALUE: + params[0] = (GLfloat)(ctx->Color.ClearIndex); + break; + case GL_INDEX_MODE: + params[0] = BOOLEAN_TO_FLOAT(!ctx->DrawBuffer->Visual.rgbMode); + break; + case GL_INDEX_OFFSET: + params[0] = (GLfloat)(ctx->Pixel.IndexOffset); + break; + case GL_INDEX_SHIFT: + params[0] = (GLfloat)(ctx->Pixel.IndexShift); + break; + case GL_INDEX_WRITEMASK: + params[0] = (GLfloat)(ctx->Color.IndexMask); + break; + case GL_LIGHT0: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[0].Enabled); + break; + case GL_LIGHT1: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[1].Enabled); + break; + case GL_LIGHT2: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[2].Enabled); + break; + case GL_LIGHT3: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[3].Enabled); + break; + case GL_LIGHT4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[4].Enabled); + break; + case GL_LIGHT5: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[5].Enabled); + break; + case GL_LIGHT6: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[6].Enabled); + break; + case GL_LIGHT7: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Light[7].Enabled); + break; + case GL_LIGHTING: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Enabled); + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = ctx->Light.Model.Ambient[0]; + params[1] = ctx->Light.Model.Ambient[1]; + params[2] = ctx->Light.Model.Ambient[2]; + params[3] = ctx->Light.Model.Ambient[3]; + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = ENUM_TO_FLOAT(ctx->Light.Model.ColorControl); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Model.LocalViewer); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + params[0] = BOOLEAN_TO_FLOAT(ctx->Light.Model.TwoSide); + break; + case GL_LINE_SMOOTH: + params[0] = BOOLEAN_TO_FLOAT(ctx->Line.SmoothFlag); + break; + case GL_LINE_SMOOTH_HINT: + params[0] = ENUM_TO_FLOAT(ctx->Hint.LineSmooth); + break; + case GL_LINE_STIPPLE: + params[0] = BOOLEAN_TO_FLOAT(ctx->Line.StippleFlag); + break; + case GL_LINE_STIPPLE_PATTERN: + params[0] = (GLfloat)(ctx->Line.StipplePattern); + break; + case GL_LINE_STIPPLE_REPEAT: + params[0] = (GLfloat)(ctx->Line.StippleFactor); + break; + case GL_LINE_WIDTH: + params[0] = ctx->Line.Width; + break; + case GL_LINE_WIDTH_GRANULARITY: + params[0] = ctx->Const.LineWidthGranularity; + break; + case GL_LINE_WIDTH_RANGE: + params[0] = ctx->Const.MinLineWidthAA; + params[1] = ctx->Const.MaxLineWidthAA; + break; + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = ctx->Const.MinLineWidth; + params[1] = ctx->Const.MaxLineWidth; + break; + case GL_LIST_BASE: + params[0] = (GLfloat)(ctx->List.ListBase); + break; + case GL_LIST_INDEX: + params[0] = (GLfloat)(ctx->ListState.CurrentListNum); + break; + case GL_LIST_MODE: + { + GLenum mode; + if (!ctx->CompileFlag) + mode = 0; + else if (ctx->ExecuteFlag) + mode = GL_COMPILE_AND_EXECUTE; + else + mode = GL_COMPILE; + params[0] = ENUM_TO_FLOAT(mode); + } + break; + case GL_INDEX_LOGIC_OP: + params[0] = BOOLEAN_TO_FLOAT(ctx->Color.IndexLogicOpEnabled); + break; + case GL_COLOR_LOGIC_OP: + params[0] = BOOLEAN_TO_FLOAT(ctx->Color.ColorLogicOpEnabled); + break; + case GL_LOGIC_OP_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Color.LogicOp); + break; + case GL_MAP1_COLOR_4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Color4); + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = ctx->Eval.MapGrid1u1; + params[1] = ctx->Eval.MapGrid1u2; + break; + case GL_MAP1_GRID_SEGMENTS: + params[0] = (GLfloat)(ctx->Eval.MapGrid1un); + break; + case GL_MAP1_INDEX: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Index); + break; + case GL_MAP1_NORMAL: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Normal); + break; + case GL_MAP1_TEXTURE_COORD_1: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord1); + break; + case GL_MAP1_TEXTURE_COORD_2: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord2); + break; + case GL_MAP1_TEXTURE_COORD_3: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord3); + break; + case GL_MAP1_TEXTURE_COORD_4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1TextureCoord4); + break; + case GL_MAP1_VERTEX_3: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Vertex3); + break; + case GL_MAP1_VERTEX_4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Vertex4); + break; + case GL_MAP2_COLOR_4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Color4); + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = ctx->Eval.MapGrid2u1; + params[1] = ctx->Eval.MapGrid2u2; + params[2] = ctx->Eval.MapGrid2v1; + params[3] = ctx->Eval.MapGrid2v2; + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = (GLfloat)(ctx->Eval.MapGrid2un); + params[1] = (GLfloat)(ctx->Eval.MapGrid2vn); + break; + case GL_MAP2_INDEX: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Index); + break; + case GL_MAP2_NORMAL: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Normal); + break; + case GL_MAP2_TEXTURE_COORD_1: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord1); + break; + case GL_MAP2_TEXTURE_COORD_2: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord2); + break; + case GL_MAP2_TEXTURE_COORD_3: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord3); + break; + case GL_MAP2_TEXTURE_COORD_4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2TextureCoord4); + break; + case GL_MAP2_VERTEX_3: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Vertex3); + break; + case GL_MAP2_VERTEX_4: + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map2Vertex4); + break; + case GL_MAP_COLOR: + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.MapColorFlag); + break; + case GL_MAP_STENCIL: + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.MapStencilFlag); + break; + case GL_MATRIX_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Transform.MatrixMode); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + params[0] = (GLfloat)(MAX_ATTRIB_STACK_DEPTH); + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + params[0] = (GLfloat)(MAX_CLIENT_ATTRIB_STACK_DEPTH); + break; + case GL_MAX_CLIP_PLANES: + params[0] = (GLfloat)(ctx->Const.MaxClipPlanes); + break; + case GL_MAX_ELEMENTS_VERTICES: + params[0] = (GLfloat)(ctx->Const.MaxArrayLockSize); + break; + case GL_MAX_ELEMENTS_INDICES: + params[0] = (GLfloat)(ctx->Const.MaxArrayLockSize); + break; + case GL_MAX_EVAL_ORDER: + params[0] = (GLfloat)(MAX_EVAL_ORDER); + break; + case GL_MAX_LIGHTS: + params[0] = (GLfloat)(ctx->Const.MaxLights); + break; + case GL_MAX_LIST_NESTING: + params[0] = (GLfloat)(MAX_LIST_NESTING); + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + params[0] = (GLfloat)(MAX_MODELVIEW_STACK_DEPTH); + break; + case GL_MAX_NAME_STACK_DEPTH: + params[0] = (GLfloat)(MAX_NAME_STACK_DEPTH); + break; + case GL_MAX_PIXEL_MAP_TABLE: + params[0] = (GLfloat)(MAX_PIXEL_MAP_TABLE); + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + params[0] = (GLfloat)(MAX_PROJECTION_STACK_DEPTH); + break; + case GL_MAX_TEXTURE_SIZE: + params[0] = (GLfloat)(1 << (ctx->Const.MaxTextureLevels - 1)); + break; + case GL_MAX_3D_TEXTURE_SIZE: + params[0] = (GLfloat)(1 << (ctx->Const.Max3DTextureLevels - 1)); + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + params[0] = (GLfloat)(MAX_TEXTURE_STACK_DEPTH); + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = (GLfloat)(ctx->Const.MaxViewportWidth); + params[1] = (GLfloat)(ctx->Const.MaxViewportHeight); + break; + case GL_MODELVIEW_MATRIX: + { + const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m; + params[0] = matrix[0]; + params[1] = matrix[1]; + params[2] = matrix[2]; + params[3] = matrix[3]; + params[4] = matrix[4]; + params[5] = matrix[5]; + params[6] = matrix[6]; + params[7] = matrix[7]; + params[8] = matrix[8]; + params[9] = matrix[9]; + params[10] = matrix[10]; + params[11] = matrix[11]; + params[12] = matrix[12]; + params[13] = matrix[13]; + params[14] = matrix[14]; + params[15] = matrix[15]; + } + break; + case GL_MODELVIEW_STACK_DEPTH: + params[0] = (GLfloat)(ctx->ModelviewMatrixStack.Depth + 1); + break; + case GL_NAME_STACK_DEPTH: + params[0] = (GLfloat)(ctx->Select.NameStackDepth); + break; + case GL_NORMALIZE: + params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.Normalize); + break; + case GL_PACK_ALIGNMENT: + params[0] = (GLfloat)(ctx->Pack.Alignment); + break; + case GL_PACK_LSB_FIRST: + params[0] = BOOLEAN_TO_FLOAT(ctx->Pack.LsbFirst); + break; + case GL_PACK_ROW_LENGTH: + params[0] = (GLfloat)(ctx->Pack.RowLength); + break; + case GL_PACK_SKIP_PIXELS: + params[0] = (GLfloat)(ctx->Pack.SkipPixels); + break; + case GL_PACK_SKIP_ROWS: + params[0] = (GLfloat)(ctx->Pack.SkipRows); + break; + case GL_PACK_SWAP_BYTES: + params[0] = BOOLEAN_TO_FLOAT(ctx->Pack.SwapBytes); + break; + case GL_PACK_SKIP_IMAGES_EXT: + params[0] = (GLfloat)(ctx->Pack.SkipImages); + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + params[0] = (GLfloat)(ctx->Pack.ImageHeight); + break; + case GL_PACK_INVERT_MESA: + params[0] = BOOLEAN_TO_FLOAT(ctx->Pack.Invert); + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + params[0] = ENUM_TO_FLOAT(ctx->Hint.PerspectiveCorrection); + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapAtoAsize); + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapBtoBsize); + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapGtoGsize); + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapItoAsize); + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapItoBsize); + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapItoGsize); + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapItoIsize); + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapItoRsize); + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapRtoRsize); + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + params[0] = (GLfloat)(ctx->Pixel.MapStoSsize); + break; + case GL_POINT_SIZE: + params[0] = ctx->Point.Size; + break; + case GL_POINT_SIZE_GRANULARITY: + params[0] = ctx->Const.PointSizeGranularity; + break; + case GL_POINT_SIZE_RANGE: + params[0] = ctx->Const.MinPointSizeAA; + params[1] = ctx->Const.MaxPointSizeAA; + break; + case GL_ALIASED_POINT_SIZE_RANGE: + params[0] = ctx->Const.MinPointSize; + params[1] = ctx->Const.MaxPointSize; + break; + case GL_POINT_SMOOTH: + params[0] = BOOLEAN_TO_FLOAT(ctx->Point.SmoothFlag); + break; + case GL_POINT_SMOOTH_HINT: + params[0] = ENUM_TO_FLOAT(ctx->Hint.PointSmooth); + break; + case GL_POINT_SIZE_MIN_EXT: + params[0] = ctx->Point.MinSize; + break; + case GL_POINT_SIZE_MAX_EXT: + params[0] = ctx->Point.MaxSize; + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + params[0] = ctx->Point.Threshold; + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = ctx->Point.Params[0]; + params[1] = ctx->Point.Params[1]; + params[2] = ctx->Point.Params[2]; + break; + case GL_POLYGON_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Polygon.FrontMode); + params[1] = ENUM_TO_FLOAT(ctx->Polygon.BackMode); + break; + case GL_POLYGON_OFFSET_BIAS_EXT: + params[0] = ctx->Polygon.OffsetUnits; + break; + case GL_POLYGON_OFFSET_FACTOR: + params[0] = ctx->Polygon.OffsetFactor ; + break; + case GL_POLYGON_OFFSET_UNITS: + params[0] = ctx->Polygon.OffsetUnits ; + break; + case GL_POLYGON_SMOOTH: + params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.SmoothFlag); + break; + case GL_POLYGON_SMOOTH_HINT: + params[0] = ENUM_TO_FLOAT(ctx->Hint.PolygonSmooth); + break; + case GL_POLYGON_STIPPLE: + params[0] = BOOLEAN_TO_FLOAT(ctx->Polygon.StippleFlag); + break; + case GL_PROJECTION_MATRIX: + { + const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m; + params[0] = matrix[0]; + params[1] = matrix[1]; + params[2] = matrix[2]; + params[3] = matrix[3]; + params[4] = matrix[4]; + params[5] = matrix[5]; + params[6] = matrix[6]; + params[7] = matrix[7]; + params[8] = matrix[8]; + params[9] = matrix[9]; + params[10] = matrix[10]; + params[11] = matrix[11]; + params[12] = matrix[12]; + params[13] = matrix[13]; + params[14] = matrix[14]; + params[15] = matrix[15]; + } + break; + case GL_PROJECTION_STACK_DEPTH: + params[0] = (GLfloat)(ctx->ProjectionMatrixStack.Depth + 1); + break; + case GL_READ_BUFFER: + params[0] = ENUM_TO_FLOAT(ctx->Pixel.ReadBuffer); + break; + case GL_RED_BIAS: + params[0] = ctx->Pixel.RedBias; + break; + case GL_RED_BITS: + params[0] = (GLfloat)( ctx->DrawBuffer->Visual.redBits ); + break; + case GL_RED_SCALE: + params[0] = ctx->Pixel.RedScale; + break; + case GL_RENDER_MODE: + params[0] = ENUM_TO_FLOAT(ctx->RenderMode); + break; + case GL_RESCALE_NORMAL: + params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.RescaleNormals); + break; + case GL_RGBA_MODE: + params[0] = BOOLEAN_TO_FLOAT(ctx->DrawBuffer->Visual.rgbMode); + break; + case GL_SCISSOR_BOX: + params[0] = (GLfloat)(ctx->Scissor.X); + params[1] = (GLfloat)(ctx->Scissor.Y); + params[2] = (GLfloat)(ctx->Scissor.Width); + params[3] = (GLfloat)(ctx->Scissor.Height); + break; + case GL_SCISSOR_TEST: + params[0] = BOOLEAN_TO_FLOAT(ctx->Scissor.Enabled); + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = (GLfloat)(ctx->Select.BufferSize); + break; + case GL_SHADE_MODEL: + params[0] = ENUM_TO_FLOAT(ctx->Light.ShadeModel); + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + params[0] = BOOLEAN_TO_FLOAT(ctx->Texture.SharedPalette); + break; + case GL_STENCIL_BITS: + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.stencilBits); + break; + case GL_STENCIL_CLEAR_VALUE: + params[0] = (GLfloat)(ctx->Stencil.Clear); + break; + case GL_STENCIL_FAIL: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_FUNC: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.Function[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_PASS_DEPTH_PASS: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_REF: + params[0] = (GLfloat)(ctx->Stencil.Ref[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_TEST: + params[0] = BOOLEAN_TO_FLOAT(ctx->Stencil.Enabled); + break; + case GL_STENCIL_VALUE_MASK: + params[0] = (GLfloat)(ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_WRITEMASK: + params[0] = (GLfloat)(ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]); + break; + case GL_STEREO: + params[0] = BOOLEAN_TO_FLOAT(ctx->DrawBuffer->Visual.stereoMode); + break; + case GL_SUBPIXEL_BITS: + params[0] = (GLfloat)(ctx->Const.SubPixelBits); + break; + case GL_TEXTURE_1D: + params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_1D)); + break; + case GL_TEXTURE_2D: + params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_2D)); + break; + case GL_TEXTURE_3D: + params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_3D)); + break; + case GL_TEXTURE_BINDING_1D: + params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name); + break; + case GL_TEXTURE_BINDING_2D: + params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name); + break; + case GL_TEXTURE_BINDING_3D: + params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name); + break; + case GL_TEXTURE_ENV_COLOR: + { + const GLfloat *color = ctx->Texture.Unit[ctx->Texture.CurrentUnit].EnvColor; + params[0] = color[0]; + params[1] = color[1]; + params[2] = color[2]; + params[3] = color[3]; + } + break; + case GL_TEXTURE_ENV_MODE: + params[0] = ENUM_TO_FLOAT(ctx->Texture.Unit[ctx->Texture.CurrentUnit].EnvMode); + break; + case GL_TEXTURE_GEN_S: + params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_GEN_T: + params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_GEN_R: + params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_GEN_Q: + params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_MATRIX: + { + const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m; + params[0] = matrix[0]; + params[1] = matrix[1]; + params[2] = matrix[2]; + params[3] = matrix[3]; + params[4] = matrix[4]; + params[5] = matrix[5]; + params[6] = matrix[6]; + params[7] = matrix[7]; + params[8] = matrix[8]; + params[9] = matrix[9]; + params[10] = matrix[10]; + params[11] = matrix[11]; + params[12] = matrix[12]; + params[13] = matrix[13]; + params[14] = matrix[14]; + params[15] = matrix[15]; + } + break; + case GL_TEXTURE_STACK_DEPTH: + params[0] = (GLfloat)(ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1); + break; + case GL_UNPACK_ALIGNMENT: + params[0] = (GLfloat)(ctx->Unpack.Alignment); + break; + case GL_UNPACK_LSB_FIRST: + params[0] = BOOLEAN_TO_FLOAT(ctx->Unpack.LsbFirst); + break; + case GL_UNPACK_ROW_LENGTH: + params[0] = (GLfloat)(ctx->Unpack.RowLength); + break; + case GL_UNPACK_SKIP_PIXELS: + params[0] = (GLfloat)(ctx->Unpack.SkipPixels); + break; + case GL_UNPACK_SKIP_ROWS: + params[0] = (GLfloat)(ctx->Unpack.SkipRows); + break; + case GL_UNPACK_SWAP_BYTES: + params[0] = BOOLEAN_TO_FLOAT(ctx->Unpack.SwapBytes); + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + params[0] = (GLfloat)(ctx->Unpack.SkipImages); + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + params[0] = (GLfloat)(ctx->Unpack.ImageHeight); + break; + case GL_UNPACK_CLIENT_STORAGE_APPLE: + params[0] = BOOLEAN_TO_FLOAT(ctx->Unpack.ClientStorage); + break; + case GL_VIEWPORT: + params[0] = (GLfloat)(ctx->Viewport.X); + params[1] = (GLfloat)(ctx->Viewport.Y); + params[2] = (GLfloat)(ctx->Viewport.Width); + params[3] = (GLfloat)(ctx->Viewport.Height); + break; + case GL_ZOOM_X: + params[0] = ctx->Pixel.ZoomX; + break; + case GL_ZOOM_Y: + params[0] = ctx->Pixel.ZoomY; + break; + case GL_VERTEX_ARRAY: + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.Vertex.Enabled); + break; + case GL_VERTEX_ARRAY_SIZE: + params[0] = (GLfloat)(ctx->Array.Vertex.Size); + break; + case GL_VERTEX_ARRAY_TYPE: + params[0] = ENUM_TO_FLOAT(ctx->Array.Vertex.Type); + break; + case GL_VERTEX_ARRAY_STRIDE: + params[0] = (GLfloat)(ctx->Array.Vertex.Stride); + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + params[0] = (GLfloat)(0); + break; + case GL_NORMAL_ARRAY: + params[0] = ENUM_TO_FLOAT(ctx->Array.Normal.Enabled); + break; + case GL_NORMAL_ARRAY_TYPE: + params[0] = ENUM_TO_FLOAT(ctx->Array.Normal.Type); + break; + case GL_NORMAL_ARRAY_STRIDE: + params[0] = (GLfloat)(ctx->Array.Normal.Stride); + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + params[0] = (GLfloat)(0); + break; + case GL_COLOR_ARRAY: + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.Color.Enabled); + break; + case GL_COLOR_ARRAY_SIZE: + params[0] = (GLfloat)(ctx->Array.Color.Size); + break; + case GL_COLOR_ARRAY_TYPE: + params[0] = ENUM_TO_FLOAT(ctx->Array.Color.Type); + break; + case GL_COLOR_ARRAY_STRIDE: + params[0] = (GLfloat)(ctx->Array.Color.Stride); + break; + case GL_COLOR_ARRAY_COUNT_EXT: + params[0] = (GLfloat)(0); + break; + case GL_INDEX_ARRAY: + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.Index.Enabled); + break; + case GL_INDEX_ARRAY_TYPE: + params[0] = ENUM_TO_FLOAT(ctx->Array.Index.Type); + break; + case GL_INDEX_ARRAY_STRIDE: + params[0] = (GLfloat)(ctx->Array.Index.Stride); + break; + case GL_INDEX_ARRAY_COUNT_EXT: + params[0] = (GLfloat)(0); + break; + case GL_TEXTURE_COORD_ARRAY: + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Enabled); + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + params[0] = (GLfloat)(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Size); + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + params[0] = ENUM_TO_FLOAT(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Type); + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + params[0] = (GLfloat)(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Stride); + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + params[0] = (GLfloat)(0); + break; + case GL_EDGE_FLAG_ARRAY: + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.EdgeFlag.Enabled); + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + params[0] = (GLfloat)(ctx->Array.EdgeFlag.Stride); + break; + case GL_EDGE_FLAG_ARRAY_COUNT_EXT: + params[0] = (GLfloat)(0); + break; + case GL_MAX_TEXTURE_UNITS_ARB: + CHECK_EXTENSION_F(ARB_multitexture, pname); + params[0] = (GLfloat)(MIN2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits)); + break; + case GL_ACTIVE_TEXTURE_ARB: + CHECK_EXTENSION_F(ARB_multitexture, pname); + params[0] = (GLfloat)(GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit); + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + CHECK_EXTENSION_F(ARB_multitexture, pname); + params[0] = (GLfloat)(GL_TEXTURE0_ARB + ctx->Array.ActiveTexture); + break; + case GL_TEXTURE_CUBE_MAP_ARB: + CHECK_EXTENSION_F(ARB_texture_cube_map, pname); + params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB)); + break; + case GL_TEXTURE_BINDING_CUBE_MAP_ARB: + CHECK_EXTENSION_F(ARB_texture_cube_map, pname); + params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name); + break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: + CHECK_EXTENSION_F(ARB_texture_cube_map, pname); + params[0] = (GLfloat)((1 << (ctx->Const.MaxCubeTextureLevels - 1))); + break; + case GL_TEXTURE_COMPRESSION_HINT_ARB: + CHECK_EXTENSION_F(ARB_texture_compression, pname); + params[0] = (GLfloat)(ctx->Hint.TextureCompression); + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB: + CHECK_EXTENSION_F(ARB_texture_compression, pname); + params[0] = (GLfloat)(_mesa_get_compressed_formats(ctx, NULL)); + break; + case GL_COMPRESSED_TEXTURE_FORMATS_ARB: + CHECK_EXTENSION_F(ARB_texture_compression, pname); + { + GLint formats[100]; + GLuint i, n = _mesa_get_compressed_formats(ctx, formats); + ASSERT(n <= 100); + for (i = 0; i < n; i++) + params[i] = ENUM_TO_INT(formats[i]); + } + break; + case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT: + CHECK_EXTENSION_F(EXT_compiled_vertex_array, pname); + params[0] = (GLfloat)(ctx->Array.LockFirst); + break; + case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT: + CHECK_EXTENSION_F(EXT_compiled_vertex_array, pname); + params[0] = (GLfloat)(ctx->Array.LockCount); + break; + case GL_TRANSPOSE_COLOR_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ColorMatrixStack.Top->m; + params[0] = matrix[0]; + params[1] = matrix[4]; + params[2] = matrix[8]; + params[3] = matrix[12]; + params[4] = matrix[1]; + params[5] = matrix[5]; + params[6] = matrix[9]; + params[7] = matrix[13]; + params[8] = matrix[2]; + params[9] = matrix[6]; + params[10] = matrix[10]; + params[11] = matrix[14]; + params[12] = matrix[3]; + params[13] = matrix[7]; + params[14] = matrix[11]; + params[15] = matrix[15]; + } + break; + case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m; + params[0] = matrix[0]; + params[1] = matrix[4]; + params[2] = matrix[8]; + params[3] = matrix[12]; + params[4] = matrix[1]; + params[5] = matrix[5]; + params[6] = matrix[9]; + params[7] = matrix[13]; + params[8] = matrix[2]; + params[9] = matrix[6]; + params[10] = matrix[10]; + params[11] = matrix[14]; + params[12] = matrix[3]; + params[13] = matrix[7]; + params[14] = matrix[11]; + params[15] = matrix[15]; + } + break; + case GL_TRANSPOSE_PROJECTION_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m; + params[0] = matrix[0]; + params[1] = matrix[4]; + params[2] = matrix[8]; + params[3] = matrix[12]; + params[4] = matrix[1]; + params[5] = matrix[5]; + params[6] = matrix[9]; + params[7] = matrix[13]; + params[8] = matrix[2]; + params[9] = matrix[6]; + params[10] = matrix[10]; + params[11] = matrix[14]; + params[12] = matrix[3]; + params[13] = matrix[7]; + params[14] = matrix[11]; + params[15] = matrix[15]; + } + break; + case GL_TRANSPOSE_TEXTURE_MATRIX_ARB: + { + const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m; + params[0] = matrix[0]; + params[1] = matrix[4]; + params[2] = matrix[8]; + params[3] = matrix[12]; + params[4] = matrix[1]; + params[5] = matrix[5]; + params[6] = matrix[9]; + params[7] = matrix[13]; + params[8] = matrix[2]; + params[9] = matrix[6]; + params[10] = matrix[10]; + params[11] = matrix[14]; + params[12] = matrix[3]; + params[13] = matrix[7]; + params[14] = matrix[11]; + params[15] = matrix[15]; + } + break; + case GL_OCCLUSION_TEST_HP: + CHECK_EXTENSION_F(HP_occlusion_test, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.OcclusionTest); + break; + case GL_OCCLUSION_TEST_RESULT_HP: + CHECK_EXTENSION_F(HP_occlusion_test, pname); + { + FLUSH_VERTICES(ctx, _NEW_DEPTH); + if (ctx->Depth.OcclusionTest) + params[0] = ctx->OcclusionResult; + else + params[0] = ctx->OcclusionResultSaved; + /* reset flag now */ + ctx->OcclusionResult = GL_FALSE; + ctx->OcclusionResultSaved = GL_FALSE; + return; + } + break; + case GL_PIXEL_TEXTURE_SGIS: + CHECK_EXTENSION_F(SGIS_pixel_texture, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.PixelTextureEnabled); + break; + case GL_PIXEL_TEX_GEN_SGIX: + CHECK_EXTENSION_F(SGIX_pixel_texture, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.PixelTextureEnabled); + break; + case GL_PIXEL_TEX_GEN_MODE_SGIX: + CHECK_EXTENSION_F(SGIX_pixel_texture, pname); + params[0] = ENUM_TO_FLOAT(pixel_texgen_mode(ctx)); + break; + case GL_COLOR_MATRIX_SGI: + { + const GLfloat *matrix = ctx->ColorMatrixStack.Top->m; + params[0] = matrix[0]; + params[1] = matrix[1]; + params[2] = matrix[2]; + params[3] = matrix[3]; + params[4] = matrix[4]; + params[5] = matrix[5]; + params[6] = matrix[6]; + params[7] = matrix[7]; + params[8] = matrix[8]; + params[9] = matrix[9]; + params[10] = matrix[10]; + params[11] = matrix[11]; + params[12] = matrix[12]; + params[13] = matrix[13]; + params[14] = matrix[14]; + params[15] = matrix[15]; + } + break; + case GL_COLOR_MATRIX_STACK_DEPTH_SGI: + params[0] = (GLfloat)(ctx->ColorMatrixStack.Depth + 1); + break; + case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI: + params[0] = (GLfloat)(MAX_COLOR_STACK_DEPTH); + break; + case GL_POST_COLOR_MATRIX_RED_SCALE_SGI: + params[0] = ctx->Pixel.PostColorMatrixScale[0]; + break; + case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI: + params[0] = ctx->Pixel.PostColorMatrixScale[1]; + break; + case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI: + params[0] = ctx->Pixel.PostColorMatrixScale[2]; + break; + case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI: + params[0] = ctx->Pixel.PostColorMatrixScale[3]; + break; + case GL_POST_COLOR_MATRIX_RED_BIAS_SGI: + params[0] = ctx->Pixel.PostColorMatrixBias[0]; + break; + case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI: + params[0] = ctx->Pixel.PostColorMatrixBias[1]; + break; + case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI: + params[0] = ctx->Pixel.PostColorMatrixBias[2]; + break; + case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI: + params[0] = ctx->Pixel.PostColorMatrixBias[3]; + break; + case GL_CONVOLUTION_1D_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.Convolution1DEnabled); + break; + case GL_CONVOLUTION_2D_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.Convolution2DEnabled); + break; + case GL_SEPARABLE_2D_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.Separable2DEnabled); + break; + case GL_POST_CONVOLUTION_RED_SCALE_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionScale[0]; + break; + case GL_POST_CONVOLUTION_GREEN_SCALE_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionScale[1]; + break; + case GL_POST_CONVOLUTION_BLUE_SCALE_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionScale[2]; + break; + case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionScale[3]; + break; + case GL_POST_CONVOLUTION_RED_BIAS_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionBias[0]; + break; + case GL_POST_CONVOLUTION_GREEN_BIAS_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionBias[1]; + break; + case GL_POST_CONVOLUTION_BLUE_BIAS_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionBias[2]; + break; + case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT: + CHECK_EXTENSION_F(EXT_convolution, pname); + params[0] = ctx->Pixel.PostConvolutionBias[3]; + break; + case GL_HISTOGRAM: + CHECK_EXTENSION_F(EXT_histogram, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.HistogramEnabled); + break; + case GL_MINMAX: + CHECK_EXTENSION_F(EXT_histogram, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.MinMaxEnabled); + break; + case GL_COLOR_TABLE_SGI: + CHECK_EXTENSION_F(SGI_color_table, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.ColorTableEnabled); + break; + case GL_POST_CONVOLUTION_COLOR_TABLE_SGI: + CHECK_EXTENSION_F(SGI_color_table, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.PostConvolutionColorTableEnabled); + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI: + CHECK_EXTENSION_F(SGI_color_table, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Pixel.PostColorMatrixColorTableEnabled); + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + CHECK_EXTENSION_F(SGI_texture_color_table, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled); + break; + case GL_COLOR_SUM_EXT: + CHECK_EXTENSION_F(EXT_secondary_color, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Fog.ColorSumEnabled); + break; + case GL_CURRENT_SECONDARY_COLOR_EXT: + CHECK_EXTENSION_F(EXT_secondary_color, pname); + { + FLUSH_CURRENT(ctx, 0); + params[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]; + params[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]; + params[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]; + params[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]; + } + break; + case GL_SECONDARY_COLOR_ARRAY_EXT: + CHECK_EXTENSION_F(EXT_secondary_color, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.SecondaryColor.Enabled); + break; + case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT: + CHECK_EXTENSION_F(EXT_secondary_color, pname); + params[0] = ENUM_TO_FLOAT(ctx->Array.SecondaryColor.Type); + break; + case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT: + CHECK_EXTENSION_F(EXT_secondary_color, pname); + params[0] = (GLfloat)(ctx->Array.SecondaryColor.Stride); + break; + case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT: + CHECK_EXTENSION_F(EXT_secondary_color, pname); + params[0] = (GLfloat)(ctx->Array.SecondaryColor.Size); + break; + case GL_CURRENT_FOG_COORDINATE_EXT: + CHECK_EXTENSION_F(EXT_fog_coord, pname); + { + FLUSH_CURRENT(ctx, 0); + params[0] = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; + } + break; + case GL_FOG_COORDINATE_ARRAY_EXT: + CHECK_EXTENSION_F(EXT_fog_coord, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.FogCoord.Enabled); + break; + case GL_FOG_COORDINATE_ARRAY_TYPE_EXT: + CHECK_EXTENSION_F(EXT_fog_coord, pname); + params[0] = ENUM_TO_FLOAT(ctx->Array.FogCoord.Type); + break; + case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT: + CHECK_EXTENSION_F(EXT_fog_coord, pname); + params[0] = (GLfloat)(ctx->Array.FogCoord.Stride); + break; + case GL_FOG_COORDINATE_SOURCE_EXT: + CHECK_EXTENSION_F(EXT_fog_coord, pname); + params[0] = ENUM_TO_FLOAT(ctx->Fog.FogCoordinateSource); + break; + case GL_MAX_TEXTURE_LOD_BIAS_EXT: + CHECK_EXTENSION_F(EXT_texture_lod_bias, pname); + params[0] = ctx->Const.MaxTextureLodBias; + break; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + CHECK_EXTENSION_F(EXT_texture_filter_anisotropic, pname); + params[0] = ctx->Const.MaxTextureMaxAnisotropy; + break; + case GL_MULTISAMPLE_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.Enabled); + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleAlphaToCoverage); + break; + case GL_SAMPLE_ALPHA_TO_ONE_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleAlphaToOne); + break; + case GL_SAMPLE_COVERAGE_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleCoverage); + break; + case GL_SAMPLE_COVERAGE_VALUE_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = ctx->Multisample.SampleCoverageValue; + break; + case GL_SAMPLE_COVERAGE_INVERT_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Multisample.SampleCoverageInvert); + break; + case GL_SAMPLE_BUFFERS_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.sampleBuffers); + break; + case GL_SAMPLES_ARB: + CHECK_EXTENSION_F(ARB_multisample, pname); + params[0] = (GLfloat)(ctx->DrawBuffer->Visual.samples); + break; + case GL_RASTER_POSITION_UNCLIPPED_IBM: + CHECK_EXTENSION_F(IBM_rasterpos_clip, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Transform.RasterPositionUnclipped); + break; + case GL_POINT_SPRITE_NV: + CHECK_EXTENSION_F(NV_point_sprite, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Point.PointSprite); + break; + case GL_POINT_SPRITE_R_MODE_NV: + CHECK_EXTENSION_F(NV_point_sprite, pname); + params[0] = ENUM_TO_FLOAT(ctx->Point.SpriteRMode); + break; + case GL_POINT_SPRITE_COORD_ORIGIN: + CHECK_EXTENSION_F(NV_point_sprite, pname); + params[0] = ENUM_TO_FLOAT(ctx->Point.SpriteOrigin); + break; + case GL_GENERATE_MIPMAP_HINT_SGIS: + CHECK_EXTENSION_F(SGIS_generate_mipmap, pname); + params[0] = ENUM_TO_FLOAT(ctx->Hint.GenerateMipmap); + break; + case GL_VERTEX_PROGRAM_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.Enabled); + break; + case GL_VERTEX_PROGRAM_POINT_SIZE_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.PointSizeEnabled); + break; + case GL_VERTEX_PROGRAM_TWO_SIDE_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.TwoSideEnabled); + break; + case GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = (GLfloat)(ctx->Const.MaxProgramMatrixStackDepth); + break; + case GL_MAX_TRACK_MATRICES_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = (GLfloat)(ctx->Const.MaxProgramMatrices); + break; + case GL_CURRENT_MATRIX_STACK_DEPTH_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->CurrentStack->Depth + 1); + break; + case GL_CURRENT_MATRIX_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + { + const GLfloat *matrix = ctx->CurrentStack->Top->m; + params[0] = matrix[0]; + params[1] = matrix[1]; + params[2] = matrix[2]; + params[3] = matrix[3]; + params[4] = matrix[4]; + params[5] = matrix[5]; + params[6] = matrix[6]; + params[7] = matrix[7]; + params[8] = matrix[8]; + params[9] = matrix[9]; + params[10] = matrix[10]; + params[11] = matrix[11]; + params[12] = matrix[12]; + params[13] = matrix[13]; + params[14] = matrix[14]; + params[15] = matrix[15]; + } + break; + case GL_VERTEX_PROGRAM_BINDING_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = (GLfloat)((ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0)); + break; + case GL_PROGRAM_ERROR_POSITION_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = (GLfloat)(ctx->Program.ErrorPos); + break; + case GL_VERTEX_ATTRIB_ARRAY0_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[0].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY1_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[1].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY2_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[2].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY3_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[3].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[4].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY5_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[5].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY6_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[6].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY7_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[7].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY8_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[8].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY9_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[9].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY10_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[10].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY11_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[11].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY12_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[12].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY13_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[13].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY14_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[14].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY15_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Array.VertexAttrib[15].Enabled); + break; + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[0]); + break; + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[1]); + break; + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[2]); + break; + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[3]); + break; + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[4]); + break; + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[5]); + break; + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[6]); + break; + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[7]); + break; + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[8]); + break; + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[9]); + break; + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[10]); + break; + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[11]); + break; + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[12]); + break; + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[13]); + break; + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[14]); + break; + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION_F(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Eval.Map1Attrib[15]); + break; + case GL_FRAGMENT_PROGRAM_NV: + CHECK_EXTENSION_F(NV_fragment_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->FragmentProgram.Enabled); + break; + case GL_MAX_TEXTURE_COORDS_NV: + CHECK_EXTENSION_F(NV_fragment_program, pname); + params[0] = (GLfloat)(ctx->Const.MaxTextureCoordUnits); + break; + case GL_MAX_TEXTURE_IMAGE_UNITS_NV: + CHECK_EXTENSION_F(NV_fragment_program, pname); + params[0] = (GLfloat)(ctx->Const.MaxTextureImageUnits); + break; + case GL_FRAGMENT_PROGRAM_BINDING_NV: + CHECK_EXTENSION_F(NV_fragment_program, pname); + params[0] = (GLfloat)(ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0); + break; + case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV: + CHECK_EXTENSION_F(NV_fragment_program, pname); + params[0] = (GLfloat)(MAX_NV_FRAGMENT_PROGRAM_PARAMS); + break; + case GL_TEXTURE_RECTANGLE_NV: + CHECK_EXTENSION_F(NV_texture_rectangle, pname); + params[0] = BOOLEAN_TO_FLOAT(_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV)); + break; + case GL_TEXTURE_BINDING_RECTANGLE_NV: + CHECK_EXTENSION_F(NV_texture_rectangle, pname); + params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name); + break; + case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV: + CHECK_EXTENSION_F(NV_texture_rectangle, pname); + params[0] = (GLfloat)(ctx->Const.MaxTextureRectSize); + break; + case GL_STENCIL_TEST_TWO_SIDE_EXT: + CHECK_EXTENSION_F(EXT_stencil_two_side, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Stencil.TestTwoSide); + break; + case GL_ACTIVE_STENCIL_FACE_EXT: + CHECK_EXTENSION_F(EXT_stencil_two_side, pname); + params[0] = ENUM_TO_FLOAT(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT); + break; + case GL_MAX_SHININESS_NV: + CHECK_EXTENSION_F(NV_light_max_exponent, pname); + params[0] = ctx->Const.MaxShininess; + break; + case GL_MAX_SPOT_EXPONENT_NV: + CHECK_EXTENSION_F(NV_light_max_exponent, pname); + params[0] = ctx->Const.MaxSpotExponent; + break; + case GL_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.ArrayBufferObj->Name); + break; + case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.Vertex.BufferObj->Name); + break; + case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.Normal.BufferObj->Name); + break; + case GL_COLOR_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.Color.BufferObj->Name); + break; + case GL_INDEX_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.Index.BufferObj->Name); + break; + case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.TexCoord[ctx->Array.ActiveTexture].BufferObj->Name); + break; + case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.EdgeFlag.BufferObj->Name); + break; + case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.SecondaryColor.BufferObj->Name); + break; + case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.FogCoord.BufferObj->Name); + break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_F(ARB_vertex_buffer_object, pname); + params[0] = (GLfloat)(ctx->Array.ElementArrayBufferObj->Name); + break; + case GL_PIXEL_PACK_BUFFER_BINDING_EXT: + CHECK_EXTENSION_F(EXT_pixel_buffer_object, pname); + params[0] = (GLfloat)(ctx->Pack.BufferObj->Name); + break; + case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT: + CHECK_EXTENSION_F(EXT_pixel_buffer_object, pname); + params[0] = (GLfloat)(ctx->Unpack.BufferObj->Name); + break; + case GL_MAX_VERTEX_ATTRIBS_ARB: + CHECK_EXTENSION_F(ARB_vertex_program, pname); + params[0] = (GLfloat)(ctx->Const.MaxVertexProgramAttribs); + break; + case GL_FRAGMENT_PROGRAM_ARB: + CHECK_EXTENSION_F(ARB_fragment_program, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->FragmentProgram.Enabled); + break; + case GL_TRANSPOSE_CURRENT_MATRIX_ARB: + CHECK_EXTENSION_F(ARB_fragment_program, pname); + { + const GLfloat *matrix = ctx->CurrentStack->Top->m; + params[0] = matrix[0]; + params[1] = matrix[4]; + params[2] = matrix[8]; + params[3] = matrix[12]; + params[4] = matrix[1]; + params[5] = matrix[5]; + params[6] = matrix[9]; + params[7] = matrix[13]; + params[8] = matrix[2]; + params[9] = matrix[6]; + params[10] = matrix[10]; + params[11] = matrix[14]; + params[12] = matrix[3]; + params[13] = matrix[7]; + params[14] = matrix[11]; + params[15] = matrix[15]; + } + break; + case GL_DEPTH_BOUNDS_TEST_EXT: + CHECK_EXTENSION_F(EXT_depth_bounds_test, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->Depth.BoundsTest); + break; + case GL_DEPTH_BOUNDS_EXT: + CHECK_EXTENSION_F(EXT_depth_bounds_test, pname); + params[0] = ctx->Depth.BoundsMin; + params[1] = ctx->Depth.BoundsMax; + break; + case GL_FRAGMENT_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION_F(MESA_program_debug, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->FragmentProgram.CallbackEnabled); + break; + case GL_VERTEX_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION_F(MESA_program_debug, pname); + params[0] = BOOLEAN_TO_FLOAT(ctx->VertexProgram.CallbackEnabled); + break; + case GL_FRAGMENT_PROGRAM_POSITION_MESA: + CHECK_EXTENSION_F(MESA_program_debug, pname); + params[0] = (GLfloat)(ctx->FragmentProgram.CurrentPosition); + break; + case GL_VERTEX_PROGRAM_POSITION_MESA: + CHECK_EXTENSION_F(MESA_program_debug, pname); + params[0] = (GLfloat)(ctx->VertexProgram.CurrentPosition); + break; + case GL_MAX_DRAW_BUFFERS_ARB: + CHECK_EXTENSION_F(ARB_draw_buffers, pname); + params[0] = (GLfloat)(ctx->Const.MaxDrawBuffers); + break; + case GL_DRAW_BUFFER0_ARB: + CHECK_EXTENSION_F(ARB_draw_buffers, pname); + params[0] = ENUM_TO_FLOAT(ctx->Color.DrawBuffer[0]); + break; + case GL_DRAW_BUFFER1_ARB: + CHECK_EXTENSION_F(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[1]; + params[0] = ENUM_TO_FLOAT(buffer); + } + break; + case GL_DRAW_BUFFER2_ARB: + CHECK_EXTENSION_F(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[2]; + params[0] = ENUM_TO_FLOAT(buffer); + } + break; + case GL_DRAW_BUFFER3_ARB: + CHECK_EXTENSION_F(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[3]; + params[0] = ENUM_TO_FLOAT(buffer); + } + break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + CHECK_EXTENSION_F(OES_read_format, pname); + params[0] = (GLfloat)(ctx->Const.ColorReadType); + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + CHECK_EXTENSION_F(OES_read_format, pname); + params[0] = (GLfloat)(ctx->Const.ColorReadFormat); + break; + case GL_NUM_FRAGMENT_REGISTERS_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(6); + break; + case GL_NUM_FRAGMENT_CONSTANTS_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(8); + break; + case GL_NUM_PASSES_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(2); + break; + case GL_NUM_INSTRUCTIONS_PER_PASS_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(8); + break; + case GL_NUM_INSTRUCTIONS_TOTAL_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(16); + break; + case GL_COLOR_ALPHA_PAIRING_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = BOOLEAN_TO_FLOAT(GL_TRUE); + break; + case GL_NUM_LOOPBACK_COMPONENTS_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(3); + break; + case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI: + CHECK_EXTENSION_F(ATI_fragment_shader, pname); + params[0] = (GLfloat)(3); + break; + case GL_STENCIL_BACK_FUNC: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.Function[1]); + break; + case GL_STENCIL_BACK_VALUE_MASK: + params[0] = (GLfloat)(ctx->Stencil.ValueMask[1]); + break; + case GL_STENCIL_BACK_REF: + params[0] = (GLfloat)(ctx->Stencil.Ref[1]); + break; + case GL_STENCIL_BACK_FAIL: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.FailFunc[1]); + break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZFailFunc[1]); + break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + params[0] = ENUM_TO_FLOAT(ctx->Stencil.ZPassFunc[1]); + break; + case GL_FRAMEBUFFER_BINDING_EXT: + CHECK_EXTENSION_F(EXT_framebuffer_object, pname); + params[0] = (GLfloat)(ctx->DrawBuffer->Name); + break; + case GL_RENDERBUFFER_BINDING_EXT: + CHECK_EXTENSION_F(EXT_framebuffer_object, pname); + params[0] = (GLfloat)(ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0); + break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: + CHECK_EXTENSION_F(EXT_framebuffer_object, pname); + params[0] = (GLfloat)(ctx->Const.MaxColorAttachments); + break; + case GL_MAX_RENDERBUFFER_SIZE_EXT: + CHECK_EXTENSION_F(EXT_framebuffer_object, pname); + params[0] = (GLfloat)(ctx->Const.MaxRenderbufferSize); + break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB: + CHECK_EXTENSION_F(ARB_fragment_shader, pname); + params[0] = (GLfloat)(MAX_FRAGMENT_UNIFORM_COMPONENTS); + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB: + CHECK_EXTENSION_F(ARB_fragment_shader, pname); + params[0] = ENUM_TO_FLOAT(ctx->Hint.FragmentShaderDerivative); + break; + case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB: + CHECK_EXTENSION_F(ARB_vertex_shader, pname); + params[0] = (GLfloat)(MAX_VERTEX_UNIFORM_COMPONENTS); + break; + case GL_MAX_VARYING_FLOATS_ARB: + CHECK_EXTENSION_F(ARB_vertex_shader, pname); + params[0] = (GLfloat)(MAX_VARYING_FLOATS); + break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB: + CHECK_EXTENSION_F(ARB_vertex_shader, pname); + params[0] = (GLfloat)(MAX_VERTEX_TEXTURE_IMAGE_UNITS); + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB: + CHECK_EXTENSION_F(ARB_vertex_shader, pname); + params[0] = (GLfloat)(MAX_COMBINED_TEXTURE_IMAGE_UNITS); + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(pname=0x%x)", pname); + } +} + +void GLAPIENTRY +_mesa_GetIntegerv( GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!params) + return; + + if (ctx->NewState) + _mesa_update_state(ctx); + + if (ctx->Driver.GetIntegerv && + ctx->Driver.GetIntegerv(ctx, pname, params)) + return; + + switch (pname) { + case GL_ACCUM_RED_BITS: + params[0] = ctx->DrawBuffer->Visual.accumRedBits; + break; + case GL_ACCUM_GREEN_BITS: + params[0] = ctx->DrawBuffer->Visual.accumGreenBits; + break; + case GL_ACCUM_BLUE_BITS: + params[0] = ctx->DrawBuffer->Visual.accumBlueBits; + break; + case GL_ACCUM_ALPHA_BITS: + params[0] = ctx->DrawBuffer->Visual.accumAlphaBits; + break; + case GL_ACCUM_CLEAR_VALUE: + params[0] = FLOAT_TO_INT(ctx->Accum.ClearColor[0]); + params[1] = FLOAT_TO_INT(ctx->Accum.ClearColor[1]); + params[2] = FLOAT_TO_INT(ctx->Accum.ClearColor[2]); + params[3] = FLOAT_TO_INT(ctx->Accum.ClearColor[3]); + break; + case GL_ALPHA_BIAS: + params[0] = IROUND(ctx->Pixel.AlphaBias); + break; + case GL_ALPHA_BITS: + params[0] = ctx->DrawBuffer->Visual.alphaBits; + break; + case GL_ALPHA_SCALE: + params[0] = IROUND(ctx->Pixel.AlphaScale); + break; + case GL_ALPHA_TEST: + params[0] = BOOLEAN_TO_INT(ctx->Color.AlphaEnabled); + break; + case GL_ALPHA_TEST_FUNC: + params[0] = ENUM_TO_INT(ctx->Color.AlphaFunc); + break; + case GL_ALPHA_TEST_REF: + params[0] = FLOAT_TO_INT(ctx->Color.AlphaRef); + break; + case GL_ATTRIB_STACK_DEPTH: + params[0] = ctx->AttribStackDepth; + break; + case GL_AUTO_NORMAL: + params[0] = BOOLEAN_TO_INT(ctx->Eval.AutoNormal); + break; + case GL_AUX_BUFFERS: + params[0] = ctx->DrawBuffer->Visual.numAuxBuffers; + break; + case GL_BLEND: + params[0] = BOOLEAN_TO_INT(ctx->Color.BlendEnabled); + break; + case GL_BLEND_DST: + params[0] = ENUM_TO_INT(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC: + params[0] = ENUM_TO_INT(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_SRC_RGB_EXT: + params[0] = ENUM_TO_INT(ctx->Color.BlendSrcRGB); + break; + case GL_BLEND_DST_RGB_EXT: + params[0] = ENUM_TO_INT(ctx->Color.BlendDstRGB); + break; + case GL_BLEND_SRC_ALPHA_EXT: + params[0] = ENUM_TO_INT(ctx->Color.BlendSrcA); + break; + case GL_BLEND_DST_ALPHA_EXT: + params[0] = ENUM_TO_INT(ctx->Color.BlendDstA); + break; + case GL_BLEND_EQUATION: + params[0] = ENUM_TO_INT(ctx->Color.BlendEquationRGB ); + break; + case GL_BLEND_EQUATION_ALPHA_EXT: + params[0] = ENUM_TO_INT(ctx->Color.BlendEquationA ); + break; + case GL_BLEND_COLOR_EXT: + params[0] = FLOAT_TO_INT(ctx->Color.BlendColor[0]); + params[1] = FLOAT_TO_INT(ctx->Color.BlendColor[1]); + params[2] = FLOAT_TO_INT(ctx->Color.BlendColor[2]); + params[3] = FLOAT_TO_INT(ctx->Color.BlendColor[3]); + break; + case GL_BLUE_BIAS: + params[0] = IROUND(ctx->Pixel.BlueBias); + break; + case GL_BLUE_BITS: + params[0] = ctx->DrawBuffer->Visual.blueBits; + break; + case GL_BLUE_SCALE: + params[0] = IROUND(ctx->Pixel.BlueScale); + break; + case GL_CLIENT_ATTRIB_STACK_DEPTH: + params[0] = ctx->ClientAttribStackDepth; + break; + case GL_CLIP_PLANE0: + params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 0) & 1); + break; + case GL_CLIP_PLANE1: + params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 1) & 1); + break; + case GL_CLIP_PLANE2: + params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 2) & 1); + break; + case GL_CLIP_PLANE3: + params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 3) & 1); + break; + case GL_CLIP_PLANE4: + params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 4) & 1); + break; + case GL_CLIP_PLANE5: + params[0] = BOOLEAN_TO_INT((ctx->Transform.ClipPlanesEnabled >> 5) & 1); + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = FLOAT_TO_INT(ctx->Color.ClearColor[0]); + params[1] = FLOAT_TO_INT(ctx->Color.ClearColor[1]); + params[2] = FLOAT_TO_INT(ctx->Color.ClearColor[2]); + params[3] = FLOAT_TO_INT(ctx->Color.ClearColor[3]); + break; + case GL_COLOR_MATERIAL: + params[0] = BOOLEAN_TO_INT(ctx->Light.ColorMaterialEnabled); + break; + case GL_COLOR_MATERIAL_FACE: + params[0] = ENUM_TO_INT(ctx->Light.ColorMaterialFace); + break; + case GL_COLOR_MATERIAL_PARAMETER: + params[0] = ENUM_TO_INT(ctx->Light.ColorMaterialMode); + break; + case GL_COLOR_WRITEMASK: + params[0] = ctx->Color.ColorMask[RCOMP] ? 1 : 0; + params[1] = ctx->Color.ColorMask[GCOMP] ? 1 : 0; + params[2] = ctx->Color.ColorMask[BCOMP] ? 1 : 0; + params[3] = ctx->Color.ColorMask[ACOMP] ? 1 : 0; + break; + case GL_CULL_FACE: + params[0] = BOOLEAN_TO_INT(ctx->Polygon.CullFlag); + break; + case GL_CULL_FACE_MODE: + params[0] = ENUM_TO_INT(ctx->Polygon.CullFaceMode); + break; + case GL_CURRENT_COLOR: + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0]); + params[1] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1]); + params[2] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2]); + params[3] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3]); + } + break; + case GL_CURRENT_INDEX: + { + FLUSH_CURRENT(ctx, 0); + params[0] = IROUND(ctx->Current.Index); + } + break; + case GL_CURRENT_NORMAL: + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0]); + params[1] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1]); + params[2] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2]); + } + break; + case GL_CURRENT_RASTER_COLOR: + params[0] = FLOAT_TO_INT(ctx->Current.RasterColor[0]); + params[1] = FLOAT_TO_INT(ctx->Current.RasterColor[1]); + params[2] = FLOAT_TO_INT(ctx->Current.RasterColor[2]); + params[3] = FLOAT_TO_INT(ctx->Current.RasterColor[3]); + break; + case GL_CURRENT_RASTER_DISTANCE: + params[0] = IROUND(ctx->Current.RasterDistance); + break; + case GL_CURRENT_RASTER_INDEX: + params[0] = IROUND(ctx->Current.RasterIndex); + break; + case GL_CURRENT_RASTER_POSITION: + params[0] = IROUND(ctx->Current.RasterPos[0]); + params[1] = IROUND(ctx->Current.RasterPos[1]); + params[2] = IROUND(ctx->Current.RasterPos[2]); + params[3] = IROUND(ctx->Current.RasterPos[3]); + break; + case GL_CURRENT_RASTER_TEXTURE_COORDS: + { + const GLuint texUnit = ctx->Texture.CurrentUnit; + params[0] = IROUND(ctx->Current.RasterTexCoords[texUnit][0]); + params[1] = IROUND(ctx->Current.RasterTexCoords[texUnit][1]); + params[2] = IROUND(ctx->Current.RasterTexCoords[texUnit][2]); + params[3] = IROUND(ctx->Current.RasterTexCoords[texUnit][3]); + } + break; + case GL_CURRENT_RASTER_POSITION_VALID: + params[0] = BOOLEAN_TO_INT(ctx->Current.RasterPosValid); + break; + case GL_CURRENT_TEXTURE_COORDS: + { + const GLuint texUnit = ctx->Texture.CurrentUnit; + params[0] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][0]); + params[1] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][1]); + params[2] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][2]); + params[3] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texUnit][3]); + } + break; + case GL_DEPTH_BIAS: + params[0] = IROUND(ctx->Pixel.DepthBias); + break; + case GL_DEPTH_BITS: + params[0] = ctx->DrawBuffer->Visual.depthBits; + break; + case GL_DEPTH_CLEAR_VALUE: + params[0] = IROUND(ctx->Depth.Clear); + break; + case GL_DEPTH_FUNC: + params[0] = ENUM_TO_INT(ctx->Depth.Func); + break; + case GL_DEPTH_RANGE: + params[0] = FLOAT_TO_INT(ctx->Viewport.Near); + params[1] = FLOAT_TO_INT(ctx->Viewport.Far); + break; + case GL_DEPTH_SCALE: + params[0] = IROUND(ctx->Pixel.DepthScale); + break; + case GL_DEPTH_TEST: + params[0] = BOOLEAN_TO_INT(ctx->Depth.Test); + break; + case GL_DEPTH_WRITEMASK: + params[0] = BOOLEAN_TO_INT(ctx->Depth.Mask); + break; + case GL_DITHER: + params[0] = BOOLEAN_TO_INT(ctx->Color.DitherFlag); + break; + case GL_DOUBLEBUFFER: + params[0] = BOOLEAN_TO_INT(ctx->DrawBuffer->Visual.doubleBufferMode); + break; + case GL_DRAW_BUFFER: + params[0] = ENUM_TO_INT(ctx->Color.DrawBuffer[0]); + break; + case GL_EDGE_FLAG: + { + FLUSH_CURRENT(ctx, 0); + params[0] = BOOLEAN_TO_INT(ctx->Current.EdgeFlag); + } + break; + case GL_FEEDBACK_BUFFER_SIZE: + params[0] = ctx->Feedback.BufferSize; + break; + case GL_FEEDBACK_BUFFER_TYPE: + params[0] = ENUM_TO_INT(ctx->Feedback.Type); + break; + case GL_FOG: + params[0] = BOOLEAN_TO_INT(ctx->Fog.Enabled); + break; + case GL_FOG_COLOR: + params[0] = FLOAT_TO_INT(ctx->Fog.Color[0]); + params[1] = FLOAT_TO_INT(ctx->Fog.Color[1]); + params[2] = FLOAT_TO_INT(ctx->Fog.Color[2]); + params[3] = FLOAT_TO_INT(ctx->Fog.Color[3]); + break; + case GL_FOG_DENSITY: + params[0] = IROUND(ctx->Fog.Density); + break; + case GL_FOG_END: + params[0] = IROUND(ctx->Fog.End); + break; + case GL_FOG_HINT: + params[0] = ENUM_TO_INT(ctx->Hint.Fog); + break; + case GL_FOG_INDEX: + params[0] = IROUND(ctx->Fog.Index); + break; + case GL_FOG_MODE: + params[0] = ENUM_TO_INT(ctx->Fog.Mode); + break; + case GL_FOG_START: + params[0] = IROUND(ctx->Fog.Start); + break; + case GL_FRONT_FACE: + params[0] = ENUM_TO_INT(ctx->Polygon.FrontFace); + break; + case GL_GREEN_BIAS: + params[0] = IROUND(ctx->Pixel.GreenBias); + break; + case GL_GREEN_BITS: + params[0] = ctx->DrawBuffer->Visual.greenBits; + break; + case GL_GREEN_SCALE: + params[0] = IROUND(ctx->Pixel.GreenScale); + break; + case GL_INDEX_BITS: + params[0] = ctx->DrawBuffer->Visual.indexBits; + break; + case GL_INDEX_CLEAR_VALUE: + params[0] = ctx->Color.ClearIndex; + break; + case GL_INDEX_MODE: + params[0] = BOOLEAN_TO_INT(!ctx->DrawBuffer->Visual.rgbMode); + break; + case GL_INDEX_OFFSET: + params[0] = ctx->Pixel.IndexOffset; + break; + case GL_INDEX_SHIFT: + params[0] = ctx->Pixel.IndexShift; + break; + case GL_INDEX_WRITEMASK: + params[0] = ctx->Color.IndexMask; + break; + case GL_LIGHT0: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[0].Enabled); + break; + case GL_LIGHT1: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[1].Enabled); + break; + case GL_LIGHT2: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[2].Enabled); + break; + case GL_LIGHT3: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[3].Enabled); + break; + case GL_LIGHT4: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[4].Enabled); + break; + case GL_LIGHT5: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[5].Enabled); + break; + case GL_LIGHT6: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[6].Enabled); + break; + case GL_LIGHT7: + params[0] = BOOLEAN_TO_INT(ctx->Light.Light[7].Enabled); + break; + case GL_LIGHTING: + params[0] = BOOLEAN_TO_INT(ctx->Light.Enabled); + break; + case GL_LIGHT_MODEL_AMBIENT: + params[0] = FLOAT_TO_INT(ctx->Light.Model.Ambient[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Model.Ambient[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Model.Ambient[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Model.Ambient[3]); + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + params[0] = ENUM_TO_INT(ctx->Light.Model.ColorControl); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + params[0] = BOOLEAN_TO_INT(ctx->Light.Model.LocalViewer); + break; + case GL_LIGHT_MODEL_TWO_SIDE: + params[0] = BOOLEAN_TO_INT(ctx->Light.Model.TwoSide); + break; + case GL_LINE_SMOOTH: + params[0] = BOOLEAN_TO_INT(ctx->Line.SmoothFlag); + break; + case GL_LINE_SMOOTH_HINT: + params[0] = ENUM_TO_INT(ctx->Hint.LineSmooth); + break; + case GL_LINE_STIPPLE: + params[0] = BOOLEAN_TO_INT(ctx->Line.StippleFlag); + break; + case GL_LINE_STIPPLE_PATTERN: + params[0] = ctx->Line.StipplePattern; + break; + case GL_LINE_STIPPLE_REPEAT: + params[0] = ctx->Line.StippleFactor; + break; + case GL_LINE_WIDTH: + params[0] = IROUND(ctx->Line.Width); + break; + case GL_LINE_WIDTH_GRANULARITY: + params[0] = IROUND(ctx->Const.LineWidthGranularity); + break; + case GL_LINE_WIDTH_RANGE: + params[0] = IROUND(ctx->Const.MinLineWidthAA); + params[1] = IROUND(ctx->Const.MaxLineWidthAA); + break; + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = IROUND(ctx->Const.MinLineWidth); + params[1] = IROUND(ctx->Const.MaxLineWidth); + break; + case GL_LIST_BASE: + params[0] = ctx->List.ListBase; + break; + case GL_LIST_INDEX: + params[0] = ctx->ListState.CurrentListNum; + break; + case GL_LIST_MODE: + { + GLenum mode; + if (!ctx->CompileFlag) + mode = 0; + else if (ctx->ExecuteFlag) + mode = GL_COMPILE_AND_EXECUTE; + else + mode = GL_COMPILE; + params[0] = ENUM_TO_INT(mode); + } + break; + case GL_INDEX_LOGIC_OP: + params[0] = BOOLEAN_TO_INT(ctx->Color.IndexLogicOpEnabled); + break; + case GL_COLOR_LOGIC_OP: + params[0] = BOOLEAN_TO_INT(ctx->Color.ColorLogicOpEnabled); + break; + case GL_LOGIC_OP_MODE: + params[0] = ENUM_TO_INT(ctx->Color.LogicOp); + break; + case GL_MAP1_COLOR_4: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Color4); + break; + case GL_MAP1_GRID_DOMAIN: + params[0] = IROUND(ctx->Eval.MapGrid1u1); + params[1] = IROUND(ctx->Eval.MapGrid1u2); + break; + case GL_MAP1_GRID_SEGMENTS: + params[0] = ctx->Eval.MapGrid1un; + break; + case GL_MAP1_INDEX: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Index); + break; + case GL_MAP1_NORMAL: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Normal); + break; + case GL_MAP1_TEXTURE_COORD_1: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord1); + break; + case GL_MAP1_TEXTURE_COORD_2: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord2); + break; + case GL_MAP1_TEXTURE_COORD_3: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord3); + break; + case GL_MAP1_TEXTURE_COORD_4: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1TextureCoord4); + break; + case GL_MAP1_VERTEX_3: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Vertex3); + break; + case GL_MAP1_VERTEX_4: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Vertex4); + break; + case GL_MAP2_COLOR_4: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Color4); + break; + case GL_MAP2_GRID_DOMAIN: + params[0] = IROUND(ctx->Eval.MapGrid2u1); + params[1] = IROUND(ctx->Eval.MapGrid2u2); + params[2] = IROUND(ctx->Eval.MapGrid2v1); + params[3] = IROUND(ctx->Eval.MapGrid2v2); + break; + case GL_MAP2_GRID_SEGMENTS: + params[0] = ctx->Eval.MapGrid2un; + params[1] = ctx->Eval.MapGrid2vn; + break; + case GL_MAP2_INDEX: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Index); + break; + case GL_MAP2_NORMAL: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Normal); + break; + case GL_MAP2_TEXTURE_COORD_1: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord1); + break; + case GL_MAP2_TEXTURE_COORD_2: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord2); + break; + case GL_MAP2_TEXTURE_COORD_3: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord3); + break; + case GL_MAP2_TEXTURE_COORD_4: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2TextureCoord4); + break; + case GL_MAP2_VERTEX_3: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Vertex3); + break; + case GL_MAP2_VERTEX_4: + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map2Vertex4); + break; + case GL_MAP_COLOR: + params[0] = BOOLEAN_TO_INT(ctx->Pixel.MapColorFlag); + break; + case GL_MAP_STENCIL: + params[0] = BOOLEAN_TO_INT(ctx->Pixel.MapStencilFlag); + break; + case GL_MATRIX_MODE: + params[0] = ENUM_TO_INT(ctx->Transform.MatrixMode); + break; + case GL_MAX_ATTRIB_STACK_DEPTH: + params[0] = MAX_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: + params[0] = MAX_CLIENT_ATTRIB_STACK_DEPTH; + break; + case GL_MAX_CLIP_PLANES: + params[0] = ctx->Const.MaxClipPlanes; + break; + case GL_MAX_ELEMENTS_VERTICES: + params[0] = ctx->Const.MaxArrayLockSize; + break; + case GL_MAX_ELEMENTS_INDICES: + params[0] = ctx->Const.MaxArrayLockSize; + break; + case GL_MAX_EVAL_ORDER: + params[0] = MAX_EVAL_ORDER; + break; + case GL_MAX_LIGHTS: + params[0] = ctx->Const.MaxLights; + break; + case GL_MAX_LIST_NESTING: + params[0] = MAX_LIST_NESTING; + break; + case GL_MAX_MODELVIEW_STACK_DEPTH: + params[0] = MAX_MODELVIEW_STACK_DEPTH; + break; + case GL_MAX_NAME_STACK_DEPTH: + params[0] = MAX_NAME_STACK_DEPTH; + break; + case GL_MAX_PIXEL_MAP_TABLE: + params[0] = MAX_PIXEL_MAP_TABLE; + break; + case GL_MAX_PROJECTION_STACK_DEPTH: + params[0] = MAX_PROJECTION_STACK_DEPTH; + break; + case GL_MAX_TEXTURE_SIZE: + params[0] = 1 << (ctx->Const.MaxTextureLevels - 1); + break; + case GL_MAX_3D_TEXTURE_SIZE: + params[0] = 1 << (ctx->Const.Max3DTextureLevels - 1); + break; + case GL_MAX_TEXTURE_STACK_DEPTH: + params[0] = MAX_TEXTURE_STACK_DEPTH; + break; + case GL_MAX_VIEWPORT_DIMS: + params[0] = ctx->Const.MaxViewportWidth; + params[1] = ctx->Const.MaxViewportHeight; + break; + case GL_MODELVIEW_MATRIX: + { + const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[1]); + params[2] = IROUND(matrix[2]); + params[3] = IROUND(matrix[3]); + params[4] = IROUND(matrix[4]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[6]); + params[7] = IROUND(matrix[7]); + params[8] = IROUND(matrix[8]); + params[9] = IROUND(matrix[9]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[11]); + params[12] = IROUND(matrix[12]); + params[13] = IROUND(matrix[13]); + params[14] = IROUND(matrix[14]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_MODELVIEW_STACK_DEPTH: + params[0] = ctx->ModelviewMatrixStack.Depth + 1; + break; + case GL_NAME_STACK_DEPTH: + params[0] = ctx->Select.NameStackDepth; + break; + case GL_NORMALIZE: + params[0] = BOOLEAN_TO_INT(ctx->Transform.Normalize); + break; + case GL_PACK_ALIGNMENT: + params[0] = ctx->Pack.Alignment; + break; + case GL_PACK_LSB_FIRST: + params[0] = BOOLEAN_TO_INT(ctx->Pack.LsbFirst); + break; + case GL_PACK_ROW_LENGTH: + params[0] = ctx->Pack.RowLength; + break; + case GL_PACK_SKIP_PIXELS: + params[0] = ctx->Pack.SkipPixels; + break; + case GL_PACK_SKIP_ROWS: + params[0] = ctx->Pack.SkipRows; + break; + case GL_PACK_SWAP_BYTES: + params[0] = BOOLEAN_TO_INT(ctx->Pack.SwapBytes); + break; + case GL_PACK_SKIP_IMAGES_EXT: + params[0] = ctx->Pack.SkipImages; + break; + case GL_PACK_IMAGE_HEIGHT_EXT: + params[0] = ctx->Pack.ImageHeight; + break; + case GL_PACK_INVERT_MESA: + params[0] = BOOLEAN_TO_INT(ctx->Pack.Invert); + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + params[0] = ENUM_TO_INT(ctx->Hint.PerspectiveCorrection); + break; + case GL_PIXEL_MAP_A_TO_A_SIZE: + params[0] = ctx->Pixel.MapAtoAsize; + break; + case GL_PIXEL_MAP_B_TO_B_SIZE: + params[0] = ctx->Pixel.MapBtoBsize; + break; + case GL_PIXEL_MAP_G_TO_G_SIZE: + params[0] = ctx->Pixel.MapGtoGsize; + break; + case GL_PIXEL_MAP_I_TO_A_SIZE: + params[0] = ctx->Pixel.MapItoAsize; + break; + case GL_PIXEL_MAP_I_TO_B_SIZE: + params[0] = ctx->Pixel.MapItoBsize; + break; + case GL_PIXEL_MAP_I_TO_G_SIZE: + params[0] = ctx->Pixel.MapItoGsize; + break; + case GL_PIXEL_MAP_I_TO_I_SIZE: + params[0] = ctx->Pixel.MapItoIsize; + break; + case GL_PIXEL_MAP_I_TO_R_SIZE: + params[0] = ctx->Pixel.MapItoRsize; + break; + case GL_PIXEL_MAP_R_TO_R_SIZE: + params[0] = ctx->Pixel.MapRtoRsize; + break; + case GL_PIXEL_MAP_S_TO_S_SIZE: + params[0] = ctx->Pixel.MapStoSsize; + break; + case GL_POINT_SIZE: + params[0] = IROUND(ctx->Point.Size); + break; + case GL_POINT_SIZE_GRANULARITY: + params[0] = IROUND(ctx->Const.PointSizeGranularity); + break; + case GL_POINT_SIZE_RANGE: + params[0] = IROUND(ctx->Const.MinPointSizeAA); + params[1] = IROUND(ctx->Const.MaxPointSizeAA); + break; + case GL_ALIASED_POINT_SIZE_RANGE: + params[0] = IROUND(ctx->Const.MinPointSize); + params[1] = IROUND(ctx->Const.MaxPointSize); + break; + case GL_POINT_SMOOTH: + params[0] = BOOLEAN_TO_INT(ctx->Point.SmoothFlag); + break; + case GL_POINT_SMOOTH_HINT: + params[0] = ENUM_TO_INT(ctx->Hint.PointSmooth); + break; + case GL_POINT_SIZE_MIN_EXT: + params[0] = IROUND(ctx->Point.MinSize); + break; + case GL_POINT_SIZE_MAX_EXT: + params[0] = IROUND(ctx->Point.MaxSize); + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + params[0] = IROUND(ctx->Point.Threshold); + break; + case GL_DISTANCE_ATTENUATION_EXT: + params[0] = IROUND(ctx->Point.Params[0]); + params[1] = IROUND(ctx->Point.Params[1]); + params[2] = IROUND(ctx->Point.Params[2]); + break; + case GL_POLYGON_MODE: + params[0] = ENUM_TO_INT(ctx->Polygon.FrontMode); + params[1] = ENUM_TO_INT(ctx->Polygon.BackMode); + break; + case GL_POLYGON_OFFSET_BIAS_EXT: + params[0] = IROUND(ctx->Polygon.OffsetUnits); + break; + case GL_POLYGON_OFFSET_FACTOR: + params[0] = IROUND(ctx->Polygon.OffsetFactor ); + break; + case GL_POLYGON_OFFSET_UNITS: + params[0] = IROUND(ctx->Polygon.OffsetUnits ); + break; + case GL_POLYGON_SMOOTH: + params[0] = BOOLEAN_TO_INT(ctx->Polygon.SmoothFlag); + break; + case GL_POLYGON_SMOOTH_HINT: + params[0] = ENUM_TO_INT(ctx->Hint.PolygonSmooth); + break; + case GL_POLYGON_STIPPLE: + params[0] = BOOLEAN_TO_INT(ctx->Polygon.StippleFlag); + break; + case GL_PROJECTION_MATRIX: + { + const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[1]); + params[2] = IROUND(matrix[2]); + params[3] = IROUND(matrix[3]); + params[4] = IROUND(matrix[4]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[6]); + params[7] = IROUND(matrix[7]); + params[8] = IROUND(matrix[8]); + params[9] = IROUND(matrix[9]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[11]); + params[12] = IROUND(matrix[12]); + params[13] = IROUND(matrix[13]); + params[14] = IROUND(matrix[14]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_PROJECTION_STACK_DEPTH: + params[0] = ctx->ProjectionMatrixStack.Depth + 1; + break; + case GL_READ_BUFFER: + params[0] = ENUM_TO_INT(ctx->Pixel.ReadBuffer); + break; + case GL_RED_BIAS: + params[0] = IROUND(ctx->Pixel.RedBias); + break; + case GL_RED_BITS: + params[0] = ctx->DrawBuffer->Visual.redBits ; + break; + case GL_RED_SCALE: + params[0] = IROUND(ctx->Pixel.RedScale); + break; + case GL_RENDER_MODE: + params[0] = ENUM_TO_INT(ctx->RenderMode); + break; + case GL_RESCALE_NORMAL: + params[0] = BOOLEAN_TO_INT(ctx->Transform.RescaleNormals); + break; + case GL_RGBA_MODE: + params[0] = BOOLEAN_TO_INT(ctx->DrawBuffer->Visual.rgbMode); + break; + case GL_SCISSOR_BOX: + params[0] = ctx->Scissor.X; + params[1] = ctx->Scissor.Y; + params[2] = ctx->Scissor.Width; + params[3] = ctx->Scissor.Height; + break; + case GL_SCISSOR_TEST: + params[0] = BOOLEAN_TO_INT(ctx->Scissor.Enabled); + break; + case GL_SELECTION_BUFFER_SIZE: + params[0] = ctx->Select.BufferSize; + break; + case GL_SHADE_MODEL: + params[0] = ENUM_TO_INT(ctx->Light.ShadeModel); + break; + case GL_SHARED_TEXTURE_PALETTE_EXT: + params[0] = BOOLEAN_TO_INT(ctx->Texture.SharedPalette); + break; + case GL_STENCIL_BITS: + params[0] = ctx->DrawBuffer->Visual.stencilBits; + break; + case GL_STENCIL_CLEAR_VALUE: + params[0] = ctx->Stencil.Clear; + break; + case GL_STENCIL_FAIL: + params[0] = ENUM_TO_INT(ctx->Stencil.FailFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_FUNC: + params[0] = ENUM_TO_INT(ctx->Stencil.Function[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_PASS_DEPTH_FAIL: + params[0] = ENUM_TO_INT(ctx->Stencil.ZFailFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_PASS_DEPTH_PASS: + params[0] = ENUM_TO_INT(ctx->Stencil.ZPassFunc[ctx->Stencil.ActiveFace]); + break; + case GL_STENCIL_REF: + params[0] = ctx->Stencil.Ref[ctx->Stencil.ActiveFace]; + break; + case GL_STENCIL_TEST: + params[0] = BOOLEAN_TO_INT(ctx->Stencil.Enabled); + break; + case GL_STENCIL_VALUE_MASK: + params[0] = ctx->Stencil.ValueMask[ctx->Stencil.ActiveFace]; + break; + case GL_STENCIL_WRITEMASK: + params[0] = ctx->Stencil.WriteMask[ctx->Stencil.ActiveFace]; + break; + case GL_STEREO: + params[0] = BOOLEAN_TO_INT(ctx->DrawBuffer->Visual.stereoMode); + break; + case GL_SUBPIXEL_BITS: + params[0] = ctx->Const.SubPixelBits; + break; + case GL_TEXTURE_1D: + params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_1D)); + break; + case GL_TEXTURE_2D: + params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_2D)); + break; + case GL_TEXTURE_3D: + params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_3D)); + break; + case GL_TEXTURE_BINDING_1D: + params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D->Name; + break; + case GL_TEXTURE_BINDING_2D: + params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D->Name; + break; + case GL_TEXTURE_BINDING_3D: + params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D->Name; + break; + case GL_TEXTURE_ENV_COLOR: + { + const GLfloat *color = ctx->Texture.Unit[ctx->Texture.CurrentUnit].EnvColor; + params[0] = FLOAT_TO_INT(color[0]); + params[1] = FLOAT_TO_INT(color[1]); + params[2] = FLOAT_TO_INT(color[2]); + params[3] = FLOAT_TO_INT(color[3]); + } + break; + case GL_TEXTURE_ENV_MODE: + params[0] = ENUM_TO_INT(ctx->Texture.Unit[ctx->Texture.CurrentUnit].EnvMode); + break; + case GL_TEXTURE_GEN_S: + params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_GEN_T: + params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & T_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_GEN_R: + params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & R_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_GEN_Q: + params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & Q_BIT) ? 1 : 0)); + break; + case GL_TEXTURE_MATRIX: + { + const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[1]); + params[2] = IROUND(matrix[2]); + params[3] = IROUND(matrix[3]); + params[4] = IROUND(matrix[4]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[6]); + params[7] = IROUND(matrix[7]); + params[8] = IROUND(matrix[8]); + params[9] = IROUND(matrix[9]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[11]); + params[12] = IROUND(matrix[12]); + params[13] = IROUND(matrix[13]); + params[14] = IROUND(matrix[14]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_TEXTURE_STACK_DEPTH: + params[0] = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Depth + 1; + break; + case GL_UNPACK_ALIGNMENT: + params[0] = ctx->Unpack.Alignment; + break; + case GL_UNPACK_LSB_FIRST: + params[0] = BOOLEAN_TO_INT(ctx->Unpack.LsbFirst); + break; + case GL_UNPACK_ROW_LENGTH: + params[0] = ctx->Unpack.RowLength; + break; + case GL_UNPACK_SKIP_PIXELS: + params[0] = ctx->Unpack.SkipPixels; + break; + case GL_UNPACK_SKIP_ROWS: + params[0] = ctx->Unpack.SkipRows; + break; + case GL_UNPACK_SWAP_BYTES: + params[0] = BOOLEAN_TO_INT(ctx->Unpack.SwapBytes); + break; + case GL_UNPACK_SKIP_IMAGES_EXT: + params[0] = ctx->Unpack.SkipImages; + break; + case GL_UNPACK_IMAGE_HEIGHT_EXT: + params[0] = ctx->Unpack.ImageHeight; + break; + case GL_UNPACK_CLIENT_STORAGE_APPLE: + params[0] = BOOLEAN_TO_INT(ctx->Unpack.ClientStorage); + break; + case GL_VIEWPORT: + params[0] = ctx->Viewport.X; + params[1] = ctx->Viewport.Y; + params[2] = ctx->Viewport.Width; + params[3] = ctx->Viewport.Height; + break; + case GL_ZOOM_X: + params[0] = IROUND(ctx->Pixel.ZoomX); + break; + case GL_ZOOM_Y: + params[0] = IROUND(ctx->Pixel.ZoomY); + break; + case GL_VERTEX_ARRAY: + params[0] = BOOLEAN_TO_INT(ctx->Array.Vertex.Enabled); + break; + case GL_VERTEX_ARRAY_SIZE: + params[0] = ctx->Array.Vertex.Size; + break; + case GL_VERTEX_ARRAY_TYPE: + params[0] = ENUM_TO_INT(ctx->Array.Vertex.Type); + break; + case GL_VERTEX_ARRAY_STRIDE: + params[0] = ctx->Array.Vertex.Stride; + break; + case GL_VERTEX_ARRAY_COUNT_EXT: + params[0] = 0; + break; + case GL_NORMAL_ARRAY: + params[0] = ENUM_TO_INT(ctx->Array.Normal.Enabled); + break; + case GL_NORMAL_ARRAY_TYPE: + params[0] = ENUM_TO_INT(ctx->Array.Normal.Type); + break; + case GL_NORMAL_ARRAY_STRIDE: + params[0] = ctx->Array.Normal.Stride; + break; + case GL_NORMAL_ARRAY_COUNT_EXT: + params[0] = 0; + break; + case GL_COLOR_ARRAY: + params[0] = BOOLEAN_TO_INT(ctx->Array.Color.Enabled); + break; + case GL_COLOR_ARRAY_SIZE: + params[0] = ctx->Array.Color.Size; + break; + case GL_COLOR_ARRAY_TYPE: + params[0] = ENUM_TO_INT(ctx->Array.Color.Type); + break; + case GL_COLOR_ARRAY_STRIDE: + params[0] = ctx->Array.Color.Stride; + break; + case GL_COLOR_ARRAY_COUNT_EXT: + params[0] = 0; + break; + case GL_INDEX_ARRAY: + params[0] = BOOLEAN_TO_INT(ctx->Array.Index.Enabled); + break; + case GL_INDEX_ARRAY_TYPE: + params[0] = ENUM_TO_INT(ctx->Array.Index.Type); + break; + case GL_INDEX_ARRAY_STRIDE: + params[0] = ctx->Array.Index.Stride; + break; + case GL_INDEX_ARRAY_COUNT_EXT: + params[0] = 0; + break; + case GL_TEXTURE_COORD_ARRAY: + params[0] = BOOLEAN_TO_INT(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Enabled); + break; + case GL_TEXTURE_COORD_ARRAY_SIZE: + params[0] = ctx->Array.TexCoord[ctx->Array.ActiveTexture].Size; + break; + case GL_TEXTURE_COORD_ARRAY_TYPE: + params[0] = ENUM_TO_INT(ctx->Array.TexCoord[ctx->Array.ActiveTexture].Type); + break; + case GL_TEXTURE_COORD_ARRAY_STRIDE: + params[0] = ctx->Array.TexCoord[ctx->Array.ActiveTexture].Stride; + break; + case GL_TEXTURE_COORD_ARRAY_COUNT_EXT: + params[0] = 0; + break; + case GL_EDGE_FLAG_ARRAY: + params[0] = BOOLEAN_TO_INT(ctx->Array.EdgeFlag.Enabled); + break; + case GL_EDGE_FLAG_ARRAY_STRIDE: + params[0] = ctx->Array.EdgeFlag.Stride; + break; + case GL_EDGE_FLAG_ARRAY_COUNT_EXT: + params[0] = 0; + break; + case GL_MAX_TEXTURE_UNITS_ARB: + CHECK_EXTENSION_I(ARB_multitexture, pname); + params[0] = MIN2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits); + break; + case GL_ACTIVE_TEXTURE_ARB: + CHECK_EXTENSION_I(ARB_multitexture, pname); + params[0] = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit; + break; + case GL_CLIENT_ACTIVE_TEXTURE_ARB: + CHECK_EXTENSION_I(ARB_multitexture, pname); + params[0] = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + CHECK_EXTENSION_I(ARB_texture_cube_map, pname); + params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_CUBE_MAP_ARB)); + break; + case GL_TEXTURE_BINDING_CUBE_MAP_ARB: + CHECK_EXTENSION_I(ARB_texture_cube_map, pname); + params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap->Name; + break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: + CHECK_EXTENSION_I(ARB_texture_cube_map, pname); + params[0] = (1 << (ctx->Const.MaxCubeTextureLevels - 1)); + break; + case GL_TEXTURE_COMPRESSION_HINT_ARB: + CHECK_EXTENSION_I(ARB_texture_compression, pname); + params[0] = ctx->Hint.TextureCompression; + break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB: + CHECK_EXTENSION_I(ARB_texture_compression, pname); + params[0] = _mesa_get_compressed_formats(ctx, NULL); + break; + case GL_COMPRESSED_TEXTURE_FORMATS_ARB: + CHECK_EXTENSION_I(ARB_texture_compression, pname); + { + GLint formats[100]; + GLuint i, n = _mesa_get_compressed_formats(ctx, formats); + ASSERT(n <= 100); + for (i = 0; i < n; i++) + params[i] = ENUM_TO_INT(formats[i]); + } + break; + case GL_ARRAY_ELEMENT_LOCK_FIRST_EXT: + CHECK_EXTENSION_I(EXT_compiled_vertex_array, pname); + params[0] = ctx->Array.LockFirst; + break; + case GL_ARRAY_ELEMENT_LOCK_COUNT_EXT: + CHECK_EXTENSION_I(EXT_compiled_vertex_array, pname); + params[0] = ctx->Array.LockCount; + break; + case GL_TRANSPOSE_COLOR_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ColorMatrixStack.Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[4]); + params[2] = IROUND(matrix[8]); + params[3] = IROUND(matrix[12]); + params[4] = IROUND(matrix[1]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[9]); + params[7] = IROUND(matrix[13]); + params[8] = IROUND(matrix[2]); + params[9] = IROUND(matrix[6]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[14]); + params[12] = IROUND(matrix[3]); + params[13] = IROUND(matrix[7]); + params[14] = IROUND(matrix[11]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_TRANSPOSE_MODELVIEW_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ModelviewMatrixStack.Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[4]); + params[2] = IROUND(matrix[8]); + params[3] = IROUND(matrix[12]); + params[4] = IROUND(matrix[1]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[9]); + params[7] = IROUND(matrix[13]); + params[8] = IROUND(matrix[2]); + params[9] = IROUND(matrix[6]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[14]); + params[12] = IROUND(matrix[3]); + params[13] = IROUND(matrix[7]); + params[14] = IROUND(matrix[11]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_TRANSPOSE_PROJECTION_MATRIX_ARB: + { + const GLfloat *matrix = ctx->ProjectionMatrixStack.Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[4]); + params[2] = IROUND(matrix[8]); + params[3] = IROUND(matrix[12]); + params[4] = IROUND(matrix[1]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[9]); + params[7] = IROUND(matrix[13]); + params[8] = IROUND(matrix[2]); + params[9] = IROUND(matrix[6]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[14]); + params[12] = IROUND(matrix[3]); + params[13] = IROUND(matrix[7]); + params[14] = IROUND(matrix[11]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_TRANSPOSE_TEXTURE_MATRIX_ARB: + { + const GLfloat *matrix = ctx->TextureMatrixStack[ctx->Texture.CurrentUnit].Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[4]); + params[2] = IROUND(matrix[8]); + params[3] = IROUND(matrix[12]); + params[4] = IROUND(matrix[1]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[9]); + params[7] = IROUND(matrix[13]); + params[8] = IROUND(matrix[2]); + params[9] = IROUND(matrix[6]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[14]); + params[12] = IROUND(matrix[3]); + params[13] = IROUND(matrix[7]); + params[14] = IROUND(matrix[11]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_OCCLUSION_TEST_HP: + CHECK_EXTENSION_I(HP_occlusion_test, pname); + params[0] = BOOLEAN_TO_INT(ctx->Depth.OcclusionTest); + break; + case GL_OCCLUSION_TEST_RESULT_HP: + CHECK_EXTENSION_I(HP_occlusion_test, pname); + { + FLUSH_VERTICES(ctx, _NEW_DEPTH); + if (ctx->Depth.OcclusionTest) + params[0] = ctx->OcclusionResult; + else + params[0] = ctx->OcclusionResultSaved; + /* reset flag now */ + ctx->OcclusionResult = GL_FALSE; + ctx->OcclusionResultSaved = GL_FALSE; + return; + } + break; + case GL_PIXEL_TEXTURE_SGIS: + CHECK_EXTENSION_I(SGIS_pixel_texture, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.PixelTextureEnabled); + break; + case GL_PIXEL_TEX_GEN_SGIX: + CHECK_EXTENSION_I(SGIX_pixel_texture, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.PixelTextureEnabled); + break; + case GL_PIXEL_TEX_GEN_MODE_SGIX: + CHECK_EXTENSION_I(SGIX_pixel_texture, pname); + params[0] = ENUM_TO_INT(pixel_texgen_mode(ctx)); + break; + case GL_COLOR_MATRIX_SGI: + { + const GLfloat *matrix = ctx->ColorMatrixStack.Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[1]); + params[2] = IROUND(matrix[2]); + params[3] = IROUND(matrix[3]); + params[4] = IROUND(matrix[4]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[6]); + params[7] = IROUND(matrix[7]); + params[8] = IROUND(matrix[8]); + params[9] = IROUND(matrix[9]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[11]); + params[12] = IROUND(matrix[12]); + params[13] = IROUND(matrix[13]); + params[14] = IROUND(matrix[14]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_COLOR_MATRIX_STACK_DEPTH_SGI: + params[0] = ctx->ColorMatrixStack.Depth + 1; + break; + case GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI: + params[0] = MAX_COLOR_STACK_DEPTH; + break; + case GL_POST_COLOR_MATRIX_RED_SCALE_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[0]); + break; + case GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[1]); + break; + case GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[2]); + break; + case GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixScale[3]); + break; + case GL_POST_COLOR_MATRIX_RED_BIAS_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[0]); + break; + case GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[1]); + break; + case GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[2]); + break; + case GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI: + params[0] = IROUND(ctx->Pixel.PostColorMatrixBias[3]); + break; + case GL_CONVOLUTION_1D_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.Convolution1DEnabled); + break; + case GL_CONVOLUTION_2D_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.Convolution2DEnabled); + break; + case GL_SEPARABLE_2D_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.Separable2DEnabled); + break; + case GL_POST_CONVOLUTION_RED_SCALE_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionScale[0]); + break; + case GL_POST_CONVOLUTION_GREEN_SCALE_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionScale[1]); + break; + case GL_POST_CONVOLUTION_BLUE_SCALE_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionScale[2]); + break; + case GL_POST_CONVOLUTION_ALPHA_SCALE_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionScale[3]); + break; + case GL_POST_CONVOLUTION_RED_BIAS_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionBias[0]); + break; + case GL_POST_CONVOLUTION_GREEN_BIAS_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionBias[1]); + break; + case GL_POST_CONVOLUTION_BLUE_BIAS_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionBias[2]); + break; + case GL_POST_CONVOLUTION_ALPHA_BIAS_EXT: + CHECK_EXTENSION_I(EXT_convolution, pname); + params[0] = IROUND(ctx->Pixel.PostConvolutionBias[3]); + break; + case GL_HISTOGRAM: + CHECK_EXTENSION_I(EXT_histogram, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.HistogramEnabled); + break; + case GL_MINMAX: + CHECK_EXTENSION_I(EXT_histogram, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.MinMaxEnabled); + break; + case GL_COLOR_TABLE_SGI: + CHECK_EXTENSION_I(SGI_color_table, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.ColorTableEnabled); + break; + case GL_POST_CONVOLUTION_COLOR_TABLE_SGI: + CHECK_EXTENSION_I(SGI_color_table, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.PostConvolutionColorTableEnabled); + break; + case GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI: + CHECK_EXTENSION_I(SGI_color_table, pname); + params[0] = BOOLEAN_TO_INT(ctx->Pixel.PostColorMatrixColorTableEnabled); + break; + case GL_TEXTURE_COLOR_TABLE_SGI: + CHECK_EXTENSION_I(SGI_texture_color_table, pname); + params[0] = BOOLEAN_TO_INT(ctx->Texture.Unit[ctx->Texture.CurrentUnit].ColorTableEnabled); + break; + case GL_COLOR_SUM_EXT: + CHECK_EXTENSION_I(EXT_secondary_color, pname); + params[0] = BOOLEAN_TO_INT(ctx->Fog.ColorSumEnabled); + break; + case GL_CURRENT_SECONDARY_COLOR_EXT: + CHECK_EXTENSION_I(EXT_secondary_color, pname); + { + FLUSH_CURRENT(ctx, 0); + params[0] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0]); + params[1] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1]); + params[2] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2]); + params[3] = FLOAT_TO_INT(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3]); + } + break; + case GL_SECONDARY_COLOR_ARRAY_EXT: + CHECK_EXTENSION_I(EXT_secondary_color, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.SecondaryColor.Enabled); + break; + case GL_SECONDARY_COLOR_ARRAY_TYPE_EXT: + CHECK_EXTENSION_I(EXT_secondary_color, pname); + params[0] = ENUM_TO_INT(ctx->Array.SecondaryColor.Type); + break; + case GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT: + CHECK_EXTENSION_I(EXT_secondary_color, pname); + params[0] = ctx->Array.SecondaryColor.Stride; + break; + case GL_SECONDARY_COLOR_ARRAY_SIZE_EXT: + CHECK_EXTENSION_I(EXT_secondary_color, pname); + params[0] = ctx->Array.SecondaryColor.Size; + break; + case GL_CURRENT_FOG_COORDINATE_EXT: + CHECK_EXTENSION_I(EXT_fog_coord, pname); + { + FLUSH_CURRENT(ctx, 0); + params[0] = IROUND(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]); + } + break; + case GL_FOG_COORDINATE_ARRAY_EXT: + CHECK_EXTENSION_I(EXT_fog_coord, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.FogCoord.Enabled); + break; + case GL_FOG_COORDINATE_ARRAY_TYPE_EXT: + CHECK_EXTENSION_I(EXT_fog_coord, pname); + params[0] = ENUM_TO_INT(ctx->Array.FogCoord.Type); + break; + case GL_FOG_COORDINATE_ARRAY_STRIDE_EXT: + CHECK_EXTENSION_I(EXT_fog_coord, pname); + params[0] = ctx->Array.FogCoord.Stride; + break; + case GL_FOG_COORDINATE_SOURCE_EXT: + CHECK_EXTENSION_I(EXT_fog_coord, pname); + params[0] = ENUM_TO_INT(ctx->Fog.FogCoordinateSource); + break; + case GL_MAX_TEXTURE_LOD_BIAS_EXT: + CHECK_EXTENSION_I(EXT_texture_lod_bias, pname); + params[0] = IROUND(ctx->Const.MaxTextureLodBias); + break; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + CHECK_EXTENSION_I(EXT_texture_filter_anisotropic, pname); + params[0] = IROUND(ctx->Const.MaxTextureMaxAnisotropy); + break; + case GL_MULTISAMPLE_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = BOOLEAN_TO_INT(ctx->Multisample.Enabled); + break; + case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleAlphaToCoverage); + break; + case GL_SAMPLE_ALPHA_TO_ONE_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleAlphaToOne); + break; + case GL_SAMPLE_COVERAGE_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleCoverage); + break; + case GL_SAMPLE_COVERAGE_VALUE_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = IROUND(ctx->Multisample.SampleCoverageValue); + break; + case GL_SAMPLE_COVERAGE_INVERT_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = BOOLEAN_TO_INT(ctx->Multisample.SampleCoverageInvert); + break; + case GL_SAMPLE_BUFFERS_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = ctx->DrawBuffer->Visual.sampleBuffers; + break; + case GL_SAMPLES_ARB: + CHECK_EXTENSION_I(ARB_multisample, pname); + params[0] = ctx->DrawBuffer->Visual.samples; + break; + case GL_RASTER_POSITION_UNCLIPPED_IBM: + CHECK_EXTENSION_I(IBM_rasterpos_clip, pname); + params[0] = BOOLEAN_TO_INT(ctx->Transform.RasterPositionUnclipped); + break; + case GL_POINT_SPRITE_NV: + CHECK_EXTENSION_I(NV_point_sprite, pname); + params[0] = BOOLEAN_TO_INT(ctx->Point.PointSprite); + break; + case GL_POINT_SPRITE_R_MODE_NV: + CHECK_EXTENSION_I(NV_point_sprite, pname); + params[0] = ENUM_TO_INT(ctx->Point.SpriteRMode); + break; + case GL_POINT_SPRITE_COORD_ORIGIN: + CHECK_EXTENSION_I(NV_point_sprite, pname); + params[0] = ENUM_TO_INT(ctx->Point.SpriteOrigin); + break; + case GL_GENERATE_MIPMAP_HINT_SGIS: + CHECK_EXTENSION_I(SGIS_generate_mipmap, pname); + params[0] = ENUM_TO_INT(ctx->Hint.GenerateMipmap); + break; + case GL_VERTEX_PROGRAM_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.Enabled); + break; + case GL_VERTEX_PROGRAM_POINT_SIZE_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.PointSizeEnabled); + break; + case GL_VERTEX_PROGRAM_TWO_SIDE_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.TwoSideEnabled); + break; + case GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = ctx->Const.MaxProgramMatrixStackDepth; + break; + case GL_MAX_TRACK_MATRICES_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = ctx->Const.MaxProgramMatrices; + break; + case GL_CURRENT_MATRIX_STACK_DEPTH_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->CurrentStack->Depth + 1); + break; + case GL_CURRENT_MATRIX_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + { + const GLfloat *matrix = ctx->CurrentStack->Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[1]); + params[2] = IROUND(matrix[2]); + params[3] = IROUND(matrix[3]); + params[4] = IROUND(matrix[4]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[6]); + params[7] = IROUND(matrix[7]); + params[8] = IROUND(matrix[8]); + params[9] = IROUND(matrix[9]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[11]); + params[12] = IROUND(matrix[12]); + params[13] = IROUND(matrix[13]); + params[14] = IROUND(matrix[14]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_VERTEX_PROGRAM_BINDING_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = (ctx->VertexProgram.Current ? ctx->VertexProgram.Current->Base.Id : 0); + break; + case GL_PROGRAM_ERROR_POSITION_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = ctx->Program.ErrorPos; + break; + case GL_VERTEX_ATTRIB_ARRAY0_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[0].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY1_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[1].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY2_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[2].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY3_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[3].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[4].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY5_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[5].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY6_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[6].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY7_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[7].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY8_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[8].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY9_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[9].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY10_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[10].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY11_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[11].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY12_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[12].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY13_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[13].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY14_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[14].Enabled); + break; + case GL_VERTEX_ATTRIB_ARRAY15_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Array.VertexAttrib[15].Enabled); + break; + case GL_MAP1_VERTEX_ATTRIB0_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[0]); + break; + case GL_MAP1_VERTEX_ATTRIB1_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[1]); + break; + case GL_MAP1_VERTEX_ATTRIB2_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[2]); + break; + case GL_MAP1_VERTEX_ATTRIB3_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[3]); + break; + case GL_MAP1_VERTEX_ATTRIB4_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[4]); + break; + case GL_MAP1_VERTEX_ATTRIB5_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[5]); + break; + case GL_MAP1_VERTEX_ATTRIB6_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[6]); + break; + case GL_MAP1_VERTEX_ATTRIB7_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[7]); + break; + case GL_MAP1_VERTEX_ATTRIB8_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[8]); + break; + case GL_MAP1_VERTEX_ATTRIB9_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[9]); + break; + case GL_MAP1_VERTEX_ATTRIB10_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[10]); + break; + case GL_MAP1_VERTEX_ATTRIB11_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[11]); + break; + case GL_MAP1_VERTEX_ATTRIB12_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[12]); + break; + case GL_MAP1_VERTEX_ATTRIB13_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[13]); + break; + case GL_MAP1_VERTEX_ATTRIB14_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[14]); + break; + case GL_MAP1_VERTEX_ATTRIB15_4_NV: + CHECK_EXTENSION_I(NV_vertex_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->Eval.Map1Attrib[15]); + break; + case GL_FRAGMENT_PROGRAM_NV: + CHECK_EXTENSION_I(NV_fragment_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->FragmentProgram.Enabled); + break; + case GL_MAX_TEXTURE_COORDS_NV: + CHECK_EXTENSION_I(NV_fragment_program, pname); + params[0] = ctx->Const.MaxTextureCoordUnits; + break; + case GL_MAX_TEXTURE_IMAGE_UNITS_NV: + CHECK_EXTENSION_I(NV_fragment_program, pname); + params[0] = ctx->Const.MaxTextureImageUnits; + break; + case GL_FRAGMENT_PROGRAM_BINDING_NV: + CHECK_EXTENSION_I(NV_fragment_program, pname); + params[0] = ctx->FragmentProgram.Current ? ctx->FragmentProgram.Current->Base.Id : 0; + break; + case GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV: + CHECK_EXTENSION_I(NV_fragment_program, pname); + params[0] = MAX_NV_FRAGMENT_PROGRAM_PARAMS; + break; + case GL_TEXTURE_RECTANGLE_NV: + CHECK_EXTENSION_I(NV_texture_rectangle, pname); + params[0] = BOOLEAN_TO_INT(_mesa_IsEnabled(GL_TEXTURE_RECTANGLE_NV)); + break; + case GL_TEXTURE_BINDING_RECTANGLE_NV: + CHECK_EXTENSION_I(NV_texture_rectangle, pname); + params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentRect->Name; + break; + case GL_MAX_RECTANGLE_TEXTURE_SIZE_NV: + CHECK_EXTENSION_I(NV_texture_rectangle, pname); + params[0] = ctx->Const.MaxTextureRectSize; + break; + case GL_STENCIL_TEST_TWO_SIDE_EXT: + CHECK_EXTENSION_I(EXT_stencil_two_side, pname); + params[0] = BOOLEAN_TO_INT(ctx->Stencil.TestTwoSide); + break; + case GL_ACTIVE_STENCIL_FACE_EXT: + CHECK_EXTENSION_I(EXT_stencil_two_side, pname); + params[0] = ENUM_TO_INT(ctx->Stencil.ActiveFace ? GL_BACK : GL_FRONT); + break; + case GL_MAX_SHININESS_NV: + CHECK_EXTENSION_I(NV_light_max_exponent, pname); + params[0] = IROUND(ctx->Const.MaxShininess); + break; + case GL_MAX_SPOT_EXPONENT_NV: + CHECK_EXTENSION_I(NV_light_max_exponent, pname); + params[0] = IROUND(ctx->Const.MaxSpotExponent); + break; + case GL_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.ArrayBufferObj->Name; + break; + case GL_VERTEX_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.Vertex.BufferObj->Name; + break; + case GL_NORMAL_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.Normal.BufferObj->Name; + break; + case GL_COLOR_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.Color.BufferObj->Name; + break; + case GL_INDEX_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.Index.BufferObj->Name; + break; + case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.TexCoord[ctx->Array.ActiveTexture].BufferObj->Name; + break; + case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.EdgeFlag.BufferObj->Name; + break; + case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.SecondaryColor.BufferObj->Name; + break; + case GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.FogCoord.BufferObj->Name; + break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB: + CHECK_EXTENSION_I(ARB_vertex_buffer_object, pname); + params[0] = ctx->Array.ElementArrayBufferObj->Name; + break; + case GL_PIXEL_PACK_BUFFER_BINDING_EXT: + CHECK_EXTENSION_I(EXT_pixel_buffer_object, pname); + params[0] = ctx->Pack.BufferObj->Name; + break; + case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT: + CHECK_EXTENSION_I(EXT_pixel_buffer_object, pname); + params[0] = ctx->Unpack.BufferObj->Name; + break; + case GL_MAX_VERTEX_ATTRIBS_ARB: + CHECK_EXTENSION_I(ARB_vertex_program, pname); + params[0] = ctx->Const.MaxVertexProgramAttribs; + break; + case GL_FRAGMENT_PROGRAM_ARB: + CHECK_EXTENSION_I(ARB_fragment_program, pname); + params[0] = BOOLEAN_TO_INT(ctx->FragmentProgram.Enabled); + break; + case GL_TRANSPOSE_CURRENT_MATRIX_ARB: + CHECK_EXTENSION_I(ARB_fragment_program, pname); + { + const GLfloat *matrix = ctx->CurrentStack->Top->m; + params[0] = IROUND(matrix[0]); + params[1] = IROUND(matrix[4]); + params[2] = IROUND(matrix[8]); + params[3] = IROUND(matrix[12]); + params[4] = IROUND(matrix[1]); + params[5] = IROUND(matrix[5]); + params[6] = IROUND(matrix[9]); + params[7] = IROUND(matrix[13]); + params[8] = IROUND(matrix[2]); + params[9] = IROUND(matrix[6]); + params[10] = IROUND(matrix[10]); + params[11] = IROUND(matrix[14]); + params[12] = IROUND(matrix[3]); + params[13] = IROUND(matrix[7]); + params[14] = IROUND(matrix[11]); + params[15] = IROUND(matrix[15]); + } + break; + case GL_DEPTH_BOUNDS_TEST_EXT: + CHECK_EXTENSION_I(EXT_depth_bounds_test, pname); + params[0] = BOOLEAN_TO_INT(ctx->Depth.BoundsTest); + break; + case GL_DEPTH_BOUNDS_EXT: + CHECK_EXTENSION_I(EXT_depth_bounds_test, pname); + params[0] = IROUND(ctx->Depth.BoundsMin); + params[1] = IROUND(ctx->Depth.BoundsMax); + break; + case GL_FRAGMENT_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION_I(MESA_program_debug, pname); + params[0] = BOOLEAN_TO_INT(ctx->FragmentProgram.CallbackEnabled); + break; + case GL_VERTEX_PROGRAM_CALLBACK_MESA: + CHECK_EXTENSION_I(MESA_program_debug, pname); + params[0] = BOOLEAN_TO_INT(ctx->VertexProgram.CallbackEnabled); + break; + case GL_FRAGMENT_PROGRAM_POSITION_MESA: + CHECK_EXTENSION_I(MESA_program_debug, pname); + params[0] = ctx->FragmentProgram.CurrentPosition; + break; + case GL_VERTEX_PROGRAM_POSITION_MESA: + CHECK_EXTENSION_I(MESA_program_debug, pname); + params[0] = ctx->VertexProgram.CurrentPosition; + break; + case GL_MAX_DRAW_BUFFERS_ARB: + CHECK_EXTENSION_I(ARB_draw_buffers, pname); + params[0] = ctx->Const.MaxDrawBuffers; + break; + case GL_DRAW_BUFFER0_ARB: + CHECK_EXTENSION_I(ARB_draw_buffers, pname); + params[0] = ENUM_TO_INT(ctx->Color.DrawBuffer[0]); + break; + case GL_DRAW_BUFFER1_ARB: + CHECK_EXTENSION_I(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[1]; + params[0] = ENUM_TO_INT(buffer); + } + break; + case GL_DRAW_BUFFER2_ARB: + CHECK_EXTENSION_I(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[2]; + params[0] = ENUM_TO_INT(buffer); + } + break; + case GL_DRAW_BUFFER3_ARB: + CHECK_EXTENSION_I(ARB_draw_buffers, pname); + { + GLenum buffer; + if (pname - GL_DRAW_BUFFER0_ARB >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGet(GL_DRAW_BUFFERx_ARB)"); + return; + } + buffer = ctx->Color.DrawBuffer[3]; + params[0] = ENUM_TO_INT(buffer); + } + break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: + CHECK_EXTENSION_I(OES_read_format, pname); + params[0] = ctx->Const.ColorReadType; + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: + CHECK_EXTENSION_I(OES_read_format, pname); + params[0] = ctx->Const.ColorReadFormat; + break; + case GL_NUM_FRAGMENT_REGISTERS_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 6; + break; + case GL_NUM_FRAGMENT_CONSTANTS_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 8; + break; + case GL_NUM_PASSES_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 2; + break; + case GL_NUM_INSTRUCTIONS_PER_PASS_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 8; + break; + case GL_NUM_INSTRUCTIONS_TOTAL_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 16; + break; + case GL_COLOR_ALPHA_PAIRING_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = BOOLEAN_TO_INT(GL_TRUE); + break; + case GL_NUM_LOOPBACK_COMPONENTS_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 3; + break; + case GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI: + CHECK_EXTENSION_I(ATI_fragment_shader, pname); + params[0] = 3; + break; + case GL_STENCIL_BACK_FUNC: + params[0] = ENUM_TO_INT(ctx->Stencil.Function[1]); + break; + case GL_STENCIL_BACK_VALUE_MASK: + params[0] = ctx->Stencil.ValueMask[1]; + break; + case GL_STENCIL_BACK_REF: + params[0] = ctx->Stencil.Ref[1]; + break; + case GL_STENCIL_BACK_FAIL: + params[0] = ENUM_TO_INT(ctx->Stencil.FailFunc[1]); + break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + params[0] = ENUM_TO_INT(ctx->Stencil.ZFailFunc[1]); + break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + params[0] = ENUM_TO_INT(ctx->Stencil.ZPassFunc[1]); + break; + case GL_FRAMEBUFFER_BINDING_EXT: + CHECK_EXTENSION_I(EXT_framebuffer_object, pname); + params[0] = ctx->DrawBuffer->Name; + break; + case GL_RENDERBUFFER_BINDING_EXT: + CHECK_EXTENSION_I(EXT_framebuffer_object, pname); + params[0] = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0; + break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: + CHECK_EXTENSION_I(EXT_framebuffer_object, pname); + params[0] = ctx->Const.MaxColorAttachments; + break; + case GL_MAX_RENDERBUFFER_SIZE_EXT: + CHECK_EXTENSION_I(EXT_framebuffer_object, pname); + params[0] = ctx->Const.MaxRenderbufferSize; + break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB: + CHECK_EXTENSION_I(ARB_fragment_shader, pname); + params[0] = MAX_FRAGMENT_UNIFORM_COMPONENTS; + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB: + CHECK_EXTENSION_I(ARB_fragment_shader, pname); + params[0] = ENUM_TO_INT(ctx->Hint.FragmentShaderDerivative); + break; + case GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB: + CHECK_EXTENSION_I(ARB_vertex_shader, pname); + params[0] = MAX_VERTEX_UNIFORM_COMPONENTS; + break; + case GL_MAX_VARYING_FLOATS_ARB: + CHECK_EXTENSION_I(ARB_vertex_shader, pname); + params[0] = MAX_VARYING_FLOATS; + break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB: + CHECK_EXTENSION_I(ARB_vertex_shader, pname); + params[0] = MAX_VERTEX_TEXTURE_IMAGE_UNITS; + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB: + CHECK_EXTENSION_I(ARB_vertex_shader, pname); + params[0] = MAX_COMBINED_TEXTURE_IMAGE_UNITS; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname); + } +} + + +void GLAPIENTRY +_mesa_GetDoublev( GLenum pname, GLdouble *params ) +{ + const GLfloat magic = -1234.5F; + GLfloat values[16]; + GLuint i; + + if (!params) + return; + + /* Init temp array to magic numbers so we can figure out how many values + * are returned by the GetFloatv() call. + */ + for (i = 0; i < 16; i++) + values[i] = magic; + + _mesa_GetFloatv(pname, values); + + for (i = 0; i < 16 && values[i] != magic; i++) + params[i] = (GLdouble) values[i]; +} + diff --git a/src/mesa/main/get.h b/src/mesa/main/get.h new file mode 100644 index 00000000000..9b47b230a98 --- /dev/null +++ b/src/mesa/main/get.h @@ -0,0 +1,59 @@ +/** + * \file get.h + * State query functions. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef GET_H +#define GET_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_GetBooleanv( GLenum pname, GLboolean *params ); + +extern void GLAPIENTRY +_mesa_GetDoublev( GLenum pname, GLdouble *params ); + +extern void GLAPIENTRY +_mesa_GetFloatv( GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetIntegerv( GLenum pname, GLint *params ); + +extern void GLAPIENTRY +_mesa_GetPointerv( GLenum pname, GLvoid **params ); + +extern const GLubyte * GLAPIENTRY +_mesa_GetString( GLenum name ); + +extern GLenum GLAPIENTRY +_mesa_GetError( void ); + +#endif diff --git a/src/mesa/main/getstring.c b/src/mesa/main/getstring.c new file mode 100644 index 00000000000..5188a79c951 --- /dev/null +++ b/src/mesa/main/getstring.c @@ -0,0 +1,261 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "get.h" +#include "version.h" +#include "enums.h" +#include "extensions.h" + + +/** + * Query string-valued state. The return value should _not_ be freed by + * the caller. + * + * \param name the state variable to query. + * + * \sa glGetString(). + * + * Tries to get the string from dd_function_table::GetString, otherwise returns + * the hardcoded strings. + */ +const GLubyte * GLAPIENTRY +_mesa_GetString( GLenum name ) +{ + GET_CURRENT_CONTEXT(ctx); + static const char *vendor = "Brian Paul"; + static const char *renderer = "Mesa"; + static const char *version_1_2 = "1.2 Mesa " MESA_VERSION_STRING; + static const char *version_1_3 = "1.3 Mesa " MESA_VERSION_STRING; + static const char *version_1_4 = "1.4 Mesa " MESA_VERSION_STRING; + static const char *version_1_5 = "1.5 Mesa " MESA_VERSION_STRING; + static const char *version_2_0 = "1.5 Mesa " MESA_VERSION_STRING;/*XXX FIX*/ + + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); + + /* this is a required driver function */ + assert(ctx->Driver.GetString); + { + /* Give the driver the chance to handle this query */ + const GLubyte *str = (*ctx->Driver.GetString)(ctx, name); + if (str) + return str; + } + + switch (name) { + case GL_VENDOR: + return (const GLubyte *) vendor; + case GL_RENDERER: + return (const GLubyte *) renderer; + case GL_VERSION: + if (ctx->Extensions.ARB_multisample && + ctx->Extensions.ARB_multitexture && + ctx->Extensions.ARB_texture_border_clamp && + ctx->Extensions.ARB_texture_compression && + ctx->Extensions.ARB_texture_cube_map && + ctx->Extensions.EXT_texture_env_add && + ctx->Extensions.ARB_texture_env_combine && + ctx->Extensions.ARB_texture_env_dot3) { + if (ctx->Extensions.ARB_depth_texture && + ctx->Extensions.ARB_shadow && + ctx->Extensions.ARB_texture_env_crossbar && + ctx->Extensions.ARB_texture_mirrored_repeat && + ctx->Extensions.ARB_window_pos && + ctx->Extensions.EXT_blend_color && + ctx->Extensions.EXT_blend_func_separate && + ctx->Extensions.EXT_blend_logic_op && + ctx->Extensions.EXT_blend_minmax && + ctx->Extensions.EXT_blend_subtract && + ctx->Extensions.EXT_fog_coord && + ctx->Extensions.EXT_multi_draw_arrays && + ctx->Extensions.EXT_point_parameters && /*aka ARB*/ + ctx->Extensions.EXT_secondary_color && + ctx->Extensions.EXT_stencil_wrap && + ctx->Extensions.EXT_texture_lod_bias && + ctx->Extensions.SGIS_generate_mipmap) { + if (ctx->Extensions.ARB_occlusion_query && + ctx->Extensions.ARB_vertex_buffer_object && + ctx->Extensions.EXT_shadow_funcs) { + if (ctx->Extensions.ARB_draw_buffers && + ctx->Extensions.ARB_point_sprite && + ctx->Extensions.ARB_texture_non_power_of_two && + ctx->Extensions.EXT_stencil_two_side) { + return (const GLubyte *) version_2_0; + } + else { + return (const GLubyte *) version_1_5; + } + } + else { + return (const GLubyte *) version_1_4; + } + } + else { + return (const GLubyte *) version_1_3; + } + } + else { + return (const GLubyte *) version_1_2; + } + case GL_EXTENSIONS: + if (!ctx->Extensions.String) + ctx->Extensions.String = _mesa_make_extension_string(ctx); + return (const GLubyte *) ctx->Extensions.String; +#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program || \ + FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program + case GL_PROGRAM_ERROR_STRING_NV: + if (ctx->Extensions.NV_fragment_program || + ctx->Extensions.ARB_fragment_program || + ctx->Extensions.NV_vertex_program || + ctx->Extensions.ARB_vertex_program) { + return (const GLubyte *) ctx->Program.ErrorString; + } + /* FALL-THROUGH */ +#endif + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetString" ); + return (const GLubyte *) 0; + } +} + + +/** + * Return pointer-valued state, such as a vertex array pointer. + * + * \param pname names state to be queried + * \param params returns the pointer value + * + * \sa glGetPointerv(). + * + * Tries to get the specified pointer via dd_function_table::GetPointerv, + * otherwise gets the specified pointer from the current context. + */ +void GLAPIENTRY +_mesa_GetPointerv( GLenum pname, GLvoid **params ) +{ + GET_CURRENT_CONTEXT(ctx); + const GLuint clientUnit = ctx->Array.ActiveTexture; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!params) + return; + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetPointerv %s\n", _mesa_lookup_enum_by_nr(pname)); + + if (ctx->Driver.GetPointerv + && (*ctx->Driver.GetPointerv)(ctx, pname, params)) + return; + + switch (pname) { + case GL_VERTEX_ARRAY_POINTER: + *params = (GLvoid *) ctx->Array.Vertex.Ptr; + break; + case GL_NORMAL_ARRAY_POINTER: + *params = (GLvoid *) ctx->Array.Normal.Ptr; + break; + case GL_COLOR_ARRAY_POINTER: + *params = (GLvoid *) ctx->Array.Color.Ptr; + break; + case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT: + *params = (GLvoid *) ctx->Array.SecondaryColor.Ptr; + break; + case GL_FOG_COORDINATE_ARRAY_POINTER_EXT: + *params = (GLvoid *) ctx->Array.FogCoord.Ptr; + break; + case GL_INDEX_ARRAY_POINTER: + *params = (GLvoid *) ctx->Array.Index.Ptr; + break; + case GL_TEXTURE_COORD_ARRAY_POINTER: + *params = (GLvoid *) ctx->Array.TexCoord[clientUnit].Ptr; + break; + case GL_EDGE_FLAG_ARRAY_POINTER: + *params = (GLvoid *) ctx->Array.EdgeFlag.Ptr; + break; + case GL_FEEDBACK_BUFFER_POINTER: + *params = ctx->Feedback.Buffer; + break; + case GL_SELECTION_BUFFER_POINTER: + *params = ctx->Select.Buffer; + break; +#if FEATURE_MESA_program_debug + case GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA: + if (!ctx->Extensions.MESA_program_debug) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv"); + return; + } + *params = *(GLvoid **) &ctx->FragmentProgram.Callback; + break; + case GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA: + if (!ctx->Extensions.MESA_program_debug) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv"); + return; + } + *params = ctx->FragmentProgram.CallbackData; + break; + case GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA: + if (!ctx->Extensions.MESA_program_debug) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv"); + return; + } + *params = *(GLvoid **) &ctx->VertexProgram.Callback; + break; + case GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA: + if (!ctx->Extensions.MESA_program_debug) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetPointerv"); + return; + } + *params = ctx->VertexProgram.CallbackData; + break; +#endif + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetPointerv" ); + return; + } +} + + +/** + * Returns the current GL error code, or GL_NO_ERROR. + * \return current error code + * + * Returns __GLcontextRec::ErrorValue. + */ +GLenum GLAPIENTRY +_mesa_GetError( void ) +{ + GET_CURRENT_CONTEXT(ctx); + GLenum e = ctx->ErrorValue; + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_lookup_enum_by_nr(e)); + + ctx->ErrorValue = (GLenum) GL_NO_ERROR; + return e; +} diff --git a/src/mesa/main/glheader.h b/src/mesa/main/glheader.h new file mode 100644 index 00000000000..ee34076fb74 --- /dev/null +++ b/src/mesa/main/glheader.h @@ -0,0 +1,297 @@ +/** + * \file glheader.h + * Top-most include file. + * + * This is the top-most include file of the Mesa sources. + * It includes gl.h and all system headers which are needed. + * Other Mesa source files should \e not directly include any system + * headers. This allows Mesa to be integrated into XFree86 and + * allows system-dependent hacks/workarounds to be collected in one place. + * + * \note Actually, a lot of system-dependent stuff is now in imports.[ch]. + * + * If you touch this file, everything gets recompiled! + * + * This file should be included before any other header in the .c files. + * + * Put compiler/OS/assembly pragmas and macros here to avoid + * cluttering other source files. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef GLHEADER_H +#define GLHEADER_H + + +#if defined(XFree86LOADER) && defined(IN_MODULE) +#include "xf86_ansic.h" +#else +#include <assert.h> +#include <ctype.h> +/* If we can use Compaq's Fast Math Library on Alpha */ +#if defined(__alpha__) && defined(CCPML) +#include <cpml.h> +#else +#include <math.h> +#endif +#include <limits.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#if defined(__linux__) && defined(__i386__) +#include <fpu_control.h> +#endif +#endif +#include <float.h> +#include <stdarg.h> + + +/* Get typedefs for uintptr_t and friends */ +#if defined(_WIN32) +#include <BaseTsd.h> +#if _MSC_VER == 1200 +typedef UINT_PTR uintptr_t; +#endif +#if defined(__MINGW32__) +#include <stdint.h> +#endif +#else +#include <inttypes.h> +#endif + +#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(BUILD_FOR_SNAP) +# define __WIN32__ +# define finite _finite +#endif + +#if defined(__WATCOMC__) +# define finite _finite +# pragma disable_message(201) /* Disable unreachable code warnings */ +#endif + + +#if !defined(OPENSTEP) && (defined(__WIN32__) && !defined(__CYGWIN__)) && !defined(BUILD_FOR_SNAP) +# if !defined(__GNUC__) /* mingw environment */ +# pragma warning( disable : 4068 ) /* unknown pragma */ +# pragma warning( disable : 4710 ) /* function 'foo' not inlined */ +# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */ +# pragma warning( disable : 4127 ) /* conditional expression is constant */ +# if defined(MESA_MINWARN) +# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */ +# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */ +# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */ +# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */ +# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */ +# endif +# endif +# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */ +# define WGLAPI __declspec(dllexport) +# elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */ +# define WGLAPI __declspec(dllimport) +# else /* for use with static link lib build of Win32 edition only */ +# define WGLAPI __declspec(dllimport) +# endif /* _STATIC_MESA support */ +#endif /* WIN32 / CYGWIN bracket */ + + +#ifndef __MINGW32__ +/* XXX why is this here? + * It should probaby be somewhere in src/mesa/drivers/windows/ + */ +#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_WINGDI_H) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP) && !defined(BUILD_FOR_SNAP) +# define WGL_FONT_LINES 0 +# define WGL_FONT_POLYGONS 1 +#ifndef _GNU_H_WINDOWS32_FUNCTIONS +# ifdef UNICODE +# define wglUseFontBitmaps wglUseFontBitmapsW +# define wglUseFontOutlines wglUseFontOutlinesW +# else +# define wglUseFontBitmaps wglUseFontBitmapsA +# define wglUseFontOutlines wglUseFontOutlinesA +# endif /* !UNICODE */ +#endif /* _GNU_H_WINDOWS32_FUNCTIONS */ +typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR; +typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT; +typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR; +#if !defined(GLX_USE_MESA) +#include <GL/mesa_wgl.h> +#endif +#endif +#endif /* !__MINGW32__ */ + + +/* + * Either define MESA_BIG_ENDIAN or MESA_LITTLE_ENDIAN. + * Do not use them unless absolutely necessary! + * Try to use a runtime test instead. + * For now, only used by some DRI hardware drivers for color/texel packing. + */ +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN +#if defined(__linux__) +#include <byteswap.h> +#define CPU_TO_LE32( x ) bswap_32( x ) +#else /*__linux__*/ +#define CPU_TO_LE32( x ) ( x ) /* fix me for non-Linux big-endian! */ +#endif /*__linux__*/ +#define MESA_BIG_ENDIAN 1 +#else +#define CPU_TO_LE32( x ) ( x ) +#define MESA_LITTLE_ENDIAN 1 +#endif +#define LE32_TO_CPU( x ) CPU_TO_LE32( x ) + + +#define GL_GLEXT_PROTOTYPES +#include "GL/gl.h" +#include "GL/glext.h" + + +#if !defined(CAPI) && defined(WIN32) && !defined(BUILD_FOR_SNAP) +#define CAPI _cdecl +#endif +#include <GL/internal/glcore.h> + + +/* This is a macro on IRIX */ +#ifdef _P +#undef _P +#endif + + +/* Turn off macro checking systems used by other libraries */ +#ifdef CHECK +#undef CHECK +#endif + + +/* Create a macro so that asm functions can be linked into compilers other + * than GNU C + */ +#ifndef _ASMAPI +#if defined(WIN32) && !defined(BUILD_FOR_SNAP)/* was: !defined( __GNUC__ ) && !defined( VMS ) && !defined( __INTEL_COMPILER )*/ +#define _ASMAPI __cdecl +#else +#define _ASMAPI +#endif +#ifdef PTR_DECL_IN_FRONT +#define _ASMAPIP * _ASMAPI +#else +#define _ASMAPIP _ASMAPI * +#endif +#endif + +#ifdef USE_X86_ASM +#define _NORMAPI _ASMAPI +#define _NORMAPIP _ASMAPIP +#else +#define _NORMAPI +#define _NORMAPIP * +#endif + + +/* Function inlining */ +#if defined(__GNUC__) +# define INLINE __inline__ +#elif defined(__MSC__) +# define INLINE __inline +#elif defined(_MSC_VER) +# define INLINE __inline +#elif defined(__ICL) +# define INLINE __inline +#elif defined(__INTEL_COMPILER) +# define INLINE inline +#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100) +# define INLINE __inline +#else +# define INLINE +#endif + + +/* If we build the library with gcc's -fvisibility=hidden flag, we'll + * use the PUBLIC macro to mark functions that are to be exported. + * + * We also need to define a USED attribute, so the optimizer doesn't + * inline a static function that we later use in an alias. - ajax + */ +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 +# define PUBLIC __attribute__((visibility("default"))) +# define USED __attribute__((used)) +#else +# define PUBLIC +# define USED +#endif + + +/* Some compilers don't like some of Mesa's const usage */ +#ifdef NO_CONST +# define CONST +#else +# define CONST const +#endif + + +#if defined(BUILD_FOR_SNAP) && defined(CHECKED) +# define ASSERT(X) _CHECK(X) +#elif defined(DEBUG) +# define ASSERT(X) assert(X) +#else +# define ASSERT(X) +#endif + + +#if !defined __GNUC__ || __GNUC__ < 3 +# define __builtin_expect(x, y) x +#endif + +/* Windows does not have the ffs() function */ +#if defined(_WIN32) && !defined(__MINGW32__) +int INLINE ffs(int value) +{ + int bit; + if (value == 0) + return 0; + for (bit=1; !(value & 1); bit++) + value >>= 1; + return bit; +} +#endif + + +/* The __FUNCTION__ gcc variable is generally only used for debugging. + * If we're not using gcc, define __FUNCTION__ as a cpp symbol here. + * Don't define it if using a newer Windows compiler. + */ +#if defined(__VMS) +#define __FUNCTION__ "VMS$NL:" +#elif !(defined(__GNUC__) && __GNUC__ >= 2) && !(defined(_MSC_VER) && _MSC_VER >= 1300) +#define __FUNCTION__ "unknown" +#endif + + +#include "config.h" + +#endif /* GLHEADER_H */ diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c new file mode 100644 index 00000000000..74ab57df0ac --- /dev/null +++ b/src/mesa/main/hash.c @@ -0,0 +1,451 @@ +/** + * \file hash.c + * Generic hash table. + * + * Used for display lists, texture objects, vertex/fragment programs, + * buffer objects, etc. The hash functions are thread-safe. + * + * \note key=0 is illegal. + * + * \author Brian Paul + */ + +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "glthread.h" +#include "hash.h" + + +#define TABLE_SIZE 1023 /**< Size of lookup table/array */ + +#define HASH_FUNC(K) ((K) % TABLE_SIZE) + + +/** + * An entry in the hash table. + * + * This struct is private to this file. + */ +struct HashEntry { + GLuint Key; /**< the entry's key */ + void *Data; /**< the entry's data */ + struct HashEntry *Next; /**< pointer to next entry */ +}; + +/** + * The hash table data structure. + * + * This is an opaque types (it's not defined in hash.h file). + */ +struct _mesa_HashTable { + struct HashEntry *Table[TABLE_SIZE]; /**< the lookup table */ + GLuint MaxKey; /**< highest key inserted so far */ + _glthread_Mutex Mutex; /**< mutual exclusion lock */ +}; + + +/** + * Create a new hash table. + * + * \return pointer to a new, empty hash table. + */ +struct _mesa_HashTable * +_mesa_NewHashTable(void) +{ + struct _mesa_HashTable *table = CALLOC_STRUCT(_mesa_HashTable); + if (table) { + _glthread_INIT_MUTEX(table->Mutex); + } + return table; +} + + + +/** + * Delete a hash table. + * Frees each entry on the hash table and then the hash table structure itself. + * Note that the caller should have already traversed the table and deleted + * the objects in the table (i.e. We don't free the entries' data pointer). + * + * \param table the hash table to delete. + */ +void +_mesa_DeleteHashTable(struct _mesa_HashTable *table) +{ + GLuint i; + assert(table); + for (i = 0; i < TABLE_SIZE; i++) { + struct HashEntry *entry = table->Table[i]; + while (entry) { + struct HashEntry *next = entry->Next; + FREE(entry); + entry = next; + } + } + _glthread_DESTROY_MUTEX(table->Mutex); + FREE(table); +} + + + +/** + * Lookup an entry in the hash table. + * + * \param table the hash table. + * \param key the key. + * + * \return pointer to user's data or NULL if key not in table + */ +void * +_mesa_HashLookup(const struct _mesa_HashTable *table, GLuint key) +{ + GLuint pos; + const struct HashEntry *entry; + + assert(table); + assert(key); + + pos = HASH_FUNC(key); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + return entry->Data; + } + entry = entry->Next; + } + return NULL; +} + + + +/** + * Insert a key/pointer pair into the hash table. + * If an entry with this key already exists we'll replace the existing entry. + * + * \param table the hash table. + * \param key the key (not zero). + * \param data pointer to user data. + */ +void +_mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data) +{ + /* search for existing entry with this key */ + GLuint pos; + struct HashEntry *entry; + + assert(table); + assert(key); + + _glthread_LOCK_MUTEX(table->Mutex); + + if (key > table->MaxKey) + table->MaxKey = key; + + pos = HASH_FUNC(key); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + /* replace entry's data */ + entry->Data = data; + _glthread_UNLOCK_MUTEX(table->Mutex); + return; + } + entry = entry->Next; + } + + /* alloc and insert new table entry */ + entry = MALLOC_STRUCT(HashEntry); + entry->Key = key; + entry->Data = data; + entry->Next = table->Table[pos]; + table->Table[pos] = entry; + + _glthread_UNLOCK_MUTEX(table->Mutex); +} + + + +/** + * Remove an entry from the hash table. + * + * \param table the hash table. + * \param key key of entry to remove. + * + * While holding the hash table's lock, searches the entry with the matching + * key and unlinks it. + */ +void +_mesa_HashRemove(struct _mesa_HashTable *table, GLuint key) +{ + GLuint pos; + struct HashEntry *entry, *prev; + + assert(table); + assert(key); + + _glthread_LOCK_MUTEX(table->Mutex); + + pos = HASH_FUNC(key); + prev = NULL; + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + /* found it! */ + if (prev) { + prev->Next = entry->Next; + } + else { + table->Table[pos] = entry->Next; + } + FREE(entry); + _glthread_UNLOCK_MUTEX(table->Mutex); + return; + } + prev = entry; + entry = entry->Next; + } + + _glthread_UNLOCK_MUTEX(table->Mutex); +} + + + +/** + * Get the key of the "first" entry in the hash table. + * + * This is used in the course of deleting all display lists when + * a context is destroyed. + * + * \param table the hash table + * + * \return key for the "first" entry in the hash table. + * + * While holding the lock, walks through all table positions until finding + * the first entry of the first non-empty one. + */ +GLuint +_mesa_HashFirstEntry(struct _mesa_HashTable *table) +{ + GLuint pos; + assert(table); + _glthread_LOCK_MUTEX(table->Mutex); + for (pos=0; pos < TABLE_SIZE; pos++) { + if (table->Table[pos]) { + _glthread_UNLOCK_MUTEX(table->Mutex); + return table->Table[pos]->Key; + } + } + _glthread_UNLOCK_MUTEX(table->Mutex); + return 0; +} + + +/** + * Given a hash table key, return the next key. This is used to walk + * over all entries in the table. Note that the keys returned during + * walking won't be in any particular order. + * \return next hash key or 0 if end of table. + */ +GLuint +_mesa_HashNextEntry(const struct _mesa_HashTable *table, GLuint key) +{ + const struct HashEntry *entry; + GLuint pos; + + assert(table); + assert(key); + + /* Find the entry with given key */ + pos = HASH_FUNC(key); + entry = table->Table[pos]; + while (entry) { + if (entry->Key == key) { + break; + } + entry = entry->Next; + } + + if (!entry) { + /* the key was not found, we can't find next entry */ + return 0; + } + + if (entry->Next) { + /* return next in linked list */ + return entry->Next->Key; + } + else { + /* look for next non-empty table slot */ + pos++; + while (pos < TABLE_SIZE) { + if (table->Table[pos]) { + return table->Table[pos]->Key; + } + pos++; + } + return 0; + } +} + + +/** + * Dump contents of hash table for debugging. + * + * \param table the hash table. + */ +void +_mesa_HashPrint(const struct _mesa_HashTable *table) +{ + GLuint i; + assert(table); + for (i=0;i<TABLE_SIZE;i++) { + const struct HashEntry *entry = table->Table[i]; + while (entry) { + _mesa_debug(NULL, "%u %p\n", entry->Key, entry->Data); + entry = entry->Next; + } + } +} + + + +/** + * Find a block of adjacent unused hash keys. + * + * \param table the hash table. + * \param numKeys number of keys needed. + * + * \return Starting key of free block or 0 if failure. + * + * If there are enough free keys between the maximum key existing in the table + * (_mesa_HashTable::MaxKey) and the maximum key possible, then simply return + * the adjacent key. Otherwise do a full search for a free key block in the + * allowable key range. + */ +GLuint +_mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys) +{ + GLuint maxKey = ~((GLuint) 0); + _glthread_LOCK_MUTEX(table->Mutex); + if (maxKey - numKeys > table->MaxKey) { + /* the quick solution */ + _glthread_UNLOCK_MUTEX(table->Mutex); + return table->MaxKey + 1; + } + else { + /* the slow solution */ + GLuint freeCount = 0; + GLuint freeStart = 1; + GLuint key; + for (key=1; key!=maxKey; key++) { + if (_mesa_HashLookup(table, key)) { + /* darn, this key is already in use */ + freeCount = 0; + freeStart = key+1; + } + else { + /* this key not in use, check if we've found enough */ + freeCount++; + if (freeCount == numKeys) { + _glthread_UNLOCK_MUTEX(table->Mutex); + return freeStart; + } + } + } + /* cannot allocate a block of numKeys consecutive keys */ + _glthread_UNLOCK_MUTEX(table->Mutex); + return 0; + } +} + + +#if 0 /* debug only */ + +/** + * Test walking over all the entries in a hash table. + */ +static void +test_hash_walking(void) +{ + struct _mesa_HashTable *t = _mesa_NewHashTable(); + const GLuint limit = 50000; + GLuint i; + + /* create some entries */ + for (i = 0; i < limit; i++) { + GLuint dummy; + GLuint k = (rand() % (limit * 10)) + 1; + while (_mesa_HashLookup(t, k)) { + /* id already in use, try another */ + k = (rand() % (limit * 10)) + 1; + } + _mesa_HashInsert(t, k, &dummy); + } + + /* walk over all entries */ + { + GLuint k = _mesa_HashFirstEntry(t); + GLuint count = 0; + while (k) { + GLuint knext = _mesa_HashNextEntry(t, k); + assert(knext != k); + _mesa_HashRemove(t, k); + count++; + k = knext; + } + assert(count == limit); + k = _mesa_HashFirstEntry(t); + assert(k==0); + } + + _mesa_DeleteHashTable(t); +} + + +void +_mesa_test_hash_functions(void) +{ + int a, b, c; + struct _mesa_HashTable *t; + + t = _mesa_NewHashTable(); + _mesa_HashInsert(t, 501, &a); + _mesa_HashInsert(t, 10, &c); + _mesa_HashInsert(t, 0xfffffff8, &b); + /*_mesa_HashPrint(t);*/ + + assert(_mesa_HashLookup(t,501)); + assert(!_mesa_HashLookup(t,1313)); + assert(_mesa_HashFindFreeKeyBlock(t, 100)); + + _mesa_DeleteHashTable(t); + + test_hash_walking(); +} + +#endif diff --git a/src/mesa/main/hash.h b/src/mesa/main/hash.h new file mode 100644 index 00000000000..3cbe668e9ae --- /dev/null +++ b/src/mesa/main/hash.h @@ -0,0 +1,59 @@ +/** + * \file hash.h + * Generic hash table. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef HASH_H +#define HASH_H + + +#include "glheader.h" + + +extern struct _mesa_HashTable *_mesa_NewHashTable(void); + +extern void _mesa_DeleteHashTable(struct _mesa_HashTable *table); + +extern void *_mesa_HashLookup(const struct _mesa_HashTable *table, GLuint key); + +extern void _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data); + +extern void _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key); + +extern GLuint _mesa_HashFirstEntry(struct _mesa_HashTable *table); + +extern GLuint _mesa_HashNextEntry(const struct _mesa_HashTable *table, GLuint key); + +extern void _mesa_HashPrint(const struct _mesa_HashTable *table); + +extern GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys); + +extern void _mesa_test_hash_functions(void); + + +#endif diff --git a/src/mesa/main/hint.c b/src/mesa/main/hint.c new file mode 100644 index 00000000000..6680edd1655 --- /dev/null +++ b/src/mesa/main/hint.c @@ -0,0 +1,153 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "enums.h" +#include "context.h" +#include "hint.h" +#include "imports.h" + + + +void GLAPIENTRY +_mesa_Hint( GLenum target, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glHint %s %d\n", + _mesa_lookup_enum_by_nr(target), mode); + + if (mode != GL_NICEST && mode != GL_FASTEST && mode != GL_DONT_CARE) { + _mesa_error(ctx, GL_INVALID_ENUM, "glHint(mode)"); + return; + } + + switch (target) { + case GL_FOG_HINT: + if (ctx->Hint.Fog == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.Fog = mode; + break; + case GL_LINE_SMOOTH_HINT: + if (ctx->Hint.LineSmooth == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.LineSmooth = mode; + break; + case GL_PERSPECTIVE_CORRECTION_HINT: + if (ctx->Hint.PerspectiveCorrection == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.PerspectiveCorrection = mode; + break; + case GL_POINT_SMOOTH_HINT: + if (ctx->Hint.PointSmooth == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.PointSmooth = mode; + break; + case GL_POLYGON_SMOOTH_HINT: + if (ctx->Hint.PolygonSmooth == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.PolygonSmooth = mode; + break; + + /* GL_EXT_clip_volume_hint */ + case GL_CLIP_VOLUME_CLIPPING_HINT_EXT: + if (ctx->Hint.ClipVolumeClipping == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.ClipVolumeClipping = mode; + break; + + /* GL_ARB_texture_compression */ + case GL_TEXTURE_COMPRESSION_HINT_ARB: + if (!ctx->Extensions.ARB_texture_compression) { + _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)"); + return; + } + if (ctx->Hint.TextureCompression == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.TextureCompression = mode; + break; + + /* GL_SGIS_generate_mipmap */ + case GL_GENERATE_MIPMAP_HINT_SGIS: + if (!ctx->Extensions.SGIS_generate_mipmap) { + _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)"); + return; + } + if (ctx->Hint.GenerateMipmap == mode) + return; + FLUSH_VERTICES(ctx, _NEW_HINT); + ctx->Hint.GenerateMipmap = mode; + break;
+
+ /* GL_ARB_fragment_shader */
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB:
+ if (!ctx->Extensions.ARB_fragment_shader) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)");
+ return;
+ }
+ if (ctx->Hint.FragmentShaderDerivative == mode)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_HINT);
+ ctx->Hint.FragmentShaderDerivative = mode;
+ break; + + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glHint(target)"); + return; + } + + if (ctx->Driver.Hint) { + (*ctx->Driver.Hint)( ctx, target, mode ); + } +} + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +void _mesa_init_hint( GLcontext * ctx ) +{ + /* Hint group */ + ctx->Hint.PerspectiveCorrection = GL_DONT_CARE; + ctx->Hint.PointSmooth = GL_DONT_CARE; + ctx->Hint.LineSmooth = GL_DONT_CARE; + ctx->Hint.PolygonSmooth = GL_DONT_CARE; + ctx->Hint.Fog = GL_DONT_CARE; + ctx->Hint.ClipVolumeClipping = GL_DONT_CARE; + ctx->Hint.TextureCompression = GL_DONT_CARE; + ctx->Hint.GenerateMipmap = GL_DONT_CARE;
+ ctx->Hint.FragmentShaderDerivative = GL_DONT_CARE; +} diff --git a/src/mesa/main/hint.h b/src/mesa/main/hint.h new file mode 100644 index 00000000000..bfc3887107d --- /dev/null +++ b/src/mesa/main/hint.h @@ -0,0 +1,57 @@ +/** + * \file hint.h + * Hints operations. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef HINT_H +#define HINT_H + + +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_Hint( GLenum target, GLenum mode ); + +extern void +_mesa_init_hint( GLcontext * ctx ); + +#else + +/** No-op */ +#define _mesa_init_hint( c ) ((void) 0) + +#endif + +#endif diff --git a/src/mesa/main/histogram.c b/src/mesa/main/histogram.c new file mode 100644 index 00000000000..29aced0c7a7 --- /dev/null +++ b/src/mesa/main/histogram.c @@ -0,0 +1,1187 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "bufferobj.h" +#include "colormac.h" +#include "context.h" +#include "image.h" +#include "histogram.h" + + +/********************************************************************** + * Internal functions + */ + + +/* + * Update the min/max values from an array of fragment colors. + */ +void +_mesa_update_minmax(GLcontext *ctx, GLuint n, const GLfloat rgba[][4]) +{ + GLuint i; + for (i = 0; i < n; i++) { + /* update mins */ + if (rgba[i][RCOMP] < ctx->MinMax.Min[RCOMP]) + ctx->MinMax.Min[RCOMP] = rgba[i][RCOMP]; + if (rgba[i][GCOMP] < ctx->MinMax.Min[GCOMP]) + ctx->MinMax.Min[GCOMP] = rgba[i][GCOMP]; + if (rgba[i][BCOMP] < ctx->MinMax.Min[BCOMP]) + ctx->MinMax.Min[BCOMP] = rgba[i][BCOMP]; + if (rgba[i][ACOMP] < ctx->MinMax.Min[ACOMP]) + ctx->MinMax.Min[ACOMP] = rgba[i][ACOMP]; + + /* update maxs */ + if (rgba[i][RCOMP] > ctx->MinMax.Max[RCOMP]) + ctx->MinMax.Max[RCOMP] = rgba[i][RCOMP]; + if (rgba[i][GCOMP] > ctx->MinMax.Max[GCOMP]) + ctx->MinMax.Max[GCOMP] = rgba[i][GCOMP]; + if (rgba[i][BCOMP] > ctx->MinMax.Max[BCOMP]) + ctx->MinMax.Max[BCOMP] = rgba[i][BCOMP]; + if (rgba[i][ACOMP] > ctx->MinMax.Max[ACOMP]) + ctx->MinMax.Max[ACOMP] = rgba[i][ACOMP]; + } +} + + +/* + * Update the histogram values from an array of fragment colors. + */ +void +_mesa_update_histogram(GLcontext *ctx, GLuint n, const GLfloat rgba[][4]) +{ + const GLint max = ctx->Histogram.Width - 1; + GLfloat w = (GLfloat) max; + GLuint i; + + if (ctx->Histogram.Width == 0) + return; + + for (i = 0; i < n; i++) { + GLint ri = IROUND(rgba[i][RCOMP] * w); + GLint gi = IROUND(rgba[i][GCOMP] * w); + GLint bi = IROUND(rgba[i][BCOMP] * w); + GLint ai = IROUND(rgba[i][ACOMP] * w); + ri = CLAMP(ri, 0, max); + gi = CLAMP(gi, 0, max); + bi = CLAMP(bi, 0, max); + ai = CLAMP(ai, 0, max); + ctx->Histogram.Count[ri][RCOMP]++; + ctx->Histogram.Count[gi][GCOMP]++; + ctx->Histogram.Count[bi][BCOMP]++; + ctx->Histogram.Count[ai][ACOMP]++; + } +} + + +/* + * XXX the packed pixel formats haven't been tested. + */ +static void +pack_histogram( GLcontext *ctx, + GLuint n, CONST GLuint rgba[][4], + GLenum format, GLenum type, GLvoid *destination, + const struct gl_pixelstore_attrib *packing ) +{ + const GLint comps = _mesa_components_in_format(format); + GLuint luminance[MAX_WIDTH]; + + if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) { + GLuint i; + for (i = 0; i < n; i++) { + luminance[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP]; + } + } + +#define PACK_MACRO(TYPE) \ + { \ + GLuint i; \ + switch (format) { \ + case GL_RED: \ + for (i=0;i<n;i++) \ + dst[i] = (TYPE) rgba[i][RCOMP]; \ + break; \ + case GL_GREEN: \ + for (i=0;i<n;i++) \ + dst[i] = (TYPE) rgba[i][GCOMP]; \ + break; \ + case GL_BLUE: \ + for (i=0;i<n;i++) \ + dst[i] = (TYPE) rgba[i][BCOMP]; \ + break; \ + case GL_ALPHA: \ + for (i=0;i<n;i++) \ + dst[i] = (TYPE) rgba[i][ACOMP]; \ + break; \ + case GL_LUMINANCE: \ + for (i=0;i<n;i++) \ + dst[i] = (TYPE) luminance[i]; \ + break; \ + case GL_LUMINANCE_ALPHA: \ + for (i=0;i<n;i++) { \ + dst[i*2+0] = (TYPE) luminance[i]; \ + dst[i*2+1] = (TYPE) rgba[i][ACOMP]; \ + } \ + break; \ + case GL_RGB: \ + for (i=0;i<n;i++) { \ + dst[i*3+0] = (TYPE) rgba[i][RCOMP]; \ + dst[i*3+1] = (TYPE) rgba[i][GCOMP]; \ + dst[i*3+2] = (TYPE) rgba[i][BCOMP]; \ + } \ + break; \ + case GL_RGBA: \ + for (i=0;i<n;i++) { \ + dst[i*4+0] = (TYPE) rgba[i][RCOMP]; \ + dst[i*4+1] = (TYPE) rgba[i][GCOMP]; \ + dst[i*4+2] = (TYPE) rgba[i][BCOMP]; \ + dst[i*4+3] = (TYPE) rgba[i][ACOMP]; \ + } \ + break; \ + case GL_BGR: \ + for (i=0;i<n;i++) { \ + dst[i*3+0] = (TYPE) rgba[i][BCOMP]; \ + dst[i*3+1] = (TYPE) rgba[i][GCOMP]; \ + dst[i*3+2] = (TYPE) rgba[i][RCOMP]; \ + } \ + break; \ + case GL_BGRA: \ + for (i=0;i<n;i++) { \ + dst[i*4+0] = (TYPE) rgba[i][BCOMP]; \ + dst[i*4+1] = (TYPE) rgba[i][GCOMP]; \ + dst[i*4+2] = (TYPE) rgba[i][RCOMP]; \ + dst[i*4+3] = (TYPE) rgba[i][ACOMP]; \ + } \ + break; \ + case GL_ABGR_EXT: \ + for (i=0;i<n;i++) { \ + dst[i*4+0] = (TYPE) rgba[i][ACOMP]; \ + dst[i*4+1] = (TYPE) rgba[i][BCOMP]; \ + dst[i*4+2] = (TYPE) rgba[i][GCOMP]; \ + dst[i*4+3] = (TYPE) rgba[i][RCOMP]; \ + } \ + break; \ + default: \ + _mesa_problem(ctx, "bad format in pack_histogram"); \ + } \ + } + + switch (type) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) destination; + PACK_MACRO(GLubyte); + } + break; + case GL_BYTE: + { + GLbyte *dst = (GLbyte *) destination; + PACK_MACRO(GLbyte); + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *dst = (GLushort *) destination; + PACK_MACRO(GLushort); + if (packing->SwapBytes) { + _mesa_swap2(dst, n * comps); + } + } + break; + case GL_SHORT: + { + GLshort *dst = (GLshort *) destination; + PACK_MACRO(GLshort); + if (packing->SwapBytes) { + _mesa_swap2((GLushort *) dst, n * comps); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *dst = (GLuint *) destination; + PACK_MACRO(GLuint); + if (packing->SwapBytes) { + _mesa_swap4(dst, n * comps); + } + } + break; + case GL_INT: + { + GLint *dst = (GLint *) destination; + PACK_MACRO(GLint); + if (packing->SwapBytes) { + _mesa_swap4((GLuint *) dst, n * comps); + } + } + break; + case GL_FLOAT: + { + GLfloat *dst = (GLfloat *) destination; + PACK_MACRO(GLfloat); + if (packing->SwapBytes) { + _mesa_swap4((GLuint *) dst, n * comps); + } + } + break; + case GL_HALF_FLOAT_ARB: + { + /* temporarily store as GLuints */ + GLuint temp[4*HISTOGRAM_TABLE_SIZE]; + GLhalfARB *dst = (GLhalfARB *) destination; + GLuint i; + /* get GLuint values */ + PACK_MACRO(GLuint); + /* convert to GLhalf */ + for (i = 0; i < n * comps; i++) { + dst[i] = _mesa_float_to_half((GLfloat) temp[i]); + } + if (packing->SwapBytes) { + _mesa_swap2((GLushort *) dst, n * comps); + } + } + break; + case GL_UNSIGNED_BYTE_3_3_2: + if (format == GL_RGB) { + GLubyte *dst = (GLubyte *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x7) << 5) + | ((rgba[i][GCOMP] & 0x7) << 2) + | ((rgba[i][BCOMP] & 0x3) ); + } + } + else { + GLubyte *dst = (GLubyte *) destination; + GLuint i; + ASSERT(format == GL_BGR); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0x7) << 5) + | ((rgba[i][GCOMP] & 0x7) << 2) + | ((rgba[i][RCOMP] & 0x3) ); + } + } + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (format == GL_RGB) { + GLubyte *dst = (GLubyte *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x3) << 6) + | ((rgba[i][GCOMP] & 0x7) << 3) + | ((rgba[i][BCOMP] & 0x7) ); + } + } + else { + GLubyte *dst = (GLubyte *) destination; + GLuint i; + ASSERT(format == GL_BGR); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0x3) << 6) + | ((rgba[i][GCOMP] & 0x7) << 3) + | ((rgba[i][RCOMP] & 0x7) ); + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x3f) << 5) + | ((rgba[i][BCOMP] & 0x1f) ); + } + } + else { + GLushort *dst = (GLushort *) destination; + GLuint i; + ASSERT(format == GL_BGR); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x3f) << 5) + | ((rgba[i][RCOMP] & 0x1f) ); + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (format == GL_RGB) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x3f) << 5) + | ((rgba[i][RCOMP] & 0x1f) ); + } + } + else { + GLushort *dst = (GLushort *) destination; + GLuint i; + ASSERT(format == GL_BGR); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x3f) << 5) + | ((rgba[i][BCOMP] & 0x1f) ); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + if (format == GL_RGBA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0xf) << 12) + | ((rgba[i][GCOMP] & 0xf) << 8) + | ((rgba[i][BCOMP] & 0xf) << 4) + | ((rgba[i][ACOMP] & 0xf) ); + } + } + else if (format == GL_BGRA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0xf) << 12) + | ((rgba[i][GCOMP] & 0xf) << 8) + | ((rgba[i][RCOMP] & 0xf) << 4) + | ((rgba[i][ACOMP] & 0xf) ); + } + } + else { + GLushort *dst = (GLushort *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0xf) << 12) + | ((rgba[i][BCOMP] & 0xf) << 8) + | ((rgba[i][GCOMP] & 0xf) << 4) + | ((rgba[i][RCOMP] & 0xf) ); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + if (format == GL_RGBA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0xf) << 12) + | ((rgba[i][BCOMP] & 0xf) << 8) + | ((rgba[i][GCOMP] & 0xf) << 4) + | ((rgba[i][RCOMP] & 0xf) ); + } + } + else if (format == GL_BGRA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0xf) << 12) + | ((rgba[i][RCOMP] & 0xf) << 8) + | ((rgba[i][GCOMP] & 0xf) << 4) + | ((rgba[i][BCOMP] & 0xf) ); + } + } + else { + GLushort *dst = (GLushort *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0xf) << 12) + | ((rgba[i][GCOMP] & 0xf) << 8) + | ((rgba[i][BCOMP] & 0xf) << 4) + | ((rgba[i][ACOMP] & 0xf) ); + } + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + if (format == GL_RGBA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x1f) << 6) + | ((rgba[i][BCOMP] & 0x1f) << 1) + | ((rgba[i][ACOMP] & 0x1) ); + } + } + else if (format == GL_BGRA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x1f) << 6) + | ((rgba[i][RCOMP] & 0x1f) << 1) + | ((rgba[i][ACOMP] & 0x1) ); + } + } + else { + GLushort *dst = (GLushort *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11) + | ((rgba[i][BCOMP] & 0x1f) << 6) + | ((rgba[i][GCOMP] & 0x1f) << 1) + | ((rgba[i][RCOMP] & 0x1) ); + } + } + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (format == GL_RGBA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11) + | ((rgba[i][BCOMP] & 0x1f) << 6) + | ((rgba[i][GCOMP] & 0x1f) << 1) + | ((rgba[i][RCOMP] & 0x1) ); + } + } + else if (format == GL_BGRA) { + GLushort *dst = (GLushort *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0x1f) << 11) + | ((rgba[i][RCOMP] & 0x1f) << 6) + | ((rgba[i][GCOMP] & 0x1f) << 1) + | ((rgba[i][BCOMP] & 0x1) ); + } + } + else { + GLushort *dst = (GLushort *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x1f) << 11) + | ((rgba[i][GCOMP] & 0x1f) << 6) + | ((rgba[i][BCOMP] & 0x1f) << 1) + | ((rgba[i][ACOMP] & 0x1) ); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0xff) << 24) + | ((rgba[i][GCOMP] & 0xff) << 16) + | ((rgba[i][BCOMP] & 0xff) << 8) + | ((rgba[i][ACOMP] & 0xff) ); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0xff) << 24) + | ((rgba[i][GCOMP] & 0xff) << 16) + | ((rgba[i][RCOMP] & 0xff) << 8) + | ((rgba[i][ACOMP] & 0xff) ); + } + } + else { + GLuint *dst = (GLuint *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0xff) << 24) + | ((rgba[i][BCOMP] & 0xff) << 16) + | ((rgba[i][GCOMP] & 0xff) << 8) + | ((rgba[i][RCOMP] & 0xff) ); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0xff) << 24) + | ((rgba[i][BCOMP] & 0xff) << 16) + | ((rgba[i][GCOMP] & 0xff) << 8) + | ((rgba[i][RCOMP] & 0xff) ); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0xff) << 24) + | ((rgba[i][RCOMP] & 0xff) << 16) + | ((rgba[i][GCOMP] & 0xff) << 8) + | ((rgba[i][BCOMP] & 0xff) ); + } + } + else { + GLuint *dst = (GLuint *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0xff) << 24) + | ((rgba[i][GCOMP] & 0xff) << 16) + | ((rgba[i][BCOMP] & 0xff) << 8) + | ((rgba[i][ACOMP] & 0xff) ); + } + } + break; + case GL_UNSIGNED_INT_10_10_10_2: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22) + | ((rgba[i][GCOMP] & 0x3ff) << 12) + | ((rgba[i][BCOMP] & 0x3ff) << 2) + | ((rgba[i][ACOMP] & 0x3) ); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][BCOMP] & 0x3ff) << 22) + | ((rgba[i][GCOMP] & 0x3ff) << 12) + | ((rgba[i][RCOMP] & 0x3ff) << 2) + | ((rgba[i][ACOMP] & 0x3) ); + } + } + else { + GLuint *dst = (GLuint *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22) + | ((rgba[i][BCOMP] & 0x3ff) << 12) + | ((rgba[i][GCOMP] & 0x3ff) << 2) + | ((rgba[i][RCOMP] & 0x3) ); + } + } + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (format == GL_RGBA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22) + | ((rgba[i][BCOMP] & 0x3ff) << 12) + | ((rgba[i][GCOMP] & 0x3ff) << 2) + | ((rgba[i][RCOMP] & 0x3) ); + } + } + else if (format == GL_BGRA) { + GLuint *dst = (GLuint *) destination; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][ACOMP] & 0x3ff) << 22) + | ((rgba[i][RCOMP] & 0x3ff) << 12) + | ((rgba[i][GCOMP] & 0x3ff) << 2) + | ((rgba[i][BCOMP] & 0x3) ); + } + } + else { + GLuint *dst = (GLuint *) destination; + GLuint i; + ASSERT(format == GL_ABGR_EXT); + for (i = 0; i < n; i++) { + dst[i] = ((rgba[i][RCOMP] & 0x3ff) << 22) + | ((rgba[i][GCOMP] & 0x3ff) << 12) + | ((rgba[i][BCOMP] & 0x3ff) << 2) + | ((rgba[i][ACOMP] & 0x3) ); + } + } + break; + default: + _mesa_problem(ctx, "Bad type in pack_histogram"); + } + +#undef PACK_MACRO +} + + +/* + * Given an internalFormat token passed to glHistogram or glMinMax, + * return the corresponding base format. + * Return -1 if invalid token. + */ +static GLint +base_histogram_format( GLenum format ) +{ + switch (format) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return GL_ALPHA; + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + default: + return -1; /* error */ + } +} + + + +/********************************************************************** + * API functions + */ + + +void GLAPIENTRY +_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax"); + return; + } + + if (target != GL_MINMAX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmax(target)"); + return; + } + + if (format != GL_RED && + format != GL_GREEN && + format != GL_BLUE && + format != GL_ALPHA && + format != GL_RGB && + format != GL_BGR && + format != GL_RGBA && + format != GL_BGRA && + format != GL_ABGR_EXT && + format != GL_LUMINANCE && + format != GL_LUMINANCE_ALPHA) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMax(format)"); + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmax(format or type)"); + return; + } + + if (ctx->Pack.BufferObj->Name) { + /* pack min/max values into a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Pack, 2, 1, 1, + format, type, values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetMinMax(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION,"glGetMinMax(PBO is mapped)"); + return; + } + values = ADD_POINTERS(buf, values); + } + else if (!values) { + /* not an error */ + return; + } + + { + GLfloat minmax[2][4]; + minmax[0][RCOMP] = CLAMP(ctx->MinMax.Min[RCOMP], 0.0F, 1.0F); + minmax[0][GCOMP] = CLAMP(ctx->MinMax.Min[GCOMP], 0.0F, 1.0F); + minmax[0][BCOMP] = CLAMP(ctx->MinMax.Min[BCOMP], 0.0F, 1.0F); + minmax[0][ACOMP] = CLAMP(ctx->MinMax.Min[ACOMP], 0.0F, 1.0F); + minmax[1][RCOMP] = CLAMP(ctx->MinMax.Max[RCOMP], 0.0F, 1.0F); + minmax[1][GCOMP] = CLAMP(ctx->MinMax.Max[GCOMP], 0.0F, 1.0F); + minmax[1][BCOMP] = CLAMP(ctx->MinMax.Max[BCOMP], 0.0F, 1.0F); + minmax[1][ACOMP] = CLAMP(ctx->MinMax.Max[ACOMP], 0.0F, 1.0F); + _mesa_pack_rgba_span_float(ctx, 2, (CONST GLfloat (*)[4]) minmax, + format, type, values, &ctx->Pack, 0); + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } + + if (reset) { + _mesa_ResetMinmax(GL_MINMAX); + } +} + + +void GLAPIENTRY +_mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram"); + return; + } + + if (target != GL_HISTOGRAM) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(target)"); + return; + } + + if (format != GL_RED && + format != GL_GREEN && + format != GL_BLUE && + format != GL_ALPHA && + format != GL_RGB && + format != GL_BGR && + format != GL_RGBA && + format != GL_BGRA && + format != GL_ABGR_EXT && + format != GL_LUMINANCE && + format != GL_LUMINANCE_ALPHA) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogram(format)"); + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogram(format or type)"); + return; + } + + if (ctx->Pack.BufferObj->Name) { + /* pack min/max values into a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(1, &ctx->Pack, ctx->Histogram.Width, 1, 1, + format, type, values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetHistogram(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx,GL_INVALID_OPERATION,"glGetHistogram(PBO is mapped)"); + return; + } + values = ADD_POINTERS(buf, values); + } + else if (!values) { + /* not an error */ + return; + } + + pack_histogram(ctx, ctx->Histogram.Width, + (CONST GLuint (*)[4]) ctx->Histogram.Count, + format, type, values, &ctx->Pack); + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } + + if (reset) { + GLuint i; + for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) { + ctx->Histogram.Count[i][0] = 0; + ctx->Histogram.Count[i][1] = 0; + ctx->Histogram.Count[i][2] = 0; + ctx->Histogram.Count[i][3] = 0; + } + } +} + + +void GLAPIENTRY +_mesa_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogramParameterfv"); + return; + } + + if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameterfv(target)"); + return; + } + + switch (pname) { + case GL_HISTOGRAM_WIDTH: + *params = (GLfloat) ctx->Histogram.Width; + break; + case GL_HISTOGRAM_FORMAT: + *params = (GLfloat) ctx->Histogram.Format; + break; + case GL_HISTOGRAM_RED_SIZE: + *params = (GLfloat) ctx->Histogram.RedSize; + break; + case GL_HISTOGRAM_GREEN_SIZE: + *params = (GLfloat) ctx->Histogram.GreenSize; + break; + case GL_HISTOGRAM_BLUE_SIZE: + *params = (GLfloat) ctx->Histogram.BlueSize; + break; + case GL_HISTOGRAM_ALPHA_SIZE: + *params = (GLfloat) ctx->Histogram.AlphaSize; + break; + case GL_HISTOGRAM_LUMINANCE_SIZE: + *params = (GLfloat) ctx->Histogram.LuminanceSize; + break; + case GL_HISTOGRAM_SINK: + *params = (GLfloat) ctx->Histogram.Sink; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameterfv(pname)"); + } +} + + +void GLAPIENTRY +_mesa_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetHistogramParameteriv"); + return; + } + + if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameteriv(target)"); + return; + } + + switch (pname) { + case GL_HISTOGRAM_WIDTH: + *params = (GLint) ctx->Histogram.Width; + break; + case GL_HISTOGRAM_FORMAT: + *params = (GLint) ctx->Histogram.Format; + break; + case GL_HISTOGRAM_RED_SIZE: + *params = (GLint) ctx->Histogram.RedSize; + break; + case GL_HISTOGRAM_GREEN_SIZE: + *params = (GLint) ctx->Histogram.GreenSize; + break; + case GL_HISTOGRAM_BLUE_SIZE: + *params = (GLint) ctx->Histogram.BlueSize; + break; + case GL_HISTOGRAM_ALPHA_SIZE: + *params = (GLint) ctx->Histogram.AlphaSize; + break; + case GL_HISTOGRAM_LUMINANCE_SIZE: + *params = (GLint) ctx->Histogram.LuminanceSize; + break; + case GL_HISTOGRAM_SINK: + *params = (GLint) ctx->Histogram.Sink; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetHistogramParameteriv(pname)"); + } +} + + +void GLAPIENTRY +_mesa_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmaxParameterfv"); + return; + } + if (target != GL_MINMAX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmaxParameterfv(target)"); + return; + } + if (pname == GL_MINMAX_FORMAT) { + *params = (GLfloat) ctx->MinMax.Format; + } + else if (pname == GL_MINMAX_SINK) { + *params = (GLfloat) ctx->MinMax.Sink; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMaxParameterfv(pname)"); + } +} + + +void GLAPIENTRY +_mesa_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetMinmaxParameteriv"); + return; + } + if (target != GL_MINMAX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinmaxParameteriv(target)"); + return; + } + if (pname == GL_MINMAX_FORMAT) { + *params = (GLint) ctx->MinMax.Format; + } + else if (pname == GL_MINMAX_SINK) { + *params = (GLint) ctx->MinMax.Sink; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetMinMaxParameteriv(pname)"); + } +} + + +void GLAPIENTRY +_mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean sink) +{ + GLuint i; + GLboolean error = GL_FALSE; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */ + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glHistogram"); + return; + } + + if (target != GL_HISTOGRAM && target != GL_PROXY_HISTOGRAM) { + _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(target)"); + return; + } + + if (width < 0 || width > HISTOGRAM_TABLE_SIZE) { + if (target == GL_PROXY_HISTOGRAM) { + error = GL_TRUE; + } + else { + if (width < 0) + _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)"); + else + _mesa_error(ctx, GL_TABLE_TOO_LARGE, "glHistogram(width)"); + return; + } + } + + if (width != 0 && _mesa_bitcount(width) != 1) { + if (target == GL_PROXY_HISTOGRAM) { + error = GL_TRUE; + } + else { + _mesa_error(ctx, GL_INVALID_VALUE, "glHistogram(width)"); + return; + } + } + + if (base_histogram_format(internalFormat) < 0) { + if (target == GL_PROXY_HISTOGRAM) { + error = GL_TRUE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glHistogram(internalFormat)"); + return; + } + } + + /* reset histograms */ + for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) { + ctx->Histogram.Count[i][0] = 0; + ctx->Histogram.Count[i][1] = 0; + ctx->Histogram.Count[i][2] = 0; + ctx->Histogram.Count[i][3] = 0; + } + + if (error) { + ctx->Histogram.Width = 0; + ctx->Histogram.Format = 0; + ctx->Histogram.RedSize = 0; + ctx->Histogram.GreenSize = 0; + ctx->Histogram.BlueSize = 0; + ctx->Histogram.AlphaSize = 0; + ctx->Histogram.LuminanceSize = 0; + } + else { + ctx->Histogram.Width = width; + ctx->Histogram.Format = internalFormat; + ctx->Histogram.Sink = sink; + ctx->Histogram.RedSize = 8 * sizeof(GLuint); + ctx->Histogram.GreenSize = 8 * sizeof(GLuint); + ctx->Histogram.BlueSize = 8 * sizeof(GLuint); + ctx->Histogram.AlphaSize = 8 * sizeof(GLuint); + ctx->Histogram.LuminanceSize = 8 * sizeof(GLuint); + } + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_Minmax(GLenum target, GLenum internalFormat, GLboolean sink) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glMinmax"); + return; + } + + if (target != GL_MINMAX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glMinMax(target)"); + return; + } + + if (base_histogram_format(internalFormat) < 0) { + _mesa_error(ctx, GL_INVALID_ENUM, "glMinMax(internalFormat)"); + return; + } + + if (ctx->MinMax.Sink == sink) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->MinMax.Sink = sink; +} + + +void GLAPIENTRY +_mesa_ResetHistogram(GLenum target) +{ + GLuint i; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* sideeffects */ + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glResetHistogram"); + return; + } + + if (target != GL_HISTOGRAM) { + _mesa_error(ctx, GL_INVALID_ENUM, "glResetHistogram(target)"); + return; + } + + for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) { + ctx->Histogram.Count[i][0] = 0; + ctx->Histogram.Count[i][1] = 0; + ctx->Histogram.Count[i][2] = 0; + ctx->Histogram.Count[i][3] = 0; + } + + ctx->NewState |= _NEW_PIXEL; +} + + +void GLAPIENTRY +_mesa_ResetMinmax(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (!ctx->Extensions.EXT_histogram && !ctx->Extensions.ARB_imaging) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glResetMinmax"); + return; + } + + if (target != GL_MINMAX) { + _mesa_error(ctx, GL_INVALID_ENUM, "glResetMinMax(target)"); + return; + } + + ctx->MinMax.Min[RCOMP] = 1000; ctx->MinMax.Max[RCOMP] = -1000; + ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000; + ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000; + ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000; + ctx->NewState |= _NEW_PIXEL; +} + + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +void _mesa_init_histogram( GLcontext * ctx ) +{ + int i; + + /* Histogram group */ + ctx->Histogram.Width = 0; + ctx->Histogram.Format = GL_RGBA; + ctx->Histogram.Sink = GL_FALSE; + ctx->Histogram.RedSize = 0; + ctx->Histogram.GreenSize = 0; + ctx->Histogram.BlueSize = 0; + ctx->Histogram.AlphaSize = 0; + ctx->Histogram.LuminanceSize = 0; + for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) { + ctx->Histogram.Count[i][0] = 0; + ctx->Histogram.Count[i][1] = 0; + ctx->Histogram.Count[i][2] = 0; + ctx->Histogram.Count[i][3] = 0; + } + + /* Min/Max group */ + ctx->MinMax.Format = GL_RGBA; + ctx->MinMax.Sink = GL_FALSE; + ctx->MinMax.Min[RCOMP] = 1000; ctx->MinMax.Max[RCOMP] = -1000; + ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000; + ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000; + ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000; +} diff --git a/src/mesa/main/histogram.h b/src/mesa/main/histogram.h new file mode 100644 index 00000000000..974447231dd --- /dev/null +++ b/src/mesa/main/histogram.h @@ -0,0 +1,89 @@ +/** + * \file histogram.h + * Histogram. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef HISTOGRAM_H +#define HISTOGRAM_H + +#include "glheader.h" +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values); + +extern void GLAPIENTRY +_mesa_GetHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); + +extern void GLAPIENTRY +_mesa_GetHistogramParameterfv(GLenum target, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetHistogramParameteriv(GLenum target, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetMinmaxParameterfv(GLenum target, GLenum pname, GLfloat *params); + +extern void GLAPIENTRY +_mesa_GetMinmaxParameteriv(GLenum target, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_Histogram(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); + +extern void GLAPIENTRY +_mesa_Minmax(GLenum target, GLenum internalformat, GLboolean sink); + +extern void GLAPIENTRY +_mesa_ResetHistogram(GLenum target); + +extern void GLAPIENTRY +_mesa_ResetMinmax(GLenum target); + +extern void +_mesa_update_minmax(GLcontext *ctx, GLuint n, const GLfloat rgba[][4]); + +extern void +_mesa_update_histogram(GLcontext *ctx, GLuint n, const GLfloat rgba[][4]); + +extern void _mesa_init_histogram( GLcontext * ctx ); + +#else + +/** No-op */ +#define _mesa_init_histogram( c ) ((void) 0) + +#endif + +#endif diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c new file mode 100644 index 00000000000..12f8352c2d2 --- /dev/null +++ b/src/mesa/main/image.c @@ -0,0 +1,4201 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file image.c + * Image handling. + */ + + +#include "glheader.h" +#include "bufferobj.h" +#include "colormac.h" +#include "context.h" +#include "image.h" +#include "imports.h" +#include "histogram.h" +#include "macros.h" +#include "pixel.h" +#include "mtypes.h" + + +/** Compute ceiling of integer quotient of A divided by B. */ +#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) + + +/** + * Flip the 8 bits in each byte of the given array. + * + * \param p array. + * \param n number of bytes. + * + * \todo try this trick to flip bytes someday: + * \code + * v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); + * v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); + * v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); + * \endcode + */ +static void +flip_bytes( GLubyte *p, GLuint n ) +{ + register GLuint i, a, b; + + for (i=0;i<n;i++) { + b = (GLuint) p[i]; /* words are often faster than bytes */ + a = ((b & 0x01) << 7) | + ((b & 0x02) << 5) | + ((b & 0x04) << 3) | + ((b & 0x08) << 1) | + ((b & 0x10) >> 1) | + ((b & 0x20) >> 3) | + ((b & 0x40) >> 5) | + ((b & 0x80) >> 7); + p[i] = (GLubyte) a; + } +} + + +/** + * Flip the order of the 2 bytes in each word in the given array. + * + * \param p array. + * \param n number of words. + */ +void +_mesa_swap2( GLushort *p, GLuint n ) +{ + register GLuint i; + + for (i=0;i<n;i++) { + p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); + } +} + + + +/* + * Flip the order of the 4 bytes in each word in the given array. + */ +void +_mesa_swap4( GLuint *p, GLuint n ) +{ + register GLuint i, a, b; + + for (i=0;i<n;i++) { + b = p[i]; + a = (b >> 24) + | ((b >> 8) & 0xff00) + | ((b << 8) & 0xff0000) + | ((b << 24) & 0xff000000); + p[i] = a; + } +} + + +/** + * Get the size of a GL data type. + * + * \param type GL data type. + * + * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1 + * if an invalid type enum. + */ +GLint _mesa_sizeof_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_HALF_FLOAT_ARB: + return sizeof(GLhalfARB); + default: + return -1; + } +} + + +/** + * Same as _mesa_sizeof_type() but also accepting the packed pixel + * format data types. + */ +GLint _mesa_sizeof_packed_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_HALF_FLOAT_ARB: + return sizeof(GLhalfARB); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_UNSIGNED_BYTE_3_3_2: + return sizeof(GLubyte); + case GL_UNSIGNED_BYTE_2_3_3_REV: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT_5_6_5: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_5_6_5_REV: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_4_4_4_4: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_5_5_5_1: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return sizeof(GLushort); + case GL_UNSIGNED_INT_8_8_8_8: + return sizeof(GLuint); + case GL_UNSIGNED_INT_8_8_8_8_REV: + return sizeof(GLuint); + case GL_UNSIGNED_INT_10_10_10_2: + return sizeof(GLuint); + case GL_UNSIGNED_INT_2_10_10_10_REV: + return sizeof(GLuint); + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + return sizeof(GLushort); + default: + return -1; + } +} + + +/** + * Get the number of components in a pixel format. + * + * \param format pixel format. + * + * \return the number of components in the given format, or -1 if a bad format. + */ +GLint _mesa_components_in_format( GLenum format ) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + return 1; + case GL_LUMINANCE_ALPHA: + return 2; + case GL_RGB: + return 3; + case GL_RGBA: + return 4; + case GL_BGR: + return 3; + case GL_BGRA: + return 4; + case GL_ABGR_EXT: + return 4; + case GL_YCBCR_MESA: + return 2; + default: + return -1; + } +} + + +/** + * Get the bytes per pixel of pixel format type pair. + * + * \param format pixel format. + * \param type pixel type. + * + * \return bytes per pixel, or -1 if a bad format or type was given. + */ +GLint _mesa_bytes_per_pixel( GLenum format, GLenum type ) +{ + GLint comps = _mesa_components_in_format( format ); + if (comps < 0) + return -1; + + switch (type) { + case GL_BITMAP: + return 0; /* special case */ + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return comps * sizeof(GLubyte); + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return comps * sizeof(GLshort); + case GL_INT: + case GL_UNSIGNED_INT: + return comps * sizeof(GLint); + case GL_FLOAT: + return comps * sizeof(GLfloat); + case GL_HALF_FLOAT_ARB: + return comps * sizeof(GLhalfARB); + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (format == GL_RGB || format == GL_BGR) + return sizeof(GLubyte); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (format == GL_RGB || format == GL_BGR) + return sizeof(GLushort); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT) + return sizeof(GLushort); + else + return -1; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT) + return sizeof(GLuint); + else + return -1; + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + if (format == GL_YCBCR_MESA) + return sizeof(GLushort); + else + return -1; + default: + return -1; + } +} + + +/** + * Test for a legal pixel format and type. + * + * \param format pixel format. + * \param type pixel type. + * + * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE + * otherwise. + */ +GLboolean +_mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type ) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + switch (type) { + case GL_BITMAP: + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: +#if 0 /* not legal! see table 3.6 of the 1.5 spec */ + case GL_INTENSITY: +#endif + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_DEPTH_COMPONENT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RGB: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_BGR: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_MESA || + type == GL_UNSIGNED_SHORT_8_8_REV_MESA) + return GL_TRUE; + else + return GL_FALSE; + default: + ; /* fall-through */ + } + return GL_FALSE; +} + + +/** + * Return the address of a specific pixel in an image (1D, 2D or 3D). + * + * Pixel unpacking/packing parameters are observed according to \p packing. + * + * \param dimensions either 1, 2 or 3 to indicate dimensionality of image + * \param image starting address of image data + * \param width the image width + * \param height theimage height + * \param format the pixel format + * \param type the pixel data type + * \param packing the pixelstore attributes + * \param img which image in the volume (0 for 1D or 2D images) + * \param row row of pixel in the image (0 for 1D images) + * \param column column of pixel in the image + * + * \return address of pixel on success, or NULL on error. + * + * \sa gl_pixelstore_attrib. + */ +GLvoid * +_mesa_image_address( GLuint dimensions, + const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + GLint alignment; /* 1, 2 or 4 */ + GLint pixels_per_row; + GLint rows_per_image; + GLint skiprows; + GLint skippixels; + GLint skipimages; /* for 3-D volume images */ + GLubyte *pixel_addr; + + ASSERT(dimensions >= 1 && dimensions <= 3); + + alignment = packing->Alignment; + if (packing->RowLength > 0) { + pixels_per_row = packing->RowLength; + } + else { + pixels_per_row = width; + } + if (packing->ImageHeight > 0) { + rows_per_image = packing->ImageHeight; + } + else { + rows_per_image = height; + } + + skippixels = packing->SkipPixels; + /* Note: SKIP_ROWS _is_ used for 1D images */ + skiprows = packing->SkipRows; + /* Note: SKIP_IMAGES is only used for 3D images */ + skipimages = (dimensions == 3) ? packing->SkipImages : 0; + + if (type == GL_BITMAP) { + /* BITMAP data */ + GLint comp_per_pixel; /* components per pixel */ + GLint bytes_per_comp; /* bytes per component */ + GLint bytes_per_row; + GLint bytes_per_image; + + /* Compute bytes per component */ + bytes_per_comp = _mesa_sizeof_packed_type( type ); + if (bytes_per_comp < 0) { + return NULL; + } + + /* Compute number of components per pixel */ + comp_per_pixel = _mesa_components_in_format( format ); + if (comp_per_pixel < 0) { + return NULL; + } + + bytes_per_row = alignment + * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); + + bytes_per_image = bytes_per_row * rows_per_image; + + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + (skiprows + row) * bytes_per_row + + (skippixels + column) / 8; + } + else { + /* Non-BITMAP data */ + GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; + GLint topOfImage; + + bytes_per_pixel = _mesa_bytes_per_pixel( format, type ); + + /* The pixel type and format should have been error checked earlier */ + assert(bytes_per_pixel > 0); + + bytes_per_row = pixels_per_row * bytes_per_pixel; + remainder = bytes_per_row % alignment; + if (remainder > 0) + bytes_per_row += (alignment - remainder); + + ASSERT(bytes_per_row % alignment == 0); + + bytes_per_image = bytes_per_row * rows_per_image; + + if (packing->Invert) { + /* set pixel_addr to the last row */ + topOfImage = bytes_per_row * (height - 1); + bytes_per_row = -bytes_per_row; + } + else { + topOfImage = 0; + } + + /* compute final pixel address */ + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + topOfImage + + (skiprows + row) * bytes_per_row + + (skippixels + column) * bytes_per_pixel; + } + + return (GLvoid *) pixel_addr; +} + + +GLvoid * +_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, + GLenum format, GLenum type, + GLint column ) +{ + return _mesa_image_address(1, packing, image, width, 1, + format, type, 0, 0, column); +} + + +GLvoid * +_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint row, GLint column ) +{ + return _mesa_image_address(2, packing, image, width, height, + format, type, 0, row, column); +} + + +GLvoid * +_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + return _mesa_image_address(3, packing, image, width, height, + format, type, img, row, column); +} + + + +/** + * Compute the stride between image rows. + * + * \param packing the pixelstore attributes + * \param width image width. + * \param format pixel format. + * \param type pixel data type. + * + * \return the stride in bytes for the given parameters. + * + * Computes the number of bytes per pixel and row and compensates for alignment. + * + * \sa gl_pixelstore_attrib. + */ +GLint +_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLenum format, GLenum type ) +{ + ASSERT(packing); + if (type == GL_BITMAP) { + /* BITMAP data */ + GLint bytes; + if (packing->RowLength == 0) { + bytes = (width + 7) / 8; + } + else { + bytes = (packing->RowLength + 7) / 8; + } + if (packing->Invert) { + /* negate the bytes per row (negative row stride) */ + bytes = -bytes; + } + return bytes; + } + else { + /* Non-BITMAP data */ + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + GLint bytesPerRow, remainder; + if (bytesPerPixel <= 0) + return -1; /* error */ + if (packing->RowLength == 0) { + bytesPerRow = bytesPerPixel * width; + } + else { + bytesPerRow = bytesPerPixel * packing->RowLength; + } + remainder = bytesPerRow % packing->Alignment; + if (remainder > 0) + bytesPerRow += (packing->Alignment - remainder); + if (packing->Invert) + bytesPerRow = -bytesPerRow; + return bytesPerRow; + } +} + + +#if _HAVE_FULL_GL + +/* + * Compute the stride between images in a 3D texture (in bytes) for the given + * pixel packing parameters and image width, format and type. + */ +GLint +_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLint height, + GLenum format, GLenum type ) +{ + ASSERT(packing); + ASSERT(type != GL_BITMAP); + + { + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + GLint bytesPerRow, bytesPerImage, remainder; + + if (bytesPerPixel <= 0) + return -1; /* error */ + if (packing->RowLength == 0) { + bytesPerRow = bytesPerPixel * width; + } + else { + bytesPerRow = bytesPerPixel * packing->RowLength; + } + remainder = bytesPerRow % packing->Alignment; + if (remainder > 0) + bytesPerRow += (packing->Alignment - remainder); + + if (packing->ImageHeight == 0) + bytesPerImage = bytesPerRow * height; + else + bytesPerImage = bytesPerRow * packing->ImageHeight; + + return bytesPerImage; + } +} + + +/* + * Unpack a 32x32 pixel polygon stipple from user memory using the + * current pixel unpack settings. + */ +void +_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32], + const struct gl_pixelstore_attrib *unpacking ) +{ + GLubyte *ptrn = (GLubyte *) _mesa_unpack_bitmap( 32, 32, pattern, unpacking ); + if (ptrn) { + /* Convert pattern from GLubytes to GLuints and handle big/little + * endian differences + */ + GLubyte *p = ptrn; + GLint i; + for (i = 0; i < 32; i++) { + dest[i] = (p[0] << 24) + | (p[1] << 16) + | (p[2] << 8) + | (p[3] ); + p += 4; + } + FREE(ptrn); + } +} + + +/* + * Pack polygon stipple into user memory given current pixel packing + * settings. + */ +void +_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest, + const struct gl_pixelstore_attrib *packing ) +{ + /* Convert pattern from GLuints to GLubytes to handle big/little + * endian differences. + */ + GLubyte ptrn[32*4]; + GLint i; + for (i = 0; i < 32; i++) { + ptrn[i * 4 + 0] = (GLubyte) ((pattern[i] >> 24) & 0xff); + ptrn[i * 4 + 1] = (GLubyte) ((pattern[i] >> 16) & 0xff); + ptrn[i * 4 + 2] = (GLubyte) ((pattern[i] >> 8 ) & 0xff); + ptrn[i * 4 + 3] = (GLubyte) ((pattern[i] ) & 0xff); + } + + _mesa_pack_bitmap(32, 32, ptrn, dest, packing); +} + + +/* + * Unpack bitmap data. Resulting data will be in most-significant-bit-first + * order with row alignment = 1 byte. + */ +GLvoid * +_mesa_unpack_bitmap( GLint width, GLint height, const GLubyte *pixels, + const struct gl_pixelstore_attrib *packing ) +{ + GLint bytes, row, width_in_bytes; + GLubyte *buffer, *dst; + + if (!pixels) + return NULL; + + /* Alloc dest storage */ + bytes = ((width + 7) / 8 * height); + buffer = (GLubyte *) MALLOC( bytes ); + if (!buffer) + return NULL; + + + width_in_bytes = CEILING( width, 8 ); + dst = buffer; + for (row = 0; row < height; row++) { + const GLubyte *src = (const GLubyte *) + _mesa_image_address2d(packing, pixels, width, height, + GL_COLOR_INDEX, GL_BITMAP, row, 0); + if (!src) { + FREE(buffer); + return NULL; + } + + if (packing->SkipPixels == 0) { + MEMCPY( dst, src, width_in_bytes ); + if (packing->LsbFirst) { + flip_bytes( dst, width_in_bytes ); + } + } + else { + /* handling SkipPixels is a bit tricky (no pun intended!) */ + GLint i; + if (packing->LsbFirst) { + GLubyte srcMask = 1 << (packing->SkipPixels & 0x7); + GLubyte dstMask = 128; + const GLubyte *s = src; + GLubyte *d = dst; + *d = 0; + for (i = 0; i < width; i++) { + if (*s & srcMask) { + *d |= dstMask; + } + if (srcMask == 128) { + srcMask = 1; + s++; + } + else { + srcMask = srcMask << 1; + } + if (dstMask == 1) { + dstMask = 128; + d++; + *d = 0; + } + else { + dstMask = dstMask >> 1; + } + } + } + else { + GLubyte srcMask = 128 >> (packing->SkipPixels & 0x7); + GLubyte dstMask = 128; + const GLubyte *s = src; + GLubyte *d = dst; + *d = 0; + for (i = 0; i < width; i++) { + if (*s & srcMask) { + *d |= dstMask; + } + if (srcMask == 1) { + srcMask = 128; + s++; + } + else { + srcMask = srcMask >> 1; + } + if (dstMask == 1) { + dstMask = 128; + d++; + *d = 0; + } + else { + dstMask = dstMask >> 1; + } + } + } + } + dst += width_in_bytes; + } + + return buffer; +} + + +/* + * Pack bitmap data. + */ +void +_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source, + GLubyte *dest, const struct gl_pixelstore_attrib *packing ) +{ + GLint row, width_in_bytes; + const GLubyte *src; + + if (!source) + return; + + width_in_bytes = CEILING( width, 8 ); + src = source; + for (row = 0; row < height; row++) { + GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, dest, + width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0); + if (!dst) + return; + + if (packing->SkipPixels == 0) { + MEMCPY( dst, src, width_in_bytes ); + if (packing->LsbFirst) { + flip_bytes( dst, width_in_bytes ); + } + } + else { + /* handling SkipPixels is a bit tricky (no pun intended!) */ + GLint i; + if (packing->LsbFirst) { + GLubyte srcMask = 1 << (packing->SkipPixels & 0x7); + GLubyte dstMask = 128; + const GLubyte *s = src; + GLubyte *d = dst; + *d = 0; + for (i = 0; i < width; i++) { + if (*s & srcMask) { + *d |= dstMask; + } + if (srcMask == 128) { + srcMask = 1; + s++; + } + else { + srcMask = srcMask << 1; + } + if (dstMask == 1) { + dstMask = 128; + d++; + *d = 0; + } + else { + dstMask = dstMask >> 1; + } + } + } + else { + GLubyte srcMask = 128 >> (packing->SkipPixels & 0x7); + GLubyte dstMask = 128; + const GLubyte *s = src; + GLubyte *d = dst; + *d = 0; + for (i = 0; i < width; i++) { + if (*s & srcMask) { + *d |= dstMask; + } + if (srcMask == 1) { + srcMask = 128; + s++; + } + else { + srcMask = srcMask >> 1; + } + if (dstMask == 1) { + dstMask = 128; + d++; + *d = 0; + } + else { + dstMask = dstMask >> 1; + } + } + } + } + src += width_in_bytes; + } +} + + +/** + * Apply various pixel transfer operations to an array of RGBA pixels + * as indicated by the transferOps bitmask + */ +void +_mesa_apply_rgba_transfer_ops(GLcontext *ctx, GLuint transferOps, + GLuint n, GLfloat rgba[][4]) +{ + /* scale & bias */ + if (transferOps & IMAGE_SCALE_BIAS_BIT) { + _mesa_scale_and_bias_rgba(n, rgba, + ctx->Pixel.RedScale, ctx->Pixel.GreenScale, + ctx->Pixel.BlueScale, ctx->Pixel.AlphaScale, + ctx->Pixel.RedBias, ctx->Pixel.GreenBias, + ctx->Pixel.BlueBias, ctx->Pixel.AlphaBias); + } + /* color map lookup */ + if (transferOps & IMAGE_MAP_COLOR_BIT) { + _mesa_map_rgba( ctx, n, rgba ); + } + /* GL_COLOR_TABLE lookup */ + if (transferOps & IMAGE_COLOR_TABLE_BIT) { + _mesa_lookup_rgba_float(&ctx->ColorTable, n, rgba); + } + /* convolution */ + if (transferOps & IMAGE_CONVOLUTION_BIT) { + /* this has to be done in the calling code */ + _mesa_problem(ctx, "IMAGE_CONVOLUTION_BIT set in _mesa_apply_transfer_ops"); + } + /* GL_POST_CONVOLUTION_RED/GREEN/BLUE/ALPHA_SCALE/BIAS */ + if (transferOps & IMAGE_POST_CONVOLUTION_SCALE_BIAS) { + _mesa_scale_and_bias_rgba(n, rgba, + ctx->Pixel.PostConvolutionScale[RCOMP], + ctx->Pixel.PostConvolutionScale[GCOMP], + ctx->Pixel.PostConvolutionScale[BCOMP], + ctx->Pixel.PostConvolutionScale[ACOMP], + ctx->Pixel.PostConvolutionBias[RCOMP], + ctx->Pixel.PostConvolutionBias[GCOMP], + ctx->Pixel.PostConvolutionBias[BCOMP], + ctx->Pixel.PostConvolutionBias[ACOMP]); + } + /* GL_POST_CONVOLUTION_COLOR_TABLE lookup */ + if (transferOps & IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT) { + _mesa_lookup_rgba_float(&ctx->PostConvolutionColorTable, n, rgba); + } + /* color matrix transform */ + if (transferOps & IMAGE_COLOR_MATRIX_BIT) { + _mesa_transform_rgba(ctx, n, rgba); + } + /* GL_POST_COLOR_MATRIX_COLOR_TABLE lookup */ + if (transferOps & IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT) { + _mesa_lookup_rgba_float(&ctx->PostColorMatrixColorTable, n, rgba); + } + /* update histogram count */ + if (transferOps & IMAGE_HISTOGRAM_BIT) { + _mesa_update_histogram(ctx, n, (CONST GLfloat (*)[4]) rgba); + } + /* update min/max values */ + if (transferOps & IMAGE_MIN_MAX_BIT) { + _mesa_update_minmax(ctx, n, (CONST GLfloat (*)[4]) rgba); + } + /* clamping to [0,1] */ + if (transferOps & IMAGE_CLAMP_BIT) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); + rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); + rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); + rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); + } + } +} + + + +/* + * Used to pack an array [][4] of RGBA float colors as specified + * by the dstFormat, dstType and dstPacking. Used by glReadPixels, + * glGetConvolutionFilter(), etc. + */ +void +_mesa_pack_rgba_span_float( GLcontext *ctx, + GLuint n, CONST GLfloat rgbaIn[][4], + GLenum dstFormat, GLenum dstType, + GLvoid *dstAddr, + const struct gl_pixelstore_attrib *dstPacking, + GLuint transferOps ) +{ + const GLint comps = _mesa_components_in_format(dstFormat); + GLfloat luminance[MAX_WIDTH]; + const GLfloat (*rgba)[4]; + GLuint i; + + if (transferOps) { + /* make copy of incoming data */ + DEFMARRAY(GLfloat, rgbaCopy, MAX_WIDTH, 4); /* mac 32k limitation */ + CHECKARRAY(rgbaCopy, return); /* mac 32k limitation */ + + _mesa_memcpy(rgbaCopy, rgbaIn, n * 4 * sizeof(GLfloat)); + _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgbaCopy); + rgba = (const GLfloat (*)[4]) rgbaCopy; + + if ((transferOps & IMAGE_MIN_MAX_BIT) && ctx->MinMax.Sink) { + UNDEFARRAY(rgbaCopy); /* mac 32k limitation */ + return; + } + UNDEFARRAY(rgbaCopy); /* mac 32k limitation */ + } + else { + /* use incoming data, not a copy */ + rgba = (const GLfloat (*)[4]) rgbaIn; + } + + if (dstFormat == GL_LUMINANCE || dstFormat == GL_LUMINANCE_ALPHA) { + /* compute luminance values */ + if (ctx->ClampFragmentColors) { + for (i = 0; i < n; i++) { + GLfloat sum = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP]; + luminance[i] = CLAMP(sum, 0.0F, 1.0F); + } + } + else { + for (i = 0; i < n; i++) { + luminance[i] = rgba[i][RCOMP] + rgba[i][GCOMP] + rgba[i][BCOMP]; + } + } + } + + /* + * Pack/store the pixels. Ugh! Lots of cases!!! + */ + switch (dstType) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UBYTE(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_UBYTE(luminance[i]); + dst[i*2+1] = FLOAT_TO_UBYTE(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + dst[i*3+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + dst[i*4+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + dst[i*3+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + dst[i*4+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][ACOMP]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UBYTE(rgba[i][ACOMP]); + dst[i*4+1] = FLOAT_TO_UBYTE(rgba[i][BCOMP]); + dst[i*4+2] = FLOAT_TO_UBYTE(rgba[i][GCOMP]); + dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + } + break; + case GL_BYTE: + { + GLbyte *dst = (GLbyte *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_BYTE(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_BYTE(luminance[i]); + dst[i*2+1] = FLOAT_TO_BYTE(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]); + dst[i*3+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_BYTE(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]); + dst[i*4+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_BYTE(rgba[i][BCOMP]); + dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_BYTE(rgba[i][BCOMP]); + dst[i*3+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_BYTE(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_BYTE(rgba[i][BCOMP]); + dst[i*4+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_BYTE(rgba[i][RCOMP]); + dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][ACOMP]); + } + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_BYTE(rgba[i][ACOMP]); + dst[i*4+1] = FLOAT_TO_BYTE(rgba[i][BCOMP]); + dst[i*4+2] = FLOAT_TO_BYTE(rgba[i][GCOMP]); + dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *dst = (GLushort *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_USHORT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_USHORT(luminance[i]); + dst[i*2+1] = FLOAT_TO_USHORT(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_USHORT(rgba[i][RCOMP]); + dst[i*3+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_USHORT(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_USHORT(rgba[i][RCOMP]); + dst[i*4+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_USHORT(rgba[i][BCOMP]); + dst[i*4+3] = FLOAT_TO_USHORT(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_USHORT(rgba[i][BCOMP]); + dst[i*3+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_USHORT(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_USHORT(rgba[i][BCOMP]); + dst[i*4+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_USHORT(rgba[i][RCOMP]); + dst[i*4+3] = FLOAT_TO_USHORT(rgba[i][ACOMP]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_USHORT(rgba[i][ACOMP]); + dst[i*4+1] = FLOAT_TO_USHORT(rgba[i][BCOMP]); + dst[i*4+2] = FLOAT_TO_USHORT(rgba[i][GCOMP]); + dst[i*4+3] = FLOAT_TO_USHORT(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n * comps); + } + } + break; + case GL_SHORT: + { + GLshort *dst = (GLshort *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_SHORT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_SHORT(luminance[i]); + dst[i*2+1] = FLOAT_TO_SHORT(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]); + dst[i*3+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_SHORT(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]); + dst[i*4+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_SHORT(rgba[i][BCOMP]); + dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_SHORT(rgba[i][BCOMP]); + dst[i*3+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_SHORT(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_SHORT(rgba[i][BCOMP]); + dst[i*4+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_SHORT(rgba[i][RCOMP]); + dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][ACOMP]); + } + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_SHORT(rgba[i][ACOMP]); + dst[i*4+1] = FLOAT_TO_SHORT(rgba[i][BCOMP]); + dst[i*4+2] = FLOAT_TO_SHORT(rgba[i][GCOMP]); + dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n * comps ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *dst = (GLuint *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_UINT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_UINT(luminance[i]); + dst[i*2+1] = FLOAT_TO_UINT(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UINT(rgba[i][RCOMP]); + dst[i*3+1] = FLOAT_TO_UINT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_UINT(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UINT(rgba[i][RCOMP]); + dst[i*4+1] = FLOAT_TO_UINT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_UINT(rgba[i][BCOMP]); + dst[i*4+3] = FLOAT_TO_UINT(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_UINT(rgba[i][BCOMP]); + dst[i*3+1] = FLOAT_TO_UINT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_UINT(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UINT(rgba[i][BCOMP]); + dst[i*4+1] = FLOAT_TO_UINT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_UINT(rgba[i][RCOMP]); + dst[i*4+3] = FLOAT_TO_UINT(rgba[i][ACOMP]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_UINT(rgba[i][ACOMP]); + dst[i*4+1] = FLOAT_TO_UINT(rgba[i][BCOMP]); + dst[i*4+2] = FLOAT_TO_UINT(rgba[i][GCOMP]); + dst[i*4+3] = FLOAT_TO_UINT(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n * comps ); + } + } + break; + case GL_INT: + { + GLint *dst = (GLint *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = FLOAT_TO_INT(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = FLOAT_TO_INT(luminance[i]); + dst[i*2+1] = FLOAT_TO_INT(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_INT(rgba[i][RCOMP]); + dst[i*3+1] = FLOAT_TO_INT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_INT(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_INT(rgba[i][RCOMP]); + dst[i*4+1] = FLOAT_TO_INT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_INT(rgba[i][BCOMP]); + dst[i*4+3] = FLOAT_TO_INT(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = FLOAT_TO_INT(rgba[i][BCOMP]); + dst[i*3+1] = FLOAT_TO_INT(rgba[i][GCOMP]); + dst[i*3+2] = FLOAT_TO_INT(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_INT(rgba[i][BCOMP]); + dst[i*4+1] = FLOAT_TO_INT(rgba[i][GCOMP]); + dst[i*4+2] = FLOAT_TO_INT(rgba[i][RCOMP]); + dst[i*4+3] = FLOAT_TO_INT(rgba[i][ACOMP]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = FLOAT_TO_INT(rgba[i][ACOMP]); + dst[i*4+1] = FLOAT_TO_INT(rgba[i][BCOMP]); + dst[i*4+2] = FLOAT_TO_INT(rgba[i][GCOMP]); + dst[i*4+3] = FLOAT_TO_INT(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n * comps ); + } + } + break; + case GL_FLOAT: + { + GLfloat *dst = (GLfloat *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = rgba[i][RCOMP]; + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = rgba[i][GCOMP]; + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = rgba[i][BCOMP]; + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = rgba[i][ACOMP]; + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = luminance[i]; + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = luminance[i]; + dst[i*2+1] = rgba[i][ACOMP]; + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = rgba[i][RCOMP]; + dst[i*3+1] = rgba[i][GCOMP]; + dst[i*3+2] = rgba[i][BCOMP]; + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = rgba[i][RCOMP]; + dst[i*4+1] = rgba[i][GCOMP]; + dst[i*4+2] = rgba[i][BCOMP]; + dst[i*4+3] = rgba[i][ACOMP]; + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = rgba[i][BCOMP]; + dst[i*3+1] = rgba[i][GCOMP]; + dst[i*3+2] = rgba[i][RCOMP]; + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = rgba[i][BCOMP]; + dst[i*4+1] = rgba[i][GCOMP]; + dst[i*4+2] = rgba[i][RCOMP]; + dst[i*4+3] = rgba[i][ACOMP]; + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = rgba[i][ACOMP]; + dst[i*4+1] = rgba[i][BCOMP]; + dst[i*4+2] = rgba[i][GCOMP]; + dst[i*4+3] = rgba[i][RCOMP]; + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n * comps ); + } + } + break; + case GL_HALF_FLOAT_ARB: + { + GLhalfARB *dst = (GLhalfARB *) dstAddr; + switch (dstFormat) { + case GL_RED: + for (i=0;i<n;i++) + dst[i] = _mesa_float_to_half(rgba[i][RCOMP]); + break; + case GL_GREEN: + for (i=0;i<n;i++) + dst[i] = _mesa_float_to_half(rgba[i][GCOMP]); + break; + case GL_BLUE: + for (i=0;i<n;i++) + dst[i] = _mesa_float_to_half(rgba[i][BCOMP]); + break; + case GL_ALPHA: + for (i=0;i<n;i++) + dst[i] = _mesa_float_to_half(rgba[i][ACOMP]); + break; + case GL_LUMINANCE: + for (i=0;i<n;i++) + dst[i] = _mesa_float_to_half(luminance[i]); + break; + case GL_LUMINANCE_ALPHA: + for (i=0;i<n;i++) { + dst[i*2+0] = _mesa_float_to_half(luminance[i]); + dst[i*2+1] = _mesa_float_to_half(rgba[i][ACOMP]); + } + break; + case GL_RGB: + for (i=0;i<n;i++) { + dst[i*3+0] = _mesa_float_to_half(rgba[i][RCOMP]); + dst[i*3+1] = _mesa_float_to_half(rgba[i][GCOMP]); + dst[i*3+2] = _mesa_float_to_half(rgba[i][BCOMP]); + } + break; + case GL_RGBA: + for (i=0;i<n;i++) { + dst[i*4+0] = _mesa_float_to_half(rgba[i][RCOMP]); + dst[i*4+1] = _mesa_float_to_half(rgba[i][GCOMP]); + dst[i*4+2] = _mesa_float_to_half(rgba[i][BCOMP]); + dst[i*4+3] = _mesa_float_to_half(rgba[i][ACOMP]); + } + break; + case GL_BGR: + for (i=0;i<n;i++) { + dst[i*3+0] = _mesa_float_to_half(rgba[i][BCOMP]); + dst[i*3+1] = _mesa_float_to_half(rgba[i][GCOMP]); + dst[i*3+2] = _mesa_float_to_half(rgba[i][RCOMP]); + } + break; + case GL_BGRA: + for (i=0;i<n;i++) { + dst[i*4+0] = _mesa_float_to_half(rgba[i][BCOMP]); + dst[i*4+1] = _mesa_float_to_half(rgba[i][GCOMP]); + dst[i*4+2] = _mesa_float_to_half(rgba[i][RCOMP]); + dst[i*4+3] = _mesa_float_to_half(rgba[i][ACOMP]); + } + break; + case GL_ABGR_EXT: + for (i=0;i<n;i++) { + dst[i*4+0] = _mesa_float_to_half(rgba[i][ACOMP]); + dst[i*4+1] = _mesa_float_to_half(rgba[i][BCOMP]); + dst[i*4+2] = _mesa_float_to_half(rgba[i][GCOMP]); + dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]); + } + break; + default: + _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n * comps ); + } + } + break; + case GL_UNSIGNED_BYTE_3_3_2: + if (dstFormat == GL_RGB) { + GLubyte *dst = (GLubyte *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 7.0F)) << 5) + | (((GLint) (rgba[i][GCOMP] * 7.0F)) << 2) + | (((GLint) (rgba[i][BCOMP] * 3.0F)) ); + } + } + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (dstFormat == GL_RGB) { + GLubyte *dst = (GLubyte *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 7.0F)) ) + | (((GLint) (rgba[i][GCOMP] * 7.0F)) << 3) + | (((GLint) (rgba[i][BCOMP] * 3.0F)) << 5); + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + if (dstFormat == GL_RGB) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) << 11) + | (((GLint) (rgba[i][GCOMP] * 63.0F)) << 5) + | (((GLint) (rgba[i][BCOMP] * 31.0F)) ); + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (dstFormat == GL_RGB) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) ) + | (((GLint) (rgba[i][GCOMP] * 63.0F)) << 5) + | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 11); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + if (dstFormat == GL_RGBA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 15.0F)) << 12) + | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 8) + | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 4) + | (((GLint) (rgba[i][ACOMP] * 15.0F)) ); + } + } + else if (dstFormat == GL_BGRA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][BCOMP] * 15.0F)) << 12) + | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 8) + | (((GLint) (rgba[i][RCOMP] * 15.0F)) << 4) + | (((GLint) (rgba[i][ACOMP] * 15.0F)) ); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][ACOMP] * 15.0F)) << 4) + | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 8) + | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 12) + | (((GLint) (rgba[i][RCOMP] * 15.0F)) ); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + if (dstFormat == GL_RGBA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 15.0F)) ) + | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 4) + | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 8) + | (((GLint) (rgba[i][ACOMP] * 15.0F)) << 12); + } + } + else if (dstFormat == GL_BGRA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][BCOMP] * 15.0F)) ) + | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 4) + | (((GLint) (rgba[i][RCOMP] * 15.0F)) << 8) + | (((GLint) (rgba[i][ACOMP] * 15.0F)) << 12); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][ACOMP] * 15.0F)) ) + | (((GLint) (rgba[i][BCOMP] * 15.0F)) << 4) + | (((GLint) (rgba[i][GCOMP] * 15.0F)) << 8) + | (((GLint) (rgba[i][RCOMP] * 15.0F)) << 12); + } + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + if (dstFormat == GL_RGBA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) << 11) + | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 6) + | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 1) + | (((GLint) (rgba[i][ACOMP] * 1.0F)) ); + } + } + else if (dstFormat == GL_BGRA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][BCOMP] * 31.0F)) << 11) + | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 6) + | (((GLint) (rgba[i][RCOMP] * 31.0F)) << 1) + | (((GLint) (rgba[i][ACOMP] * 1.0F)) ); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][ACOMP] * 31.0F)) << 11) + | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 6) + | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 1) + | (((GLint) (rgba[i][RCOMP] * 1.0F)) ); + } + } + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (dstFormat == GL_RGBA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][RCOMP] * 31.0F)) ) + | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 5) + | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 10) + | (((GLint) (rgba[i][ACOMP] * 1.0F)) << 15); + } + } + else if (dstFormat == GL_BGRA) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][BCOMP] * 31.0F)) ) + | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 5) + | (((GLint) (rgba[i][RCOMP] * 31.0F)) << 10) + | (((GLint) (rgba[i][ACOMP] * 1.0F)) << 15); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLushort *dst = (GLushort *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLint) (rgba[i][ACOMP] * 31.0F)) ) + | (((GLint) (rgba[i][BCOMP] * 31.0F)) << 5) + | (((GLint) (rgba[i][GCOMP] * 31.0F)) << 10) + | (((GLint) (rgba[i][RCOMP] * 1.0F)) << 15); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8: + if (dstFormat == GL_RGBA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 24) + | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 16) + | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 8) + | (((GLuint) (rgba[i][ACOMP] * 255.0F)) ); + } + } + else if (dstFormat == GL_BGRA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 24) + | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 16) + | (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 8) + | (((GLuint) (rgba[i][ACOMP] * 255.0F)) ); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][ACOMP] * 255.0F)) << 24) + | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 16) + | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 8) + | (((GLuint) (rgba[i][RCOMP] * 255.0F)) ); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + if (dstFormat == GL_RGBA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][RCOMP] * 255.0F)) ) + | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 8) + | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 16) + | (((GLuint) (rgba[i][ACOMP] * 255.0F)) << 24); + } + } + else if (dstFormat == GL_BGRA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][BCOMP] * 255.0F)) ) + | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 8) + | (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 16) + | (((GLuint) (rgba[i][ACOMP] * 255.0F)) << 24); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][ACOMP] * 255.0F)) ) + | (((GLuint) (rgba[i][BCOMP] * 255.0F)) << 8) + | (((GLuint) (rgba[i][GCOMP] * 255.0F)) << 16) + | (((GLuint) (rgba[i][RCOMP] * 255.0F)) << 24); + } + } + break; + case GL_UNSIGNED_INT_10_10_10_2: + if (dstFormat == GL_RGBA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][RCOMP] * 1023.0F)) << 22) + | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 12) + | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 2) + | (((GLuint) (rgba[i][ACOMP] * 3.0F)) ); + } + } + else if (dstFormat == GL_BGRA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 22) + | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 12) + | (((GLuint) (rgba[i][RCOMP] * 1023.0F)) << 2) + | (((GLuint) (rgba[i][ACOMP] * 3.0F)) ); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][ACOMP] * 1023.0F)) << 22) + | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 12) + | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 2) + | (((GLuint) (rgba[i][RCOMP] * 3.0F)) ); + } + } + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (dstFormat == GL_RGBA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][RCOMP] * 1023.0F)) ) + | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 10) + | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 20) + | (((GLuint) (rgba[i][ACOMP] * 3.0F)) << 30); + } + } + else if (dstFormat == GL_BGRA) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][BCOMP] * 1023.0F)) ) + | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 10) + | (((GLuint) (rgba[i][RCOMP] * 1023.0F)) << 20) + | (((GLuint) (rgba[i][ACOMP] * 3.0F)) << 30); + } + } + else if (dstFormat == GL_ABGR_EXT) { + GLuint *dst = (GLuint *) dstAddr; + for (i=0;i<n;i++) { + dst[i] = (((GLuint) (rgba[i][ACOMP] * 1023.0F)) ) + | (((GLuint) (rgba[i][BCOMP] * 1023.0F)) << 10) + | (((GLuint) (rgba[i][GCOMP] * 1023.0F)) << 20) + | (((GLuint) (rgba[i][RCOMP] * 3.0F)) << 30); + } + } + break; + default: + _mesa_problem(ctx, "bad type in _mesa_pack_rgba_span_float"); + } +} + + +/* + * Pack the given RGBA span into client memory at 'dest' address + * in the given pixel format and type. + * Optionally apply the enabled pixel transfer ops. + * Pack into memory using the given packing params struct. + * This is used by glReadPixels and glGetTexImage?D() + * \param ctx - the context + * n - number of pixels in the span + * rgba - the pixels + * format - dest packing format + * type - dest packing data type + * destination - destination packing address + * packing - pixel packing parameters + * transferOps - bitmask of IMAGE_*_BIT operations to apply + */ +void +_mesa_pack_rgba_span_chan( GLcontext *ctx, + GLuint n, CONST GLchan srcRgba[][4], + GLenum dstFormat, GLenum dstType, + GLvoid *dstAddr, + const struct gl_pixelstore_attrib *dstPacking, + GLuint transferOps) +{ + ASSERT((ctx->NewState & _NEW_PIXEL) == 0 || transferOps == 0); + + /* Test for optimized case first */ + if (transferOps == 0 && dstFormat == GL_RGBA && dstType == CHAN_TYPE) { + /* common simple case */ + MEMCPY(dstAddr, srcRgba, n * 4 * sizeof(GLchan)); + } + else if (transferOps == 0 && dstFormat == GL_RGB && dstType == CHAN_TYPE) { + /* common simple case */ + GLuint i; + GLchan *dest = (GLchan *) dstAddr; + for (i = 0; i < n; i++) { + dest[0] = srcRgba[i][RCOMP]; + dest[1] = srcRgba[i][GCOMP]; + dest[2] = srcRgba[i][BCOMP]; + dest += 3; + } + } + else if (transferOps == 0 && dstFormat == GL_RGBA && dstType == GL_UNSIGNED_BYTE) { + /* common simple case */ + GLuint i; + GLubyte *dest = (GLubyte *) dstAddr; + for (i = 0; i < n; i++) { + dest[0] = CHAN_TO_UBYTE(srcRgba[i][RCOMP]); + dest[1] = CHAN_TO_UBYTE(srcRgba[i][GCOMP]); + dest[2] = CHAN_TO_UBYTE(srcRgba[i][BCOMP]); + dest[3] = CHAN_TO_UBYTE(srcRgba[i][ACOMP]); + dest += 4; + } + } + else { + /* general solution */ + GLuint i; + DEFMARRAY(GLfloat, rgba, MAX_WIDTH, 4); /* mac 32k limitation */ + CHECKARRAY(rgba, return); /* mac 32k limitation */ + + assert(n <= MAX_WIDTH); + /* convert color components to floating point */ + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = CHAN_TO_FLOAT(srcRgba[i][RCOMP]); + rgba[i][GCOMP] = CHAN_TO_FLOAT(srcRgba[i][GCOMP]); + rgba[i][BCOMP] = CHAN_TO_FLOAT(srcRgba[i][BCOMP]); + rgba[i][ACOMP] = CHAN_TO_FLOAT(srcRgba[i][ACOMP]); + } + _mesa_pack_rgba_span_float(ctx, n, (const GLfloat (*)[4]) rgba, + dstFormat, dstType, dstAddr, + dstPacking, transferOps); + UNDEFARRAY(rgba); /* mac 32k limitation */ + } +} + + +#define SWAP2BYTE(VALUE) \ + { \ + GLubyte *bytes = (GLubyte *) &(VALUE); \ + GLubyte tmp = bytes[0]; \ + bytes[0] = bytes[1]; \ + bytes[1] = tmp; \ + } + +#define SWAP4BYTE(VALUE) \ + { \ + GLubyte *bytes = (GLubyte *) &(VALUE); \ + GLubyte tmp = bytes[0]; \ + bytes[0] = bytes[3]; \ + bytes[3] = tmp; \ + tmp = bytes[1]; \ + bytes[1] = bytes[2]; \ + bytes[2] = tmp; \ + } + + +static void +extract_uint_indexes(GLuint n, GLuint indexes[], + GLenum srcFormat, GLenum srcType, const GLvoid *src, + const struct gl_pixelstore_attrib *unpack ) +{ + assert(srcFormat == GL_COLOR_INDEX); + + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_HALF_FLOAT_ARB || + srcType == GL_FLOAT); + + switch (srcType) { + case GL_BITMAP: + { + GLubyte *ubsrc = (GLubyte *) src; + if (unpack->LsbFirst) { + GLubyte mask = 1 << (unpack->SkipPixels & 0x7); + GLuint i; + for (i = 0; i < n; i++) { + indexes[i] = (*ubsrc & mask) ? 1 : 0; + if (mask == 128) { + mask = 1; + ubsrc++; + } + else { + mask = mask << 1; + } + } + } + else { + GLubyte mask = 128 >> (unpack->SkipPixels & 0x7); + GLuint i; + for (i = 0; i < n; i++) { + indexes[i] = (*ubsrc & mask) ? 1 : 0; + if (mask == 1) { + mask = 128; + ubsrc++; + } + else { + mask = mask >> 1; + } + } + } + } + break; + case GL_UNSIGNED_BYTE: + { + GLuint i; + const GLubyte *s = (const GLubyte *) src; + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + break; + case GL_BYTE: + { + GLuint i; + const GLbyte *s = (const GLbyte *) src; + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + break; + case GL_UNSIGNED_SHORT: + { + GLuint i; + const GLushort *s = (const GLushort *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLushort value = s[i]; + SWAP2BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_SHORT: + { + GLuint i; + const GLshort *s = (const GLshort *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLshort value = s[i]; + SWAP2BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint i; + const GLuint *s = (const GLuint *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLuint value = s[i]; + SWAP4BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_INT: + { + GLuint i; + const GLint *s = (const GLint *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLint value = s[i]; + SWAP4BYTE(value); + indexes[i] = value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i]; + } + } + break; + case GL_FLOAT: + { + GLuint i; + const GLfloat *s = (const GLfloat *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLfloat value = s[i]; + SWAP4BYTE(value); + indexes[i] = (GLuint) value; + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = (GLuint) s[i]; + } + } + break; + case GL_HALF_FLOAT_ARB: + { + GLuint i; + const GLhalfARB *s = (const GLhalfARB *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLhalfARB value = s[i]; + SWAP2BYTE(value); + indexes[i] = (GLuint) _mesa_half_to_float(value); + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = (GLuint) _mesa_half_to_float(s[i]); + } + } + break; + default: + _mesa_problem(NULL, "bad srcType in extract_uint_indexes"); + return; + } +} + + +/* + * This function extracts floating point RGBA values from arbitrary + * image data. srcFormat and srcType are the format and type parameters + * passed to glDrawPixels, glTexImage[123]D, glTexSubImage[123]D, etc. + * + * Refering to section 3.6.4 of the OpenGL 1.2 spec, this function + * implements the "Conversion to floating point", "Conversion to RGB", + * and "Final Expansion to RGBA" operations. + * + * Args: n - number of pixels + * rgba - output colors + * srcFormat - format of incoming data + * srcType - data type of incoming data + * src - source data pointer + * swapBytes - perform byteswapping of incoming data? + */ +static void +extract_float_rgba(GLuint n, GLfloat rgba[][4], + GLenum srcFormat, GLenum srcType, const GLvoid *src, + GLboolean swapBytes) +{ + GLint redIndex, greenIndex, blueIndex, alphaIndex; + GLint stride; + GLint rComp, bComp, gComp, aComp; + + ASSERT(srcFormat == GL_RED || + srcFormat == GL_GREEN || + srcFormat == GL_BLUE || + srcFormat == GL_ALPHA || + srcFormat == GL_LUMINANCE || + srcFormat == GL_LUMINANCE_ALPHA || + srcFormat == GL_INTENSITY || + srcFormat == GL_RGB || + srcFormat == GL_BGR || + srcFormat == GL_RGBA || + srcFormat == GL_BGRA || + srcFormat == GL_ABGR_EXT); + + ASSERT(srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_HALF_FLOAT_ARB || + srcType == GL_FLOAT || + srcType == GL_UNSIGNED_BYTE_3_3_2 || + srcType == GL_UNSIGNED_BYTE_2_3_3_REV || + srcType == GL_UNSIGNED_SHORT_5_6_5 || + srcType == GL_UNSIGNED_SHORT_5_6_5_REV || + srcType == GL_UNSIGNED_SHORT_4_4_4_4 || + srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV || + srcType == GL_UNSIGNED_SHORT_5_5_5_1 || + srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV || + srcType == GL_UNSIGNED_INT_10_10_10_2 || + srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + + rComp = gComp = bComp = aComp = -1; + + switch (srcFormat) { + case GL_RED: + redIndex = 0; + greenIndex = blueIndex = alphaIndex = -1; + stride = 1; + break; + case GL_GREEN: + greenIndex = 0; + redIndex = blueIndex = alphaIndex = -1; + stride = 1; + break; + case GL_BLUE: + blueIndex = 0; + redIndex = greenIndex = alphaIndex = -1; + stride = 1; + break; + case GL_ALPHA: + redIndex = greenIndex = blueIndex = -1; + alphaIndex = 0; + stride = 1; + break; + case GL_LUMINANCE: + redIndex = greenIndex = blueIndex = 0; + alphaIndex = -1; + stride = 1; + break; + case GL_LUMINANCE_ALPHA: + redIndex = greenIndex = blueIndex = 0; + alphaIndex = 1; + stride = 2; + break; + case GL_INTENSITY: + redIndex = greenIndex = blueIndex = alphaIndex = 0; + stride = 1; + break; + case GL_RGB: + redIndex = 0; + greenIndex = 1; + blueIndex = 2; + alphaIndex = -1; + rComp = 0; + gComp = 1; + bComp = 2; + aComp = 3; + stride = 3; + break; + case GL_BGR: + redIndex = 2; + greenIndex = 1; + blueIndex = 0; + alphaIndex = -1; + rComp = 2; + gComp = 1; + bComp = 0; + aComp = 3; + stride = 3; + break; + case GL_RGBA: + redIndex = 0; + greenIndex = 1; + blueIndex = 2; + alphaIndex = 3; + rComp = 0; + gComp = 1; + bComp = 2; + aComp = 3; + stride = 4; + break; + case GL_BGRA: + redIndex = 2; + greenIndex = 1; + blueIndex = 0; + alphaIndex = 3; + rComp = 2; + gComp = 1; + bComp = 0; + aComp = 3; + stride = 4; + break; + case GL_ABGR_EXT: + redIndex = 3; + greenIndex = 2; + blueIndex = 1; + alphaIndex = 0; + rComp = 3; + gComp = 2; + bComp = 1; + aComp = 0; + stride = 4; + break; + default: + _mesa_problem(NULL, "bad srcFormat in extract float data"); + return; + } + + +#define PROCESS(INDEX, CHANNEL, DEFAULT, TYPE, CONVERSION) \ + if ((INDEX) < 0) { \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + rgba[i][CHANNEL] = DEFAULT; \ + } \ + } \ + else if (swapBytes) { \ + const TYPE *s = (const TYPE *) src; \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + TYPE value = s[INDEX]; \ + if (sizeof(TYPE) == 2) { \ + SWAP2BYTE(value); \ + } \ + else if (sizeof(TYPE) == 4) { \ + SWAP4BYTE(value); \ + } \ + rgba[i][CHANNEL] = (GLfloat) CONVERSION(value); \ + s += stride; \ + } \ + } \ + else { \ + const TYPE *s = (const TYPE *) src; \ + GLuint i; \ + for (i = 0; i < n; i++) { \ + rgba[i][CHANNEL] = (GLfloat) CONVERSION(s[INDEX]); \ + s += stride; \ + } \ + } + + switch (srcType) { + case GL_UNSIGNED_BYTE: + PROCESS(redIndex, RCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLubyte, UBYTE_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLubyte, UBYTE_TO_FLOAT); + break; + case GL_BYTE: + PROCESS(redIndex, RCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLbyte, BYTE_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLbyte, BYTE_TO_FLOAT); + break; + case GL_UNSIGNED_SHORT: + PROCESS(redIndex, RCOMP, 0.0F, GLushort, USHORT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLushort, USHORT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLushort, USHORT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLushort, USHORT_TO_FLOAT); + break; + case GL_SHORT: + PROCESS(redIndex, RCOMP, 0.0F, GLshort, SHORT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLshort, SHORT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLshort, SHORT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLshort, SHORT_TO_FLOAT); + break; + case GL_UNSIGNED_INT: + PROCESS(redIndex, RCOMP, 0.0F, GLuint, UINT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLuint, UINT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLuint, UINT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLuint, UINT_TO_FLOAT); + break; + case GL_INT: + PROCESS(redIndex, RCOMP, 0.0F, GLint, INT_TO_FLOAT); + PROCESS(greenIndex, GCOMP, 0.0F, GLint, INT_TO_FLOAT); + PROCESS(blueIndex, BCOMP, 0.0F, GLint, INT_TO_FLOAT); + PROCESS(alphaIndex, ACOMP, 1.0F, GLint, INT_TO_FLOAT); + break; + case GL_FLOAT: + PROCESS(redIndex, RCOMP, 0.0F, GLfloat, (GLfloat)); + PROCESS(greenIndex, GCOMP, 0.0F, GLfloat, (GLfloat)); + PROCESS(blueIndex, BCOMP, 0.0F, GLfloat, (GLfloat)); + PROCESS(alphaIndex, ACOMP, 1.0F, GLfloat, (GLfloat)); + break; + case GL_HALF_FLOAT_ARB: + PROCESS(redIndex, RCOMP, 0.0F, GLhalfARB, _mesa_half_to_float); + PROCESS(greenIndex, GCOMP, 0.0F, GLhalfARB, _mesa_half_to_float); + PROCESS(blueIndex, BCOMP, 0.0F, GLhalfARB, _mesa_half_to_float); + PROCESS(alphaIndex, ACOMP, 1.0F, GLhalfARB, _mesa_half_to_float); + break; + case GL_UNSIGNED_BYTE_3_3_2: + { + const GLubyte *ubsrc = (const GLubyte *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLubyte p = ubsrc[i]; + rgba[i][rComp] = ((p >> 5) ) * (1.0F / 7.0F); + rgba[i][gComp] = ((p >> 2) & 0x7) * (1.0F / 7.0F); + rgba[i][bComp] = ((p ) & 0x3) * (1.0F / 3.0F); + rgba[i][aComp] = 1.0F; + } + } + break; + case GL_UNSIGNED_BYTE_2_3_3_REV: + { + const GLubyte *ubsrc = (const GLubyte *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLubyte p = ubsrc[i]; + rgba[i][rComp] = ((p ) & 0x7) * (1.0F / 7.0F); + rgba[i][gComp] = ((p >> 3) & 0x7) * (1.0F / 7.0F); + rgba[i][bComp] = ((p >> 6) ) * (1.0F / 3.0F); + rgba[i][aComp] = 1.0F; + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][bComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = 1.0F; + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][bComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = 1.0F; + } + } + break; + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][bComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][aComp] = 1.0F; + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x3f) * (1.0F / 63.0F); + rgba[i][bComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][aComp] = 1.0F; + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p >> 12) ) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p ) & 0xf) * (1.0F / 15.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p >> 12) ) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p ) & 0xf) * (1.0F / 15.0F); + } + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p ) & 0xf) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p >> 12) ) * (1.0F / 15.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p ) & 0xf) * (1.0F / 15.0F); + rgba[i][gComp] = ((p >> 4) & 0xf) * (1.0F / 15.0F); + rgba[i][bComp] = ((p >> 8) & 0xf) * (1.0F / 15.0F); + rgba[i][aComp] = ((p >> 12) ) * (1.0F / 15.0F); + } + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 6) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 1) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p ) & 0x1) * (1.0F / 1.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p >> 11) ) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 6) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 1) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p ) & 0x1) * (1.0F / 1.0F); + } + } + break; + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (swapBytes) { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + SWAP2BYTE(p); + rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 10) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p >> 15) ) * (1.0F / 1.0F); + } + } + else { + const GLushort *ussrc = (const GLushort *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLushort p = ussrc[i]; + rgba[i][rComp] = ((p ) & 0x1f) * (1.0F / 31.0F); + rgba[i][gComp] = ((p >> 5) & 0x1f) * (1.0F / 31.0F); + rgba[i][bComp] = ((p >> 10) & 0x1f) * (1.0F / 31.0F); + rgba[i][aComp] = ((p >> 15) ) * (1.0F / 1.0F); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_TO_FLOAT((p ) & 0xff); + rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff); + rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff); + rgba[i][aComp] = UBYTE_TO_FLOAT((p >> 24) ); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_TO_FLOAT((p >> 24) ); + rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff); + rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff); + rgba[i][aComp] = UBYTE_TO_FLOAT((p ) & 0xff); + } + } + break; + case GL_UNSIGNED_INT_8_8_8_8_REV: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_TO_FLOAT((p >> 24) ); + rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff); + rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff); + rgba[i][aComp] = UBYTE_TO_FLOAT((p ) & 0xff); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = UBYTE_TO_FLOAT((p ) & 0xff); + rgba[i][gComp] = UBYTE_TO_FLOAT((p >> 8) & 0xff); + rgba[i][bComp] = UBYTE_TO_FLOAT((p >> 16) & 0xff); + rgba[i][aComp] = UBYTE_TO_FLOAT((p >> 24) ); + } + } + break; + case GL_UNSIGNED_INT_10_10_10_2: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + SWAP4BYTE(p); + rgba[i][rComp] = ((p >> 22) ) * (1.0F / 1023.0F); + rgba[i][gComp] = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p ) & 0x3 ) * (1.0F / 3.0F); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = ((p >> 22) ) * (1.0F / 1023.0F); + rgba[i][gComp] = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p ) & 0x3 ) * (1.0F / 3.0F); + } + } + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + SWAP4BYTE(p); + rgba[i][rComp] = ((p ) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][gComp] = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p >> 30) ) * (1.0F / 3.0F); + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgba[i][rComp] = ((p ) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][gComp] = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][bComp] = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F); + rgba[i][aComp] = ((p >> 30) ) * (1.0F / 3.0F); + } + } + break; + default: + _mesa_problem(NULL, "bad srcType in extract float data"); + break; + } +} + + +/* + * Unpack a row of color image data from a client buffer according to + * the pixel unpacking parameters. + * Return GLchan values in the specified dest image format. + * This is used by glDrawPixels and glTexImage?D(). + * \param ctx - the context + * n - number of pixels in the span + * dstFormat - format of destination color array + * dest - the destination color array + * srcFormat - source image format + * srcType - source image data type + * source - source image pointer + * srcPacking - pixel unpacking parameters + * transferOps - bitmask of IMAGE_*_BIT values of operations to apply + * + * XXX perhaps expand this to process whole images someday. + */ +void +_mesa_unpack_color_span_chan( GLcontext *ctx, + GLuint n, GLenum dstFormat, GLchan dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ) +{ + ASSERT(dstFormat == GL_ALPHA || + dstFormat == GL_LUMINANCE || + dstFormat == GL_LUMINANCE_ALPHA || + dstFormat == GL_INTENSITY || + dstFormat == GL_RGB || + dstFormat == GL_RGBA || + dstFormat == GL_COLOR_INDEX); + + ASSERT(srcFormat == GL_RED || + srcFormat == GL_GREEN || + srcFormat == GL_BLUE || + srcFormat == GL_ALPHA || + srcFormat == GL_LUMINANCE || + srcFormat == GL_LUMINANCE_ALPHA || + srcFormat == GL_INTENSITY || + srcFormat == GL_RGB || + srcFormat == GL_BGR || + srcFormat == GL_RGBA || + srcFormat == GL_BGRA || + srcFormat == GL_ABGR_EXT || + srcFormat == GL_COLOR_INDEX); + + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_HALF_FLOAT_ARB || + srcType == GL_FLOAT || + srcType == GL_UNSIGNED_BYTE_3_3_2 || + srcType == GL_UNSIGNED_BYTE_2_3_3_REV || + srcType == GL_UNSIGNED_SHORT_5_6_5 || + srcType == GL_UNSIGNED_SHORT_5_6_5_REV || + srcType == GL_UNSIGNED_SHORT_4_4_4_4 || + srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV || + srcType == GL_UNSIGNED_SHORT_5_5_5_1 || + srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV || + srcType == GL_UNSIGNED_INT_10_10_10_2 || + srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + + /* Try simple cases first */ + if (transferOps == 0) { + if (srcType == CHAN_TYPE) { + if (dstFormat == GL_RGBA) { + if (srcFormat == GL_RGBA) { + MEMCPY( dest, source, n * 4 * sizeof(GLchan) ); + return; + } + else if (srcFormat == GL_RGB) { + GLuint i; + const GLchan *src = (const GLchan *) source; + GLchan *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = CHAN_MAX; + src += 3; + dst += 4; + } + return; + } + } + else if (dstFormat == GL_RGB) { + if (srcFormat == GL_RGB) { + MEMCPY( dest, source, n * 3 * sizeof(GLchan) ); + return; + } + else if (srcFormat == GL_RGBA) { + GLuint i; + const GLchan *src = (const GLchan *) source; + GLchan *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + src += 4; + dst += 3; + } + return; + } + } + else if (dstFormat == srcFormat) { + GLint comps = _mesa_components_in_format(srcFormat); + assert(comps > 0); + MEMCPY( dest, source, n * comps * sizeof(GLchan) ); + return; + } + } + /* + * Common situation, loading 8bit RGBA/RGB source images + * into 16/32 bit destination. (OSMesa16/32) + */ + else if (srcType == GL_UNSIGNED_BYTE) { + if (dstFormat == GL_RGBA) { + if (srcFormat == GL_RGB) { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + GLchan *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = UBYTE_TO_CHAN(src[0]); + dst[1] = UBYTE_TO_CHAN(src[1]); + dst[2] = UBYTE_TO_CHAN(src[2]); + dst[3] = CHAN_MAX; + src += 3; + dst += 4; + } + return; + } + else if (srcFormat == GL_RGBA) { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + GLchan *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = UBYTE_TO_CHAN(src[0]); + dst[1] = UBYTE_TO_CHAN(src[1]); + dst[2] = UBYTE_TO_CHAN(src[2]); + dst[3] = UBYTE_TO_CHAN(src[3]); + src += 4; + dst += 4; + } + return; + } + } + else if (dstFormat == GL_RGB) { + if (srcFormat == GL_RGB) { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + GLchan *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = UBYTE_TO_CHAN(src[0]); + dst[1] = UBYTE_TO_CHAN(src[1]); + dst[2] = UBYTE_TO_CHAN(src[2]); + src += 3; + dst += 3; + } + return; + } + else if (srcFormat == GL_RGBA) { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + GLchan *dst = dest; + for (i = 0; i < n; i++) { + dst[0] = UBYTE_TO_CHAN(src[0]); + dst[1] = UBYTE_TO_CHAN(src[1]); + dst[2] = UBYTE_TO_CHAN(src[2]); + src += 4; + dst += 3; + } + return; + } + } + } + } + + + /* general solution begins here */ + { + GLint dstComponents; + GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex; + GLint dstLuminanceIndex, dstIntensityIndex; + DEFMARRAY(GLfloat, rgba, MAX_WIDTH, 4); /* mac 32k limitation */ + CHECKARRAY(rgba, return); /* mac 32k limitation */ + + dstComponents = _mesa_components_in_format( dstFormat ); + /* source & dest image formats should have been error checked by now */ + assert(dstComponents > 0); + + /* + * Extract image data and convert to RGBA floats + */ + assert(n <= MAX_WIDTH); + if (srcFormat == GL_COLOR_INDEX) { + GLuint indexes[MAX_WIDTH]; + extract_uint_indexes(n, indexes, srcFormat, srcType, source, + srcPacking); + + if (dstFormat == GL_COLOR_INDEX + && (transferOps & IMAGE_MAP_COLOR_BIT)) { + _mesa_map_ci(ctx, n, indexes); + } + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + + if (dstFormat == GL_COLOR_INDEX) { + /* convert to GLchan and return */ + GLuint i; + for (i = 0; i < n; i++) { + dest[i] = (GLchan) (indexes[i] & 0xff); + } + UNDEFARRAY(rgba); /* mac 32k limitation */ + return; + } + else { + /* Convert indexes to RGBA */ + _mesa_map_ci_to_rgba(ctx, n, indexes, rgba); + } + + /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting + * with color indexes. + */ + transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT); + } + else { + /* non-color index data */ + extract_float_rgba(n, rgba, srcFormat, srcType, source, + srcPacking->SwapBytes); + } + + /* Need to clamp if returning GLubytes or GLushorts */ +#if CHAN_TYPE != GL_FLOAT + transferOps |= IMAGE_CLAMP_BIT; +#endif + + if (transferOps) { + _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgba); + } + + /* Now determine which color channels we need to produce. + * And determine the dest index (offset) within each color tuple. + */ + switch (dstFormat) { + case GL_ALPHA: + dstAlphaIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = -1; + dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_LUMINANCE: + dstLuminanceIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; + dstIntensityIndex = -1; + break; + case GL_LUMINANCE_ALPHA: + dstLuminanceIndex = 0; + dstAlphaIndex = 1; + dstRedIndex = dstGreenIndex = dstBlueIndex = -1; + dstIntensityIndex = -1; + break; + case GL_INTENSITY: + dstIntensityIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; + dstLuminanceIndex = -1; + break; + case GL_RGB: + dstRedIndex = 0; + dstGreenIndex = 1; + dstBlueIndex = 2; + dstAlphaIndex = dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_RGBA: + dstRedIndex = 0; + dstGreenIndex = 1; + dstBlueIndex = 2; + dstAlphaIndex = 3; + dstLuminanceIndex = dstIntensityIndex = -1; + break; + default: + _mesa_problem(ctx, "bad dstFormat in _mesa_unpack_chan_span()"); + UNDEFARRAY(rgba); /* mac 32k limitation */ + return; + } + + + /* Now return the GLchan data in the requested dstFormat */ + + if (dstRedIndex >= 0) { + GLchan *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + CLAMPED_FLOAT_TO_CHAN(dst[dstRedIndex], rgba[i][RCOMP]); + dst += dstComponents; + } + } + + if (dstGreenIndex >= 0) { + GLchan *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + CLAMPED_FLOAT_TO_CHAN(dst[dstGreenIndex], rgba[i][GCOMP]); + dst += dstComponents; + } + } + + if (dstBlueIndex >= 0) { + GLchan *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + CLAMPED_FLOAT_TO_CHAN(dst[dstBlueIndex], rgba[i][BCOMP]); + dst += dstComponents; + } + } + + if (dstAlphaIndex >= 0) { + GLchan *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + CLAMPED_FLOAT_TO_CHAN(dst[dstAlphaIndex], rgba[i][ACOMP]); + dst += dstComponents; + } + } + + if (dstIntensityIndex >= 0) { + GLchan *dst = dest; + GLuint i; + assert(dstIntensityIndex == 0); + assert(dstComponents == 1); + for (i = 0; i < n; i++) { + /* Intensity comes from red channel */ + CLAMPED_FLOAT_TO_CHAN(dst[i], rgba[i][RCOMP]); + } + } + + if (dstLuminanceIndex >= 0) { + GLchan *dst = dest; + GLuint i; + assert(dstLuminanceIndex == 0); + for (i = 0; i < n; i++) { + /* Luminance comes from red channel */ + CLAMPED_FLOAT_TO_CHAN(dst[0], rgba[i][RCOMP]); + dst += dstComponents; + } + } + UNDEFARRAY(rgba); /* mac 32k limitation */ + } +} + + +/** + * Same as _mesa_unpack_color_span_chan(), but return GLfloat data + * instead of GLchan. + */ +void +_mesa_unpack_color_span_float( GLcontext *ctx, + GLuint n, GLenum dstFormat, GLfloat dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ) +{ + ASSERT(dstFormat == GL_ALPHA || + dstFormat == GL_LUMINANCE || + dstFormat == GL_LUMINANCE_ALPHA || + dstFormat == GL_INTENSITY || + dstFormat == GL_RGB || + dstFormat == GL_RGBA || + dstFormat == GL_COLOR_INDEX); + + ASSERT(srcFormat == GL_RED || + srcFormat == GL_GREEN || + srcFormat == GL_BLUE || + srcFormat == GL_ALPHA || + srcFormat == GL_LUMINANCE || + srcFormat == GL_LUMINANCE_ALPHA || + srcFormat == GL_INTENSITY || + srcFormat == GL_RGB || + srcFormat == GL_BGR || + srcFormat == GL_RGBA || + srcFormat == GL_BGRA || + srcFormat == GL_ABGR_EXT || + srcFormat == GL_COLOR_INDEX); + + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_HALF_FLOAT_ARB || + srcType == GL_FLOAT || + srcType == GL_UNSIGNED_BYTE_3_3_2 || + srcType == GL_UNSIGNED_BYTE_2_3_3_REV || + srcType == GL_UNSIGNED_SHORT_5_6_5 || + srcType == GL_UNSIGNED_SHORT_5_6_5_REV || + srcType == GL_UNSIGNED_SHORT_4_4_4_4 || + srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV || + srcType == GL_UNSIGNED_SHORT_5_5_5_1 || + srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV || + srcType == GL_UNSIGNED_INT_8_8_8_8 || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV || + srcType == GL_UNSIGNED_INT_10_10_10_2 || + srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + + /* general solution, no special cases, yet */ + { + GLint dstComponents; + GLint dstRedIndex, dstGreenIndex, dstBlueIndex, dstAlphaIndex; + GLint dstLuminanceIndex, dstIntensityIndex; + DEFMARRAY(GLfloat, rgba, MAX_WIDTH, 4); /* mac 32k limitation */ + CHECKARRAY(rgba, return); /* mac 32k limitation */ + + dstComponents = _mesa_components_in_format( dstFormat ); + /* source & dest image formats should have been error checked by now */ + assert(dstComponents > 0); + + /* + * Extract image data and convert to RGBA floats + */ + assert(n <= MAX_WIDTH); + if (srcFormat == GL_COLOR_INDEX) { + GLuint indexes[MAX_WIDTH]; + extract_uint_indexes(n, indexes, srcFormat, srcType, source, + srcPacking); + + if (dstFormat == GL_COLOR_INDEX + && (transferOps & IMAGE_MAP_COLOR_BIT)) { + _mesa_map_ci(ctx, n, indexes); + } + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + + if (dstFormat == GL_COLOR_INDEX) { + /* convert to GLchan and return */ + GLuint i; + for (i = 0; i < n; i++) { + dest[i] = (GLchan) (indexes[i] & 0xff); + } + UNDEFARRAY(rgba); /* mac 32k limitation */ + return; + } + else { + /* Convert indexes to RGBA */ + _mesa_map_ci_to_rgba(ctx, n, indexes, rgba); + } + + /* Don't do RGBA scale/bias or RGBA->RGBA mapping if starting + * with color indexes. + */ + transferOps &= ~(IMAGE_SCALE_BIAS_BIT | IMAGE_MAP_COLOR_BIT); + } + else { + /* non-color index data */ + extract_float_rgba(n, rgba, srcFormat, srcType, source, + srcPacking->SwapBytes); + } + + if (transferOps) { + _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgba); + } + + /* Now determine which color channels we need to produce. + * And determine the dest index (offset) within each color tuple. + */ + switch (dstFormat) { + case GL_ALPHA: + dstAlphaIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = -1; + dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_LUMINANCE: + dstLuminanceIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; + dstIntensityIndex = -1; + break; + case GL_LUMINANCE_ALPHA: + dstLuminanceIndex = 0; + dstAlphaIndex = 1; + dstRedIndex = dstGreenIndex = dstBlueIndex = -1; + dstIntensityIndex = -1; + break; + case GL_INTENSITY: + dstIntensityIndex = 0; + dstRedIndex = dstGreenIndex = dstBlueIndex = dstAlphaIndex = -1; + dstLuminanceIndex = -1; + break; + case GL_RGB: + dstRedIndex = 0; + dstGreenIndex = 1; + dstBlueIndex = 2; + dstAlphaIndex = dstLuminanceIndex = dstIntensityIndex = -1; + break; + case GL_RGBA: + dstRedIndex = 0; + dstGreenIndex = 1; + dstBlueIndex = 2; + dstAlphaIndex = 3; + dstLuminanceIndex = dstIntensityIndex = -1; + break; + default: + _mesa_problem(ctx, "bad dstFormat in _mesa_unpack_color_span_float()"); + UNDEFARRAY(rgba); /* mac 32k limitation */ + return; + } + + /* Now pack results in the requested dstFormat */ + if (dstRedIndex >= 0) { + GLfloat *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstRedIndex] = rgba[i][RCOMP]; + dst += dstComponents; + } + } + + if (dstGreenIndex >= 0) { + GLfloat *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstGreenIndex] = rgba[i][GCOMP]; + dst += dstComponents; + } + } + + if (dstBlueIndex >= 0) { + GLfloat *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstBlueIndex] = rgba[i][BCOMP]; + dst += dstComponents; + } + } + + if (dstAlphaIndex >= 0) { + GLfloat *dst = dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[dstAlphaIndex] = rgba[i][ACOMP]; + dst += dstComponents; + } + } + + if (dstIntensityIndex >= 0) { + GLfloat *dst = dest; + GLuint i; + assert(dstIntensityIndex == 0); + assert(dstComponents == 1); + for (i = 0; i < n; i++) { + /* Intensity comes from red channel */ + dst[i] = rgba[i][RCOMP]; + } + } + + if (dstLuminanceIndex >= 0) { + GLfloat *dst = dest; + GLuint i; + assert(dstLuminanceIndex == 0); + for (i = 0; i < n; i++) { + /* Luminance comes from red channel */ + dst[0] = rgba[i][RCOMP]; + dst += dstComponents; + } + } + UNDEFARRAY(rgba); /* mac 32k limitation */ + } +} + + +/* + * Unpack a row of color index data from a client buffer according to + * the pixel unpacking parameters. + * This is (or will be) used by glDrawPixels, glTexImage[123]D, etc. + * + * Args: ctx - the context + * n - number of pixels + * dstType - destination data type + * dest - destination array + * srcType - source pixel type + * source - source data pointer + * srcPacking - pixel unpacking parameters + * transferOps - the pixel transfer operations to apply + */ +void +_mesa_unpack_index_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ) +{ + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_HALF_FLOAT_ARB || + srcType == GL_FLOAT); + + ASSERT(dstType == GL_UNSIGNED_BYTE || + dstType == GL_UNSIGNED_SHORT || + dstType == GL_UNSIGNED_INT); + + + transferOps &= (IMAGE_MAP_COLOR_BIT | IMAGE_SHIFT_OFFSET_BIT); + + /* + * Try simple cases first + */ + if (transferOps == 0 && srcType == GL_UNSIGNED_BYTE + && dstType == GL_UNSIGNED_BYTE) { + MEMCPY(dest, source, n * sizeof(GLubyte)); + } + else if (transferOps == 0 && srcType == GL_UNSIGNED_INT + && dstType == GL_UNSIGNED_INT && !srcPacking->SwapBytes) { + MEMCPY(dest, source, n * sizeof(GLuint)); + } + else { + /* + * general solution + */ + GLuint indexes[MAX_WIDTH]; + assert(n <= MAX_WIDTH); + + extract_uint_indexes(n, indexes, GL_COLOR_INDEX, srcType, source, + srcPacking); + + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + /* shift and offset indexes */ + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + if (transferOps & IMAGE_MAP_COLOR_BIT) { + /* Apply lookup table */ + _mesa_map_ci(ctx, n, indexes); + } + + /* convert to dest type */ + switch (dstType) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLubyte) (indexes[i] & 0xff); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLushort) (indexes[i] & 0xffff); + } + } + break; + case GL_UNSIGNED_INT: + MEMCPY(dest, indexes, n * sizeof(GLuint)); + break; + default: + _mesa_problem(ctx, "bad dstType in _mesa_unpack_index_span"); + } + } +} + + +void +_mesa_pack_index_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLuint *source, + const struct gl_pixelstore_attrib *dstPacking, + GLuint transferOps ) +{ + GLuint indexes[MAX_WIDTH]; + + ASSERT(n <= MAX_WIDTH); + + transferOps &= (IMAGE_MAP_COLOR_BIT | IMAGE_SHIFT_OFFSET_BIT); + + if (transferOps & (IMAGE_MAP_COLOR_BIT | IMAGE_SHIFT_OFFSET_BIT)) { + /* make a copy of input */ + MEMCPY(indexes, source, n * sizeof(GLuint)); + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + _mesa_shift_and_offset_ci( ctx, n, indexes); + } + if (transferOps & IMAGE_MAP_COLOR_BIT) { + _mesa_map_ci(ctx, n, indexes); + } + source = indexes; + } + + switch (dstType) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + *dst++ = (GLubyte) source[i]; + } + } + break; + case GL_BYTE: + { + GLbyte *dst = (GLbyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLbyte) source[i]; + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *dst = (GLushort *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLushort) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_SHORT: + { + GLshort *dst = (GLshort *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLshort) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLuint) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_INT: + { + GLint *dst = (GLint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLint) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_FLOAT: + { + GLfloat *dst = (GLfloat *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLfloat) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_HALF_FLOAT_ARB: + { + GLhalfARB *dst = (GLhalfARB *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = _mesa_float_to_half((GLfloat) source[i]); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + default: + _mesa_problem(ctx, "bad type in _mesa_pack_index_span"); + } +} + + +/* + * Unpack a row of stencil data from a client buffer according to + * the pixel unpacking parameters. + * This is (or will be) used by glDrawPixels + * + * Args: ctx - the context + * n - number of pixels + * dstType - destination data type + * dest - destination array + * srcType - source pixel type + * source - source data pointer + * srcPacking - pixel unpacking parameters + * transferOps - apply offset/bias/lookup ops? + */ +void +_mesa_unpack_stencil_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ) +{ + ASSERT(srcType == GL_BITMAP || + srcType == GL_UNSIGNED_BYTE || + srcType == GL_BYTE || + srcType == GL_UNSIGNED_SHORT || + srcType == GL_SHORT || + srcType == GL_UNSIGNED_INT || + srcType == GL_INT || + srcType == GL_HALF_FLOAT_ARB || + srcType == GL_FLOAT); + + ASSERT(dstType == GL_UNSIGNED_BYTE || + dstType == GL_UNSIGNED_SHORT || + dstType == GL_UNSIGNED_INT); + + /* only shift and offset apply to stencil */ + transferOps &= IMAGE_SHIFT_OFFSET_BIT; + + /* + * Try simple cases first + */ + if (transferOps == 0 && + srcType == GL_UNSIGNED_BYTE && + dstType == GL_UNSIGNED_BYTE) { + MEMCPY(dest, source, n * sizeof(GLubyte)); + } + else if (transferOps == 0 && + srcType == GL_UNSIGNED_INT && + dstType == GL_UNSIGNED_INT && + !srcPacking->SwapBytes) { + MEMCPY(dest, source, n * sizeof(GLuint)); + } + else { + /* + * general solution + */ + GLuint indexes[MAX_WIDTH]; + assert(n <= MAX_WIDTH); + + extract_uint_indexes(n, indexes, GL_COLOR_INDEX, srcType, source, + srcPacking); + + if (transferOps) { + if (transferOps & IMAGE_SHIFT_OFFSET_BIT) { + /* shift and offset indexes */ + _mesa_shift_and_offset_ci(ctx, n, indexes); + } + + if (ctx->Pixel.MapStencilFlag) { + /* Apply stencil lookup table */ + GLuint mask = ctx->Pixel.MapStoSsize - 1; + GLuint i; + for (i=0;i<n;i++) { + indexes[i] = ctx->Pixel.MapStoS[ indexes[i] & mask ]; + } + } + } + + /* convert to dest type */ + switch (dstType) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLubyte) (indexes[i] & 0xff); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = (GLushort) (indexes[i] & 0xffff); + } + } + break; + case GL_UNSIGNED_INT: + MEMCPY(dest, indexes, n * sizeof(GLuint)); + break; + default: + _mesa_problem(ctx, "bad dstType in _mesa_unpack_stencil_span"); + } + } +} + + +void +_mesa_pack_stencil_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLstencil *source, + const struct gl_pixelstore_attrib *dstPacking ) +{ + GLstencil stencil[MAX_WIDTH]; + + ASSERT(n <= MAX_WIDTH); + + if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || + ctx->Pixel.MapStencilFlag) { + /* make a copy of input */ + MEMCPY(stencil, source, n * sizeof(GLstencil)); + if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) { + _mesa_shift_and_offset_stencil( ctx, n, stencil ); + } + if (ctx->Pixel.MapStencilFlag) { + _mesa_map_stencil( ctx, n, stencil ); + } + source = stencil; + } + + switch (dstType) { + case GL_UNSIGNED_BYTE: + if (sizeof(GLstencil) == 8) { + MEMCPY( dest, source, n ); + } + else { + GLubyte *dst = (GLubyte *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = (GLubyte) source[i]; + } + } + break; + case GL_BYTE: + if (sizeof(GLstencil) == 8) { + MEMCPY( dest, source, n ); + } + else { + GLbyte *dst = (GLbyte *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = (GLbyte) source[i]; + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *dst = (GLushort *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = (GLushort) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_SHORT: + { + GLshort *dst = (GLshort *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = (GLshort) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = (GLuint) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_INT: + { + GLint *dst = (GLint *) dest; + GLuint i; + for (i=0;i<n;i++) { + *dst++ = (GLint) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_FLOAT: + { + GLfloat *dst = (GLfloat *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = (GLfloat) source[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_HALF_FLOAT_ARB: + { + GLhalfARB *dst = (GLhalfARB *) dest; + GLuint i; + for (i=0;i<n;i++) { + dst[i] = _mesa_float_to_half( (float) source[i] ); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_BITMAP: + if (dstPacking->LsbFirst) { + GLubyte *dst = (GLubyte *) dest; + GLint shift = 0; + GLuint i; + for (i = 0; i < n; i++) { + if (shift == 0) + *dst = 0; + *dst |= ((source[i] != 0) << shift); + shift++; + if (shift == 8) { + shift = 0; + dst++; + } + } + } + else { + GLubyte *dst = (GLubyte *) dest; + GLint shift = 7; + GLuint i; + for (i = 0; i < n; i++) { + if (shift == 7) + *dst = 0; + *dst |= ((source[i] != 0) << shift); + shift--; + if (shift < 0) { + shift = 7; + dst++; + } + } + } + break; + default: + _mesa_problem(ctx, "bad type in _mesa_pack_index_span"); + } +} + + +void +_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n, GLfloat *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking ) +{ + (void) srcPacking; + + switch (srcType) { + case GL_BYTE: + { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + for (i = 0; i < n; i++) { + dest[i] = BYTE_TO_FLOAT(src[i]); + } + } + break; + case GL_UNSIGNED_BYTE: + { + GLuint i; + const GLubyte *src = (const GLubyte *) source; + for (i = 0; i < n; i++) { + dest[i] = UBYTE_TO_FLOAT(src[i]); + } + } + break; + case GL_SHORT: + { + GLuint i; + const GLshort *src = (const GLshort *) source; + for (i = 0; i < n; i++) { + dest[i] = SHORT_TO_FLOAT(src[i]); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLuint i; + const GLushort *src = (const GLushort *) source; + for (i = 0; i < n; i++) { + dest[i] = USHORT_TO_FLOAT(src[i]); + } + } + break; + case GL_INT: + { + GLuint i; + const GLint *src = (const GLint *) source; + for (i = 0; i < n; i++) { + dest[i] = INT_TO_FLOAT(src[i]); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint i; + const GLuint *src = (const GLuint *) source; + for (i = 0; i < n; i++) { + dest[i] = UINT_TO_FLOAT(src[i]); + } + } + break; + case GL_FLOAT: + MEMCPY(dest, source, n * sizeof(GLfloat)); + break; + case GL_HALF_FLOAT_ARB: + { + GLuint i; + const GLhalfARB *src = (const GLhalfARB *) source; + for (i = 0; i < n; i++) { + dest[i] = _mesa_half_to_float(src[i]); + } + } + break; + default: + _mesa_problem(NULL, "bad type in _mesa_unpack_depth_span()"); + return; + } + + + /* apply depth scale and bias and clamp to [0,1] */ + if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + GLfloat d = dest[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; + dest[i] = CLAMP(d, 0.0F, 1.0F); + } + } +} + + +/* + * Pack an array of depth values. The values are floats in [0,1]. + */ +void +_mesa_pack_depth_span( const GLcontext *ctx, GLuint n, GLvoid *dest, + GLenum dstType, const GLfloat *depthSpan, + const struct gl_pixelstore_attrib *dstPacking ) +{ + GLfloat depthCopy[MAX_WIDTH]; + const GLboolean bias_or_scale = ctx->Pixel.DepthBias != 0.0 || + ctx->Pixel.DepthScale != 1.0; + + ASSERT(n <= MAX_WIDTH); + + if (bias_or_scale) { + GLuint i; + for (i = 0; i < n; i++) { + GLfloat d; + d = depthSpan[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias; + depthCopy[i] = CLAMP(d, 0.0F, 1.0F); + } + depthSpan = depthCopy; + } + + switch (dstType) { + case GL_UNSIGNED_BYTE: + { + GLubyte *dst = (GLubyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = FLOAT_TO_UBYTE( depthSpan[i] ); + } + } + break; + case GL_BYTE: + { + GLbyte *dst = (GLbyte *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = FLOAT_TO_BYTE( depthSpan[i] ); + } + } + break; + case GL_UNSIGNED_SHORT: + { + GLushort *dst = (GLushort *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = FLOAT_TO_USHORT( depthSpan[i] ); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_SHORT: + { + GLshort *dst = (GLshort *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = FLOAT_TO_SHORT( depthSpan[i] ); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + case GL_UNSIGNED_INT: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = FLOAT_TO_UINT( depthSpan[i] ); + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_INT: + { + GLint *dst = (GLint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = FLOAT_TO_INT( depthSpan[i] ); + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_FLOAT: + { + GLfloat *dst = (GLfloat *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = depthSpan[i]; + } + if (dstPacking->SwapBytes) { + _mesa_swap4( (GLuint *) dst, n ); + } + } + break; + case GL_HALF_FLOAT_ARB: + { + GLhalfARB *dst = (GLhalfARB *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i] = _mesa_float_to_half(depthSpan[i]); + } + if (dstPacking->SwapBytes) { + _mesa_swap2( (GLushort *) dst, n ); + } + } + break; + default: + _mesa_problem(ctx, "bad type in _mesa_pack_depth_span"); + } +} + + +/** + * Unpack image data. Apply byte swapping, byte flipping (bitmap). + * Return all image data in a contiguous block. This is used when we + * compile glDrawPixels, glTexImage, etc into a display list. We + * need a copy of the data in a standard format. + */ +void * +_mesa_unpack_image( GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack ) +{ + GLint bytesPerRow, compsPerRow; + GLboolean flipBytes, swap2, swap4; + + if (!pixels) + return NULL; /* not necessarily an error */ + + if (width <= 0 || height <= 0 || depth <= 0) + return NULL; /* generate error later */ + + if (format == GL_BITMAP) { + bytesPerRow = (width + 7) >> 3; + flipBytes = !unpack->LsbFirst; + swap2 = swap4 = GL_FALSE; + compsPerRow = 0; + } + else { + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + const GLint components = _mesa_components_in_format(format); + GLint bytesPerComp; + if (bytesPerPixel <= 0 || components <= 0) + return NULL; /* bad format or type. generate error later */ + bytesPerRow = bytesPerPixel * width; + bytesPerComp = bytesPerPixel / components; + flipBytes = GL_FALSE; + swap2 = (bytesPerComp == 2) && unpack->SwapBytes; + swap4 = (bytesPerComp == 4) && unpack->SwapBytes; + compsPerRow = components * width; + assert(compsPerRow >= width); + } + + { + GLubyte *destBuffer = (GLubyte *) MALLOC(bytesPerRow * height * depth); + GLubyte *dst; + GLint img, row; + if (!destBuffer) + return NULL; /* generate GL_OUT_OF_MEMORY later */ + + dst = destBuffer; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + const GLvoid *src = _mesa_image_address(dimensions, unpack, pixels, + width, height, format, type, img, row, 0); + MEMCPY(dst, src, bytesPerRow); + /* byte flipping/swapping */ + if (flipBytes) { + flip_bytes((GLubyte *) dst, bytesPerRow); + } + else if (swap2) { + _mesa_swap2((GLushort*) dst, compsPerRow); + } + else if (swap4) { + _mesa_swap4((GLuint*) dst, compsPerRow); + } + dst += bytesPerRow; + } + } + return destBuffer; + } +} + +#endif + + +/** + * Perform clipping for glDrawPixels. The image's window position + * and size, and the unpack skipPixels and skipRows are adjusted so + * that the image region is entirely within the window and scissor bounds. + * NOTE: this will only work when glPixelZoom is (1, 1). + * + * \return GL_TRUE if image is ready for drawing or + * GL_FALSE if image was completely clipped away (draw nothing) + */ +GLboolean +_mesa_clip_drawpixels(const GLcontext *ctx, + GLint *destX, GLint *destY, + GLsizei *width, GLsizei *height, + GLint *skipPixels, GLint *skipRows) +{ + const GLframebuffer *buffer = ctx->DrawBuffer; + + ASSERT(ctx->Pixel.ZoomX == 1.0F && ctx->Pixel.ZoomY == 1.0F); + + /* left clipping */ + if (*destX < buffer->_Xmin) { + *skipPixels += (buffer->_Xmin - *destX); + *width -= (buffer->_Xmin - *destX); + *destX = buffer->_Xmin; + } + /* right clipping */ + if (*destX + *width > buffer->_Xmax) + *width -= (*destX + *width - buffer->_Xmax); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*destY < buffer->_Ymin) { + *skipRows += (buffer->_Ymin - *destY); + *height -= (buffer->_Ymin - *destY); + *destY = buffer->_Ymin; + } + /* top clipping */ + if (*destY + *height > buffer->_Ymax) + *height -= (*destY + *height - buffer->_Ymax); + + if (*height <= 0) + return GL_TRUE; + + return GL_TRUE; +} + + +/** + * Perform clipping for glReadPixels. The image's window position + * and size, and the pack skipPixels and skipRows are adjusted so + * that the image region is entirely within the window bounds. + * Note: this is different from _mesa_clip_drawpixels() in that the + * scissor box is ignored, and we use the bounds of the current "read" + * surface; + * + * \return GL_TRUE if image is ready for drawing or + * GL_FALSE if image was completely clipped away (draw nothing) + */ +GLboolean +_mesa_clip_readpixels(const GLcontext *ctx, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height, + GLint *skipPixels, GLint *skipRows) +{ + const GLframebuffer *buffer = ctx->ReadBuffer; + + /* left clipping */ + if (*srcX < 0) { + *skipPixels += (0 - *srcX); + *width -= (0 - *srcX); + *srcX = 0; + } + /* right clipping */ + if (*srcX + *width > (GLsizei) buffer->Width) + *width -= (*srcX + *width - buffer->Width); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*srcY < 0) { + *skipRows += (0 - *srcY); + *height -= (0 - *srcY); + *srcY = 0; + } + /* top clipping */ + if (*srcY + *height > (GLsizei) buffer->Height) + *height -= (*srcY + *height - buffer->Height); + + if (*height <= 0) + return GL_TRUE; + + return GL_TRUE; +} + diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h new file mode 100644 index 00000000000..6b76fd8af06 --- /dev/null +++ b/src/mesa/main/image.h @@ -0,0 +1,217 @@ +/** + * \file image.h + * Image handling. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef IMAGE_H +#define IMAGE_H + + +#include "mtypes.h" + + +extern void +_mesa_swap2( GLushort *p, GLuint n ); + +extern void +_mesa_swap4( GLuint *p, GLuint n ); + +extern GLint +_mesa_sizeof_type( GLenum type ); + +extern GLint +_mesa_sizeof_packed_type( GLenum type ); + +extern GLint +_mesa_components_in_format( GLenum format ); + +extern GLint +_mesa_bytes_per_pixel( GLenum format, GLenum type ); + +extern GLboolean +_mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type ); + + +extern GLvoid * +_mesa_image_address( GLuint dimensions, + const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ); + +extern GLvoid * +_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, + GLenum format, GLenum type, + GLint column ); + +extern GLvoid * +_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint row, GLint column ); + +extern GLvoid * +_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ); + + +extern GLint +_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLenum format, GLenum type ); + + +extern GLint +_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLint height, + GLenum format, GLenum type ); + +extern void +_mesa_unpack_polygon_stipple( const GLubyte *pattern, GLuint dest[32], + const struct gl_pixelstore_attrib *unpacking ); + + +extern void +_mesa_pack_polygon_stipple( const GLuint pattern[32], GLubyte *dest, + const struct gl_pixelstore_attrib *packing ); + + +extern GLvoid * +_mesa_unpack_bitmap( GLint width, GLint height, const GLubyte *pixels, + const struct gl_pixelstore_attrib *packing ); + +extern void +_mesa_pack_bitmap( GLint width, GLint height, const GLubyte *source, + GLubyte *dest, const struct gl_pixelstore_attrib *packing ); + + +extern void +_mesa_apply_rgba_transfer_ops(GLcontext *ctx, GLuint transferOps, + GLuint n, GLfloat rgba[][4]); + +extern void +_mesa_pack_rgba_span_float( GLcontext *ctx, + GLuint n, CONST GLfloat rgba[][4], + GLenum dstFormat, GLenum dstType, GLvoid *dstAddr, + const struct gl_pixelstore_attrib *dstPacking, + GLuint transferOps ); + + +extern void +_mesa_pack_rgba_span_chan( GLcontext *ctx, + GLuint n, CONST GLchan rgba[][4], + GLenum dstFormat, GLenum dstType, GLvoid *dstAddr, + const struct gl_pixelstore_attrib *dstPacking, + GLuint transferOps ); + + +extern void +_mesa_unpack_color_span_chan( GLcontext *ctx, + GLuint n, GLenum dstFormat, GLchan dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ); + + +extern void +_mesa_unpack_color_span_float( GLcontext *ctx, + GLuint n, GLenum dstFormat, GLfloat dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ); + + +extern void +_mesa_unpack_index_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ); + + +extern void +_mesa_pack_index_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLuint *source, + const struct gl_pixelstore_attrib *dstPacking, + GLuint transferOps ); + + +extern void +_mesa_unpack_stencil_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLuint transferOps ); + +extern void +_mesa_pack_stencil_span( const GLcontext *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLstencil *source, + const struct gl_pixelstore_attrib *dstPacking ); + + +extern void +_mesa_unpack_depth_span( const GLcontext *ctx, GLuint n, GLfloat *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking ); + +extern void +_mesa_pack_depth_span( const GLcontext *ctx, GLuint n, GLvoid *dest, + GLenum dstType, const GLfloat *depthSpan, + const struct gl_pixelstore_attrib *dstPacking ); + + +extern void * +_mesa_unpack_image( GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack ); + + +extern GLboolean +_mesa_clip_drawpixels(const GLcontext *ctx, + GLint *destX, GLint *destY, + GLsizei *width, GLsizei *height, + GLint *skipPixels, GLint *skipRows); + + +extern GLboolean +_mesa_clip_readpixels(const GLcontext *ctx, + GLint *destX, GLint *destY, + GLsizei *width, GLsizei *height, + GLint *skipPixels, GLint *skipRows); + + +#endif diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c new file mode 100644 index 00000000000..fec0d338448 --- /dev/null +++ b/src/mesa/main/imports.c @@ -0,0 +1,1200 @@ +/** + * \file imports.c + * Standard C library function wrappers. + * + * Imports are services which the device driver or window system or + * operating system provides to the core renderer. The core renderer (Mesa) + * will call these functions in order to do memory allocation, simple I/O, + * etc. + * + * Some drivers will want to override/replace this file with something + * specialized, but that'll be rare. + * + * Eventually, I want to move roll the glheader.h file into this. + * + * The OpenGL SI's __GLimports structure allows per-context specification of + * replacements for the standard C lib functions. In practice that's probably + * never needed; compile-time replacements are far more likely. + * + * The _mesa_*() functions defined here don't in general take a context + * parameter. I guess we can change that someday, if need be. + * So for now, the __GLimports stuff really isn't used. + * + * \todo Functions still needed: + * - scanf + * - qsort + * - bsearch + * - rand and RAND_MAX + * + * \note When compiled into a XFree86 module these functions wrap around + * XFree86 own wrappers. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#include "imports.h" +#include "context.h" +#include "version.h" + + +#define MAXSTRING 4000 /* for vsnprintf() */ + +#ifdef WIN32 +#define vsnprintf _vsnprintf +#elif defined(__IBMC__) || defined(__IBMCPP__) || ( defined(__VMS) && __CRTL_VER < 70312000 ) +extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg); +#ifdef __VMS +#include "vsnprintf.c" +#endif +#endif + + +/**********************************************************************/ +/** \name Memory */ +/*@{*/ + +/** Wrapper around either malloc() or xf86malloc() */ +void * +_mesa_malloc(size_t bytes) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86malloc(bytes); +#else + return malloc(bytes); +#endif +} + +/** Wrapper around either calloc() or xf86calloc() */ +void * +_mesa_calloc(size_t bytes) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86calloc(1, bytes); +#else + return calloc(1, bytes); +#endif +} + +/** Wrapper around either free() or xf86free() */ +void +_mesa_free(void *ptr) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86free(ptr); +#else + free(ptr); +#endif +} + +/** + * Allocate aligned memory. + * + * \param bytes number of bytes to allocate. + * \param alignment alignment (must be greater than zero). + * + * Allocates extra memory to accommodate rounding up the address for + * alignment and to record the real malloc address. + * + * \sa _mesa_align_free(). + */ +void * +_mesa_align_malloc(size_t bytes, unsigned long alignment) +{ + uintptr_t ptr, buf; + + ASSERT( alignment > 0 ); + + ptr = (uintptr_t) _mesa_malloc(bytes + alignment + sizeof(void *)); + if (!ptr) + return NULL; + + buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); + *(uintptr_t *)(buf - sizeof(void *)) = ptr; + +#ifdef DEBUG + /* mark the non-aligned area */ + while ( ptr < buf - sizeof(void *) ) { + *(unsigned long *)ptr = 0xcdcdcdcd; + ptr += sizeof(unsigned long); + } +#endif + + return (void *) buf; +} + +/** + * Same as _mesa_align_malloc(), but using _mesa_calloc() instead of + * _mesa_malloc() + */ +void * +_mesa_align_calloc(size_t bytes, unsigned long alignment) +{ + uintptr_t ptr, buf; + + ASSERT( alignment > 0 ); + + ptr = (uintptr_t) _mesa_calloc(bytes + alignment + sizeof(void *)); + if (!ptr) + return NULL; + + buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); + *(uintptr_t *)(buf - sizeof(void *)) = ptr; + +#ifdef DEBUG + /* mark the non-aligned area */ + while ( ptr < buf - sizeof(void *) ) { + *(unsigned long *)ptr = 0xcdcdcdcd; + ptr += sizeof(unsigned long); + } +#endif + + return (void *)buf; +} + +/** + * Free memory which was allocated with either _mesa_align_malloc() + * or _mesa_align_calloc(). + * \param ptr pointer to the memory to be freed. + * The actual address to free is stored in the word immediately before the + * address the client sees. + */ +void +_mesa_align_free(void *ptr) +{ +#if 0 + _mesa_free( (void *)(*(unsigned long *)((unsigned long)ptr - sizeof(void *))) ); +#else + void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); + void *realAddr = *cubbyHole; + _mesa_free(realAddr); +#endif +} + +/** Reallocate memory */ +void * +_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize) +{ + const size_t copySize = (oldSize < newSize) ? oldSize : newSize; + void *newBuffer = _mesa_malloc(newSize); + if (newBuffer && oldBuffer && copySize > 0) + _mesa_memcpy(newBuffer, oldBuffer, copySize); + if (oldBuffer) + _mesa_free(oldBuffer); + return newBuffer; +} + +/** memcpy wrapper */ +void * +_mesa_memcpy(void *dest, const void *src, size_t n) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86memcpy(dest, src, n); +#elif defined(SUNOS4) + return memcpy((char *) dest, (char *) src, (int) n); +#else + return memcpy(dest, src, n); +#endif +} + +/** Wrapper around either memset() or xf86memset() */ +void +_mesa_memset( void *dst, int val, size_t n ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86memset( dst, val, n ); +#elif defined(SUNOS4) + memset( (char *) dst, (int) val, (int) n ); +#else + memset(dst, val, n); +#endif +} + +/** + * Fill memory with a constant 16bit word. + * \param dst destination pointer. + * \param val value. + * \param n number of words. + */ +void +_mesa_memset16( unsigned short *dst, unsigned short val, size_t n ) +{ + while (n-- > 0) + *dst++ = val; +} + +/** Wrapper around either memcpy() or xf86memcpy() or bzero() */ +void +_mesa_bzero( void *dst, size_t n ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86memset( dst, 0, n ); +#elif defined(__FreeBSD__) + bzero( dst, n ); +#else + memset( dst, 0, n ); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Math */ +/*@{*/ + +/** Wrapper around either sin() or xf86sin() */ +double +_mesa_sin(double a) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86sin(a); +#else + return sin(a); +#endif +} + +/** Wrapper around either cos() or xf86cos() */ +double +_mesa_cos(double a) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86cos(a); +#else + return cos(a); +#endif +} + +/** Wrapper around either sqrt() or xf86sqrt() */ +double +_mesa_sqrtd(double x) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86sqrt(x); +#else + return sqrt(x); +#endif +} + + +/* + * A High Speed, Low Precision Square Root + * by Paul Lalonde and Robert Dawson + * from "Graphics Gems", Academic Press, 1990 + * + * SPARC implementation of a fast square root by table + * lookup. + * SPARC floating point format is as follows: + * + * BIT 31 30 23 22 0 + * sign exponent mantissa + */ +static short sqrttab[0x100]; /* declare table of square roots */ + +static void init_sqrt_table(void) +{ +#if defined(USE_IEEE) && !defined(DEBUG) + unsigned short i; + fi_type fi; /* to access the bits of a float in C quickly */ + /* we use a union defined in glheader.h */ + + for(i=0; i<= 0x7f; i++) { + fi.i = 0; + + /* + * Build a float with the bit pattern i as mantissa + * and an exponent of 0, stored as 127 + */ + + fi.i = (i << 16) | (127 << 23); + fi.f = _mesa_sqrtd(fi.f); + + /* + * Take the square root then strip the first 7 bits of + * the mantissa into the table + */ + + sqrttab[i] = (fi.i & 0x7fffff) >> 16; + + /* + * Repeat the process, this time with an exponent of + * 1, stored as 128 + */ + + fi.i = 0; + fi.i = (i << 16) | (128 << 23); + fi.f = sqrt(fi.f); + sqrttab[i+0x80] = (fi.i & 0x7fffff) >> 16; + } +#else + (void) sqrttab; /* silence compiler warnings */ +#endif /*HAVE_FAST_MATH*/ +} + + +/** + * Single precision square root. + */ +float +_mesa_sqrtf( float x ) +{ +#if defined(USE_IEEE) && !defined(DEBUG) + fi_type num; + /* to access the bits of a float in C + * we use a union from glheader.h */ + + short e; /* the exponent */ + if (x == 0.0F) return 0.0F; /* check for square root of 0 */ + num.f = x; + e = (num.i >> 23) - 127; /* get the exponent - on a SPARC the */ + /* exponent is stored with 127 added */ + num.i &= 0x7fffff; /* leave only the mantissa */ + if (e & 0x01) num.i |= 0x800000; + /* the exponent is odd so we have to */ + /* look it up in the second half of */ + /* the lookup table, so we set the */ + /* high bit */ + e >>= 1; /* divide the exponent by two */ + /* note that in C the shift */ + /* operators are sign preserving */ + /* for signed operands */ + /* Do the table lookup, based on the quaternary mantissa, + * then reconstruct the result back into a float + */ + num.i = ((sqrttab[num.i >> 16]) << 16) | ((e + 127) << 23); + + return num.f; +#else + return (float) _mesa_sqrtd((double) x); +#endif +} + + +/** + inv_sqrt - A single precision 1/sqrt routine for IEEE format floats. + written by Josh Vanderhoof, based on newsgroup posts by James Van Buskirk + and Vesa Karvonen. +*/ +float +_mesa_inv_sqrtf(float n) +{ +#if defined(USE_IEEE) && !defined(DEBUG) + float r0, x0, y0; + float r1, x1, y1; + float r2, x2, y2; +#if 0 /* not used, see below -BP */ + float r3, x3, y3; +#endif + union { float f; unsigned int i; } u; + unsigned int magic; + + /* + Exponent part of the magic number - + + We want to: + 1. subtract the bias from the exponent, + 2. negate it + 3. divide by two (rounding towards -inf) + 4. add the bias back + + Which is the same as subtracting the exponent from 381 and dividing + by 2. + + floor(-(x - 127) / 2) + 127 = floor((381 - x) / 2) + */ + + magic = 381 << 23; + + /* + Significand part of magic number - + + With the current magic number, "(magic - u.i) >> 1" will give you: + + for 1 <= u.f <= 2: 1.25 - u.f / 4 + for 2 <= u.f <= 4: 1.00 - u.f / 8 + + This isn't a bad approximation of 1/sqrt. The maximum difference from + 1/sqrt will be around .06. After three Newton-Raphson iterations, the + maximum difference is less than 4.5e-8. (Which is actually close + enough to make the following bias academic...) + + To get a better approximation you can add a bias to the magic + number. For example, if you subtract 1/2 of the maximum difference in + the first approximation (.03), you will get the following function: + + for 1 <= u.f <= 2: 1.22 - u.f / 4 + for 2 <= u.f <= 3.76: 0.97 - u.f / 8 + for 3.76 <= u.f <= 4: 0.72 - u.f / 16 + (The 3.76 to 4 range is where the result is < .5.) + + This is the closest possible initial approximation, but with a maximum + error of 8e-11 after three NR iterations, it is still not perfect. If + you subtract 0.0332281 instead of .03, the maximum error will be + 2.5e-11 after three NR iterations, which should be about as close as + is possible. + + for 1 <= u.f <= 2: 1.2167719 - u.f / 4 + for 2 <= u.f <= 3.73: 0.9667719 - u.f / 8 + for 3.73 <= u.f <= 4: 0.7167719 - u.f / 16 + + */ + + magic -= (int)(0.0332281 * (1 << 25)); + + u.f = n; + u.i = (magic - u.i) >> 1; + + /* + Instead of Newton-Raphson, we use Goldschmidt's algorithm, which + allows more parallelism. From what I understand, the parallelism + comes at the cost of less precision, because it lets error + accumulate across iterations. + */ + x0 = 1.0f; + y0 = 0.5f * n; + r0 = u.f; + + x1 = x0 * r0; + y1 = y0 * r0 * r0; + r1 = 1.5f - y1; + + x2 = x1 * r1; + y2 = y1 * r1 * r1; + r2 = 1.5f - y2; + +#if 1 + return x2 * r2; /* we can stop here, and be conformant -BP */ +#else + x3 = x2 * r2; + y3 = y2 * r2 * r2; + r3 = 1.5f - y3; + + return x3 * r3; +#endif +#elif defined(XFree86LOADER) && defined(IN_MODULE) + return 1.0F / xf86sqrt(n); +#else + return (float) (1.0 / sqrt(n)); +#endif +} + + +/** + * Wrapper around either pow() or xf86pow(). + */ +double +_mesa_pow(double x, double y) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86pow(x, y); +#else + return pow(x, y); +#endif +} + + +/** + * Return number of bits set in given GLuint. + */ +unsigned int +_mesa_bitcount(unsigned int n) +{ + unsigned int bits; + for (bits = 0; n > 0; n = n >> 1) { + bits += (n & 1); + } + return bits; +} + + +/** + * Convert a 4-byte float to a 2-byte half float. + * Based on code from: + * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html + */ +GLhalfARB +_mesa_float_to_half(float val) +{ + const int flt = *((int *) (void *) &val); + const int flt_m = flt & 0x7fffff; + const int flt_e = (flt >> 23) & 0xff; + const int flt_s = (flt >> 31) & 0x1; + int s, e, m = 0; + GLhalfARB result; + + /* sign bit */ + s = flt_s; + + /* handle special cases */ + if ((flt_e == 0) && (flt_m == 0)) { + /* zero */ + /* m = 0; - already set */ + e = 0; + } + else if ((flt_e == 0) && (flt_m != 0)) { + /* denorm -- denorm float maps to 0 half */ + /* m = 0; - already set */ + e = 0; + } + else if ((flt_e == 0xff) && (flt_m == 0)) { + /* infinity */ + /* m = 0; - already set */ + e = 31; + } + else if ((flt_e == 0xff) && (flt_m != 0)) { + /* NaN */ + m = 1; + e = 31; + } + else { + /* regular number */ + const int new_exp = flt_e - 127; + if (new_exp < -24) { + /* this maps to 0 */ + /* m = 0; - already set */ + e = 0; + } + else if (new_exp < -14) { + /* this maps to a denorm */ + unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/ + e = 0; + switch (exp_val) { + case 0: + _mesa_warning(NULL, + "float_to_half: logical error in denorm creation!\n"); + /* m = 0; - already set */ + break; + case 1: m = 512 + (flt_m >> 14); break; + case 2: m = 256 + (flt_m >> 15); break; + case 3: m = 128 + (flt_m >> 16); break; + case 4: m = 64 + (flt_m >> 17); break; + case 5: m = 32 + (flt_m >> 18); break; + case 6: m = 16 + (flt_m >> 19); break; + case 7: m = 8 + (flt_m >> 20); break; + case 8: m = 4 + (flt_m >> 21); break; + case 9: m = 2 + (flt_m >> 22); break; + case 10: m = 1; break; + } + } + else if (new_exp > 15) { + /* map this value to infinity */ + /* m = 0; - already set */ + e = 31; + } + else { + /* regular */ + e = new_exp + 15; + m = flt_m >> 13; + } + } + + result = (s << 15) | (e << 10) | m; + return result; +} + + +/** + * Convert a 2-byte half float to a 4-byte float. + * Based on code from: + * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html + */ +float +_mesa_half_to_float(GLhalfARB val) +{ + /* XXX could also use a 64K-entry lookup table */ + const int m = val & 0x3ff; + const int e = (val >> 10) & 0x1f; + const int s = (val >> 15) & 0x1; + int flt_m, flt_e, flt_s, flt; + float result; + + /* sign bit */ + flt_s = s; + + /* handle special cases */ + if ((e == 0) && (m == 0)) { + /* zero */ + flt_m = 0; + flt_e = 0; + } + else if ((e == 0) && (m != 0)) { + /* denorm -- denorm half will fit in non-denorm single */ + const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */ + float mantissa = ((float) (m)) / 1024.0f; + float sign = s ? -1.0f : 1.0f; + return sign * mantissa * half_denorm; + } + else if ((e == 31) && (m == 0)) { + /* infinity */ + flt_e = 0xff; + flt_m = 0; + } + else if ((e == 31) && (m != 0)) { + /* NaN */ + flt_e = 0xff; + flt_m = 1; + } + else { + /* regular */ + flt_e = e + 112; + flt_m = m << 13; + } + + flt = (flt_s << 31) | (flt_e << 23) | flt_m; + result = *((float *) (void *) &flt); + return result; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Environment vars */ +/*@{*/ + +/** + * Wrapper for getenv(). + */ +char * +_mesa_getenv( const char *var ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86getenv(var); +#elif defined(_XBOX) + return NULL; +#else + return getenv(var); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name String */ +/*@{*/ + +/** Wrapper around either strstr() or xf86strstr() */ +char * +_mesa_strstr( const char *haystack, const char *needle ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strstr(haystack, needle); +#else + return strstr(haystack, needle); +#endif +} + +/** Wrapper around either strncat() or xf86strncat() */ +char * +_mesa_strncat( char *dest, const char *src, size_t n ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strncat(dest, src, n); +#else + return strncat(dest, src, n); +#endif +} + +/** Wrapper around either strcpy() or xf86strcpy() */ +char * +_mesa_strcpy( char *dest, const char *src ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strcpy(dest, src); +#else + return strcpy(dest, src); +#endif +} + +/** Wrapper around either strncpy() or xf86strncpy() */ +char * +_mesa_strncpy( char *dest, const char *src, size_t n ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strncpy(dest, src, n); +#else + return strncpy(dest, src, n); +#endif +} + +/** Wrapper around either strlen() or xf86strlen() */ +size_t +_mesa_strlen( const char *s ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strlen(s); +#else + return strlen(s); +#endif +} + +/** Wrapper around either strcmp() or xf86strcmp() */ +int +_mesa_strcmp( const char *s1, const char *s2 ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strcmp(s1, s2); +#else + return strcmp(s1, s2); +#endif +} + +/** Wrapper around either strncmp() or xf86strncmp() */ +int +_mesa_strncmp( const char *s1, const char *s2, size_t n ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strncmp(s1, s2, n); +#else + return strncmp(s1, s2, n); +#endif +} + +/** Implemented using _mesa_malloc() and _mesa_strcpy */ +char * +_mesa_strdup( const char *s ) +{ + size_t l = _mesa_strlen(s); + char *s2 = (char *) _mesa_malloc(l + 1); + if (s2) + _mesa_strcpy(s2, s); + return s2; +} + +/** Wrapper around either atoi() or xf86atoi() */ +int +_mesa_atoi(const char *s) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86atoi(s); +#else + return atoi(s); +#endif +} + +/** Wrapper around either strtod() or xf86strtod() */ +double +_mesa_strtod( const char *s, char **end ) +{ +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86strtod(s, end); +#else + return strtod(s, end); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name I/O */ +/*@{*/ + +/** Wrapper around either vsprintf() or xf86vsprintf() */ +int +_mesa_sprintf( char *str, const char *fmt, ... ) +{ + int r; + va_list args; + va_start( args, fmt ); + va_end( args ); +#if defined(XFree86LOADER) && defined(IN_MODULE) + r = xf86vsprintf( str, fmt, args ); +#else + r = vsprintf( str, fmt, args ); +#endif + return r; +} + +/** Wrapper around either printf() or xf86printf(), using vsprintf() for + * the formatting. */ +void +_mesa_printf( const char *fmtString, ... ) +{ + char s[MAXSTRING]; + va_list args; + va_start( args, fmtString ); + vsnprintf(s, MAXSTRING, fmtString, args); + va_end( args ); +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86printf("%s", s); +#else + fprintf(stderr,"%s", s); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Diagnostics */ +/*@{*/ + +/** + * Display a warning. + * + * \param ctx GL context. + * \param fmtString printf() alike format string. + * + * If debugging is enabled (either at compile-time via the DEBUG macro, or + * run-time via the MESA_DEBUG environment variable), prints the warning to + * stderr, either via fprintf() or xf86printf(). + */ +void +_mesa_warning( GLcontext *ctx, const char *fmtString, ... ) +{ + GLboolean debug; + char str[MAXSTRING]; + va_list args; + (void) ctx; + va_start( args, fmtString ); + (void) vsnprintf( str, MAXSTRING, fmtString, args ); + va_end( args ); +#ifdef DEBUG + debug = GL_TRUE; /* always print warning */ +#else + debug = _mesa_getenv("MESA_DEBUG") ? GL_TRUE : GL_FALSE; +#endif + if (debug) { +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86fprintf(stderr, "Mesa warning: %s", str); +#else + fprintf(stderr, "Mesa warning: %s", str); +#endif + } +} + +/** + * This function is called when the Mesa user has stumbled into a code + * path which may not be implemented fully or correctly. + * + * \param ctx GL context. + * \param s problem description string. + * + * Prints the message to stderr, either via fprintf() or xf86fprintf(). + */ +void +_mesa_problem( const GLcontext *ctx, const char *fmtString, ... ) +{ + va_list args; + char str[MAXSTRING]; + (void) ctx; + + va_start( args, fmtString ); + vsnprintf( str, MAXSTRING, fmtString, args ); + va_end( args ); + +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str); + xf86fprintf(stderr, "Please report at bugzilla.freedesktop.org\n"); +#else + fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str); + fprintf(stderr, "Please report at bugzilla.freedesktop.org\n"); +#endif +} + +/** + * Display an error message. + * + * If in debug mode, print error message. + * Also, record the error code by calling _mesa_record_error(). + * + * \param ctx the GL context. + * \param error the error value. + * \param fmtString printf() style format string, followed by optional args + * + * If debugging is enabled (either at compile-time via the DEBUG macro, or + * run-time via the MESA_DEBUG environment variable), interperts the error code and + * prints the error message via _mesa_debug(). + */ +void +_mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... ) +{ + const char *debugEnv; + GLboolean debug; + + debugEnv = _mesa_getenv("MESA_DEBUG"); + +#ifdef DEBUG + if (debugEnv && _mesa_strstr(debugEnv, "silent")) + debug = GL_FALSE; + else + debug = GL_TRUE; +#else + if (debugEnv) + debug = GL_TRUE; + else + debug = GL_FALSE; +#endif + + if (debug) { + va_list args; + char where[MAXSTRING]; + const char *errstr; + + va_start( args, fmtString ); + vsnprintf( where, MAXSTRING, fmtString, args ); + va_end( args ); + + switch (error) { + case GL_NO_ERROR: + errstr = "GL_NO_ERROR"; + break; + case GL_INVALID_VALUE: + errstr = "GL_INVALID_VALUE"; + break; + case GL_INVALID_ENUM: + errstr = "GL_INVALID_ENUM"; + break; + case GL_INVALID_OPERATION: + errstr = "GL_INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + errstr = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + errstr = "GL_STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + errstr = "GL_OUT_OF_MEMORY"; + break; + case GL_TABLE_TOO_LARGE: + errstr = "GL_TABLE_TOO_LARGE"; + break; + default: + errstr = "unknown"; + break; + } + _mesa_debug(ctx, "User error: %s in %s\n", errstr, where); + } + + _mesa_record_error(ctx, error); +} + +/** + * Report debug information. + * + * \param ctx GL context. + * \param fmtString printf() alike format string. + * + * Prints the message to stderr, either via fprintf() or xf86printf(). + */ +void +_mesa_debug( const GLcontext *ctx, const char *fmtString, ... ) +{ + char s[MAXSTRING]; + va_list args; + (void) ctx; + va_start(args, fmtString); + vsnprintf(s, MAXSTRING, fmtString, args); + va_end(args); +#if defined(XFree86LOADER) && defined(IN_MODULE) + xf86fprintf(stderr, "Mesa: %s", s); +#else + fprintf(stderr, "Mesa: %s", s); +#endif +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Default Imports Wrapper */ +/*@{*/ + +/** Wrapper around _mesa_malloc() */ +static void * +default_malloc(__GLcontext *gc, size_t size) +{ + (void) gc; + return _mesa_malloc(size); +} + +/** Wrapper around _mesa_malloc() */ +static void * +default_calloc(__GLcontext *gc, size_t numElem, size_t elemSize) +{ + (void) gc; + return _mesa_calloc(numElem * elemSize); +} + +/** Wrapper around either realloc() or xf86realloc() */ +static void * +default_realloc(__GLcontext *gc, void *oldAddr, size_t newSize) +{ + (void) gc; +#if defined(XFree86LOADER) && defined(IN_MODULE) + return xf86realloc(oldAddr, newSize); +#else + return realloc(oldAddr, newSize); +#endif +} + +/** Wrapper around _mesa_free() */ +static void +default_free(__GLcontext *gc, void *addr) +{ + (void) gc; + _mesa_free(addr); +} + +/** Wrapper around _mesa_getenv() */ +static char * CAPI +default_getenv( __GLcontext *gc, const char *var ) +{ + (void) gc; + return _mesa_getenv(var); +} + +/** Wrapper around _mesa_warning() */ +static void +default_warning(__GLcontext *gc, char *str) +{ + _mesa_warning(gc, str); +} + +/** Wrapper around _mesa_problem() */ +static void +default_fatal(__GLcontext *gc, char *str) +{ + _mesa_problem(gc, str); + abort(); +} + +/** Wrapper around atoi() */ +static int CAPI +default_atoi(__GLcontext *gc, const char *str) +{ + (void) gc; + return atoi(str); +} + +/** Wrapper around vsprintf() */ +static int CAPI +default_sprintf(__GLcontext *gc, char *str, const char *fmt, ...) +{ + int r; + va_list args; + (void) gc; + va_start( args, fmt ); + r = vsprintf( str, fmt, args ); + va_end( args ); + return r; +} + +/** Wrapper around fopen() */ +static void * CAPI +default_fopen(__GLcontext *gc, const char *path, const char *mode) +{ + (void) gc; + return fopen(path, mode); +} + +/** Wrapper around fclose() */ +static int CAPI +default_fclose(__GLcontext *gc, void *stream) +{ + (void) gc; + return fclose((FILE *) stream); +} + +/** Wrapper around vfprintf() */ +static int CAPI +default_fprintf(__GLcontext *gc, void *stream, const char *fmt, ...) +{ + int r; + va_list args; + (void) gc; + va_start( args, fmt ); + r = vfprintf( (FILE *) stream, fmt, args ); + va_end( args ); + return r; +} + +/** + * \todo this really is driver-specific and can't be here + */ +static __GLdrawablePrivate * +default_GetDrawablePrivate(__GLcontext *gc) +{ + (void) gc; + return NULL; +} + +/*@}*/ + + +/** + * Initialize a __GLimports object to point to the functions in this + * file. + * + * This is to be called from device drivers. + * + * Also, do some one-time initializations. + * + * \param imports the object to initialize. + * \param driverCtx pointer to device driver-specific data. + */ +void +_mesa_init_default_imports(__GLimports *imports, void *driverCtx) +{ + /* XXX maybe move this one-time init stuff into context.c */ + static GLboolean initialized = GL_FALSE; + if (!initialized) { + init_sqrt_table(); + +#if defined(_FPU_GETCW) && defined(_FPU_SETCW) + { + const char *debug = _mesa_getenv("MESA_DEBUG"); + if (debug && _mesa_strcmp(debug, "FP")==0) { + /* die on FP exceptions */ + fpu_control_t mask; + _FPU_GETCW(mask); + mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM + | _FPU_MASK_OM | _FPU_MASK_UM); + _FPU_SETCW(mask); + } + } +#endif + initialized = GL_TRUE; + } + + imports->malloc = default_malloc; + imports->calloc = default_calloc; + imports->realloc = default_realloc; + imports->free = default_free; + imports->warning = default_warning; + imports->fatal = default_fatal; + imports->getenv = default_getenv; /* not used for now */ + imports->atoi = default_atoi; + imports->sprintf = default_sprintf; + imports->fopen = default_fopen; + imports->fclose = default_fclose; + imports->fprintf = default_fprintf; + imports->getDrawablePrivate = default_GetDrawablePrivate; + imports->other = driverCtx; +} diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h new file mode 100644 index 00000000000..2ee66d9ac9b --- /dev/null +++ b/src/mesa/main/imports.h @@ -0,0 +1,778 @@ +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file imports.h + * Standard C library function wrappers. + * + * This file provides wrappers for all the standard C library functions + * like malloc(), free(), printf(), getenv(), etc. + */ + + +#ifndef IMPORTS_H +#define IMPORTS_H + + +/* XXX some of the stuff in glheader.h should be moved into this file. + */ +#include "glheader.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/**********************************************************************/ +/** \name General macros */ +/*@{*/ + +#ifndef NULL +#define NULL 0 +#endif + +/*@}*/ + + +/**********************************************************************/ +/** Memory macros */ +/*@{*/ + +/** Allocate \p BYTES bytes */ +#define MALLOC(BYTES) _mesa_malloc(BYTES) +/** Allocate and zero \p BYTES bytes */ +#define CALLOC(BYTES) _mesa_calloc(BYTES) +/** Allocate a structure of type \p T */ +#define MALLOC_STRUCT(T) (struct T *) _mesa_malloc(sizeof(struct T)) +/** Allocate and zero a structure of type \p T */ +#define CALLOC_STRUCT(T) (struct T *) _mesa_calloc(sizeof(struct T)) +/** Free memory */ +#define FREE(PTR) _mesa_free(PTR) + +/** Allocate \p BYTES aligned at \p N bytes */ +#define ALIGN_MALLOC(BYTES, N) _mesa_align_malloc(BYTES, N) +/** Allocate and zero \p BYTES bytes aligned at \p N bytes */ +#define ALIGN_CALLOC(BYTES, N) _mesa_align_calloc(BYTES, N) +/** Allocate a structure of type \p T aligned at \p N bytes */ +#define ALIGN_MALLOC_STRUCT(T, N) (struct T *) _mesa_align_malloc(sizeof(struct T), N) +/** Allocate and zero a structure of type \p T aligned at \p N bytes */ +#define ALIGN_CALLOC_STRUCT(T, N) (struct T *) _mesa_align_calloc(sizeof(struct T), N) +/** Free aligned memory */ +#define ALIGN_FREE(PTR) _mesa_align_free(PTR) + +/** Copy \p BYTES bytes from \p SRC into \p DST */ +#define MEMCPY( DST, SRC, BYTES) _mesa_memcpy(DST, SRC, BYTES) +/** Set \p N bytes in \p DST to \p VAL */ +#define MEMSET( DST, VAL, N ) _mesa_memset(DST, VAL, N) + +/*@}*/ + + +/* + * For GL_ARB_vertex_buffer_object we need to treat vertex array pointers + * as offsets into buffer stores. Since the vertex array pointer and + * buffer store pointer are both pointers and we need to add them, we use + * this macro. + * Both pointers/offsets are expressed in bytes. + */ +#define ADD_POINTERS(A, B) ( (GLubyte *) (A) + (uintptr_t) (B) ) + + +/**********************************************************************/ +/** \name [Pseudo] static array declaration. + * + * MACs and BeOS don't support static larger than 32kb, so ... + */ +/*@{*/ + +/** + * \def DEFARRAY + * Define a [static] unidimensional array + */ + +/** + * \def DEFMARRAY + * Define a [static] bi-dimensional array + */ + +/** + * \def DEFMNARRAY + * Define a [static] tri-dimensional array + */ + +/** + * \def CHECKARRAY + * Verifies a [static] array was properly allocated. + */ + +/** + * \def UNDEFARRAY + * Undefine (free) a [static] array. + */ + +#if defined(macintosh) && !defined(__MRC__) +/*extern char *AGLAlloc(int size);*/ +/*extern void AGLFree(char* ptr);*/ +# define DEFARRAY(TYPE,NAME,SIZE) TYPE *NAME = (TYPE*)_mesa_alloc(sizeof(TYPE)*(SIZE)) +# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE (*NAME)[SIZE2] = (TYPE(*)[SIZE2])_mesa_alloc(sizeof(TYPE)*(SIZE1)*(SIZE2)) +# define DEFMNARRAY(TYPE,NAME,SIZE1,SIZE2,SIZE3) TYPE (*NAME)[SIZE2][SIZE3] = (TYPE(*)[SIZE2][SIZE3])_mesa_alloc(sizeof(TYPE)*(SIZE1)*(SIZE2)*(SIZE3)) +# define CHECKARRAY(NAME,CMD) do {if (!(NAME)) {CMD;}} while (0) +# define UNDEFARRAY(NAME) do {if ((NAME)) {_mesa_free((char*)NAME);} }while (0) +#elif defined(__BEOS__) +# define DEFARRAY(TYPE,NAME,SIZE) TYPE *NAME = (TYPE*)_mesa_malloc(sizeof(TYPE)*(SIZE)) +# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE (*NAME)[SIZE2] = (TYPE(*)[SIZE2])_mesa_malloc(sizeof(TYPE)*(SIZE1)*(SIZE2)) +# define DEFMNARRAY(TYPE,NAME,SIZE1,SIZE2,SIZE3) TYPE (*NAME)[SIZE2][SIZE3] = (TYPE(*)[SIZE2][SIZE3])_mesa_malloc(sizeof(TYPE)*(SIZE1)*(SIZE2)*(SIZE3)) +# define CHECKARRAY(NAME,CMD) do {if (!(NAME)) {CMD;}} while (0) +# define UNDEFARRAY(NAME) do {if ((NAME)) {_mesa_free((char*)NAME);} }while (0) +#else +# define DEFARRAY(TYPE,NAME,SIZE) TYPE NAME[SIZE] +# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE NAME[SIZE1][SIZE2] +# define DEFMNARRAY(TYPE,NAME,SIZE1,SIZE2,SIZE3) TYPE NAME[SIZE1][SIZE2][SIZE3] +# define CHECKARRAY(NAME,CMD) do {} while(0) +# define UNDEFARRAY(NAME) +#endif + +/*@}*/ + + +/** + * Sometimes we treat GLfloats as GLints. On x86 systems, moving a float + * as a int (thereby using integer registers instead of FP registers) is + * a performance win. Typically, this can be done with ordinary casts. + * But with gcc's -fstrict-aliasing flag (which defaults to on in gcc 3.0) + * these casts generate warnings. + * The following union typedef is used to solve that. + */ +typedef union { GLfloat f; GLint i; } fi_type; + + + +/********************************************************************** + * Math macros + */ + +#define MAX_GLUSHORT 0xffff +#define MAX_GLUINT 0xffffffff + +#ifndef M_PI +#define M_PI (3.1415926536) +#endif + +#ifndef M_E +#define M_E (2.7182818284590452354) +#endif + + +/* XXX this is a bit of a hack needed for compilation within XFree86 */ +#ifndef FLT_MIN +#define FLT_MIN (1.0e-37) +#endif + +/* Degrees to radians conversion: */ +#define DEG2RAD (M_PI/180.0) + + +/*** + *** USE_IEEE: Determine if we're using IEEE floating point + ***/ +#if defined(__i386__) || defined(__386__) || defined(__sparc__) || \ + defined(__s390x__) || defined(__powerpc__) || \ + defined(__amd64__) || \ + defined(ia64) || defined(__ia64__) || \ + defined(__hppa__) || defined(hpux) || \ + defined(__mips) || defined(_MIPS_ARCH) || \ + defined(__arm__) || \ + defined(__sh__) || \ + (defined(__alpha__) && (defined(__IEEE_FLOAT) || !defined(VMS))) +#define USE_IEEE +#define IEEE_ONE 0x3f800000 +#endif + + +/*** + *** SQRTF: single-precision square root + ***/ +#if 0 /* _mesa_sqrtf() not accurate enough - temporarily disabled */ +# define SQRTF(X) _mesa_sqrtf(X) +#elif defined(XFree86LOADER) && defined(IN_MODULE) +# define SQRTF(X) (float) xf86sqrt((float) (X)) +#else +# define SQRTF(X) (float) sqrt((float) (X)) +#endif + + +/*** + *** INV_SQRTF: single-precision inverse square root + ***/ +#if 0 +#define INV_SQRTF(X) _mesa_inv_sqrt(X) +#else +#define INV_SQRTF(X) (1.0F / SQRTF(X)) /* this is faster on a P4 */ +#endif + + +/*** + *** LOG2: Log base 2 of float + ***/ +#ifdef USE_IEEE +#if 0 +/* This is pretty fast, but not accurate enough (only 2 fractional bits). + * Based on code from http://www.stereopsis.com/log2.html + */ +static INLINE GLfloat LOG2(GLfloat x) +{ + const GLfloat y = x * x * x * x; + const GLuint ix = *((GLuint *) &y); + const GLuint exp = (ix >> 23) & 0xFF; + const GLint log2 = ((GLint) exp) - 127; + return (GLfloat) log2 * (1.0 / 4.0); /* 4, because of x^4 above */ +} +#endif +/* Pretty fast, and accurate. + * Based on code from http://www.flipcode.com/totd/ + */ +static INLINE GLfloat LOG2(GLfloat val) +{ + fi_type num; + GLint log_2; + num.f = val; + log_2 = ((num.i >> 23) & 255) - 128; + num.i &= ~(255 << 23); + num.i += 127 << 23; + num.f = ((-1.0f/3) * num.f + 2) * num.f - 2.0f/3; + return num.f + log_2; +} +#elif defined(XFree86LOADER) && defined(IN_MODULE) +#define LOG2(x) ((GLfloat) (xf86log(x) * 1.442695)) +#else +/* + * NOTE: log_base_2(x) = log(x) / log(2) + * NOTE: 1.442695 = 1/log(2). + */ +#define LOG2(x) ((GLfloat) (log(x) * 1.442695F)) +#endif + + +/*** + *** IS_INF_OR_NAN: test if float is infinite or NaN + ***/ +#ifdef USE_IEEE +static INLINE int IS_INF_OR_NAN( float x ) +{ + fi_type tmp; + tmp.f = x; + return !(int)((unsigned int)((tmp.i & 0x7fffffff)-0x7f800000) >> 31); +} +#elif defined(isfinite) +#define IS_INF_OR_NAN(x) (!isfinite(x)) +#elif defined(finite) +#define IS_INF_OR_NAN(x) (!finite(x)) +#elif defined(__VMS) +#define IS_INF_OR_NAN(x) (!finite(x)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define IS_INF_OR_NAN(x) (!isfinite(x)) +#else +#define IS_INF_OR_NAN(x) (!finite(x)) +#endif + + +/*** + *** IS_NEGATIVE: test if float is negative + ***/ +#if defined(USE_IEEE) +static INLINE int GET_FLOAT_BITS( float x ) +{ + fi_type fi; + fi.f = x; + return fi.i; +} +#define IS_NEGATIVE(x) (GET_FLOAT_BITS(x) < 0) +#else +#define IS_NEGATIVE(x) (x < 0.0F) +#endif + + +/*** + *** DIFFERENT_SIGNS: test if two floats have opposite signs + ***/ +#if defined(USE_IEEE) +#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) +#else +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ +#define DIFFERENT_SIGNS(x,y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F) +#endif + + +/*** + *** CEILF: ceiling of float + *** FLOORF: floor of float + *** FABSF: absolute value of float + *** EXPF: raise e to the value + *** LDEXPF: multiply value by an integral power of two + *** FREXPF: extract mantissa and exponent from value + ***/ +#if defined(XFree86LOADER) && defined(IN_MODULE) +#define CEILF(x) ((GLfloat) xf86ceil(x)) +#define FLOORF(x) ((GLfloat) xf86floor(x)) +#define FABSF(x) ((GLfloat) xf86fabs(x)) +#define EXPF(x) ((GLfloat) xf86exp(x)) +#define LDEXPF(x,y) ((GLfloat) xf86ldexp(x,y)) +#define FREXPF(x,y) ((GLfloat) xf86frexp(x,y)) +#elif defined(__gnu_linux__) +/* C99 functions */ +#define CEILF(x) ceilf(x) +#define FLOORF(x) floorf(x) +#define FABSF(x) fabsf(x) +#define EXPF(x) expf(x) +#define LDEXPF(x,y) ldexpf(x,y) +#define FREXPF(x,y) frexpf(x,y) +#else +#define CEILF(x) ((GLfloat) ceil(x)) +#define FLOORF(x) ((GLfloat) floor(x)) +#define FABSF(x) ((GLfloat) fabs(x)) +#define EXPF(x) ((GLfloat) exp(x)) +#define LDEXPF(x,y) ((GLfloat) ldexp(x,y)) +#define FREXPF(x,y) ((GLfloat) frexp(x,y)) +#endif + + +/*** + *** IROUND: return (as an integer) float rounded to nearest integer + ***/ +#if defined(USE_SPARC_ASM) && defined(__GNUC__) && defined(__sparc__) +static INLINE int iround(float f) +{ + int r; + __asm__ ("fstoi %1, %0" : "=f" (r) : "f" (f)); + return r; +} +#define IROUND(x) iround(x) +#elif defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) && \ + (!defined(__BEOS__) || (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))) +static INLINE int iround(float f) +{ + int r; + __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st"); + return r; +} +#define IROUND(x) iround(x) +#elif defined(USE_X86_ASM) && defined(__MSC__) && defined(__WIN32__) +static INLINE int iround(float f) +{ + int r; + _asm { + fld f + fistp r + } + return r; +} +#define IROUND(x) iround(x) +#elif defined(__WATCOMC__) && defined(__386__) +long iround(float f); +#pragma aux iround = \ + "push eax" \ + "fistp dword ptr [esp]" \ + "pop eax" \ + parm [8087] \ + value [eax] \ + modify exact [eax]; +#define IROUND(x) iround(x) +#else +#define IROUND(f) ((int) (((f) >= 0.0F) ? ((f) + 0.5F) : ((f) - 0.5F))) +#endif + + +/*** + *** IROUND_POS: return (as an integer) positive float rounded to nearest int + ***/ +#ifdef DEBUG +#define IROUND_POS(f) (assert((f) >= 0.0F), IROUND(f)) +#else +#define IROUND_POS(f) (IROUND(f)) +#endif + + +/*** + *** IFLOOR: return (as an integer) floor of float + ***/ +#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) +/* + * IEEE floor for computers that round to nearest or even. + * 'f' must be between -4194304 and 4194303. + * This floor operation is done by "(iround(f + .5) + iround(f - .5)) >> 1", + * but uses some IEEE specific tricks for better speed. + * Contributed by Josh Vanderhoof + */ +static INLINE int ifloor(float f) +{ + int ai, bi; + double af, bf; + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + /* GCC generates an extra fstp/fld without this. */ + __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); + __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); + return (ai - bi) >> 1; +} +#define IFLOOR(x) ifloor(x) +#elif defined(USE_IEEE) +static INLINE int ifloor(float f) +{ + int ai, bi; + double af, bf; + fi_type u; + + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + u.f = (float) af; ai = u.i; + u.f = (float) bf; bi = u.i; + return (ai - bi) >> 1; +} +#define IFLOOR(x) ifloor(x) +#else +static INLINE int ifloor(float f) +{ + int i = IROUND(f); + return (i > f) ? i - 1 : i; +} +#define IFLOOR(x) ifloor(x) +#endif + + +/*** + *** ICEIL: return (as an integer) ceiling of float + ***/ +#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__) +/* + * IEEE ceil for computers that round to nearest or even. + * 'f' must be between -4194304 and 4194303. + * This ceil operation is done by "(iround(f + .5) + iround(f - .5) + 1) >> 1", + * but uses some IEEE specific tricks for better speed. + * Contributed by Josh Vanderhoof + */ +static INLINE int iceil(float f) +{ + int ai, bi; + double af, bf; + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + /* GCC generates an extra fstp/fld without this. */ + __asm__ ("fstps %0" : "=m" (ai) : "t" (af) : "st"); + __asm__ ("fstps %0" : "=m" (bi) : "t" (bf) : "st"); + return (ai - bi + 1) >> 1; +} +#define ICEIL(x) iceil(x) +#elif defined(USE_IEEE) +static INLINE int iceil(float f) +{ + int ai, bi; + double af, bf; + fi_type u; + af = (3 << 22) + 0.5 + (double)f; + bf = (3 << 22) + 0.5 - (double)f; + u.f = (float) af; ai = u.i; + u.f = (float) bf; bi = u.i; + return (ai - bi + 1) >> 1; +} +#define ICEIL(x) iceil(x) +#else +static INLINE int iceil(float f) +{ + int i = IROUND(f); + return (i < f) ? i + 1 : i; +} +#define ICEIL(x) iceil(x) +#endif + + +/*** + *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] + *** CLAMPED_FLOAT_TO_UBYTE: map float known to be in [0,1] to ubyte in [0,255] + ***/ +#if defined(USE_IEEE) && !defined(DEBUG) +#define IEEE_0996 0x3f7f0000 /* 0.996 or so */ +/* This function/macro is sensitive to precision. Test very carefully + * if you change it! + */ +#define UNCLAMPED_FLOAT_TO_UBYTE(UB, F) \ + do { \ + fi_type __tmp; \ + __tmp.f = (F); \ + if (__tmp.i < 0) \ + UB = (GLubyte) 0; \ + else if (__tmp.i >= IEEE_0996) \ + UB = (GLubyte) 255; \ + else { \ + __tmp.f = __tmp.f * (255.0F/256.0F) + 32768.0F; \ + UB = (GLubyte) __tmp.i; \ + } \ + } while (0) +#define CLAMPED_FLOAT_TO_UBYTE(UB, F) \ + do { \ + fi_type __tmp; \ + __tmp.f = (F) * (255.0F/256.0F) + 32768.0F; \ + UB = (GLubyte) __tmp.i; \ + } while (0) +#else +#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \ + ub = ((GLubyte) IROUND(CLAMP((f), 0.0F, 1.0F) * 255.0F)) +#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \ + ub = ((GLubyte) IROUND((f) * 255.0F)) +#endif + + +/*** + *** COPY_FLOAT: copy a float from src to dest. + ***/ +#define COPY_FLOAT( dst, src ) (dst) = (src) + + +/*** + *** START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save + *** original mode to a temporary). + *** END_FAST_MATH: Restore x86 FPU to original mode. + ***/ +#if defined(__GNUC__) && defined(__i386__) +/* + * Set the x86 FPU control word to guarentee only 32 bits of precision + * are stored in registers. Allowing the FPU to store more introduces + * differences between situations where numbers are pulled out of memory + * vs. situations where the compiler is able to optimize register usage. + * + * In the worst case, we force the compiler to use a memory access to + * truncate the float, by specifying the 'volatile' keyword. + */ +/* Hardware default: All exceptions masked, extended double precision, + * round to nearest (IEEE compliant): + */ +#define DEFAULT_X86_FPU 0x037f +/* All exceptions masked, single precision, round to nearest: + */ +#define FAST_X86_FPU 0x003f +/* The fldcw instruction will cause any pending FP exceptions to be + * raised prior to entering the block, and we clear any pending + * exceptions before exiting the block. Hence, asm code has free + * reign over the FPU while in the fast math block. + */ +#if defined(NO_FAST_MATH) +#define START_FAST_MATH(x) \ +do { \ + static GLuint mask = DEFAULT_X86_FPU; \ + __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \ + __asm__ ( "fldcw %0" : : "m" (mask) ); \ +} while (0) +#else +#define START_FAST_MATH(x) \ +do { \ + static GLuint mask = FAST_X86_FPU; \ + __asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \ + __asm__ ( "fldcw %0" : : "m" (mask) ); \ +} while (0) +#endif +/* Restore original FPU mode, and clear any exceptions that may have + * occurred in the FAST_MATH block. + */ +#define END_FAST_MATH(x) \ +do { \ + __asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \ +} while (0) + +#elif defined(__WATCOMC__) && defined(__386__) +#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */ +#define FAST_X86_FPU 0x003f /* See GCC comments above */ +void _watcom_start_fast_math(unsigned short *x,unsigned short *mask); +#pragma aux _watcom_start_fast_math = \ + "fnstcw word ptr [eax]" \ + "fldcw word ptr [ecx]" \ + parm [eax] [ecx] \ + modify exact []; +void _watcom_end_fast_math(unsigned short *x); +#pragma aux _watcom_end_fast_math = \ + "fnclex" \ + "fldcw word ptr [eax]" \ + parm [eax] \ + modify exact []; +#if defined(NO_FAST_MATH) +#define START_FAST_MATH(x) \ +do { \ + static GLushort mask = DEFAULT_X86_FPU; \ + _watcom_start_fast_math(&x,&mask); \ +} while (0) +#else +#define START_FAST_MATH(x) \ +do { \ + static GLushort mask = FAST_X86_FPU; \ + _watcom_start_fast_math(&x,&mask); \ +} while (0) +#endif +#define END_FAST_MATH(x) _watcom_end_fast_math(&x) +#else +#define START_FAST_MATH(x) x = 0 +#define END_FAST_MATH(x) (void)(x) +#endif + + + +/********************************************************************** + * Functions + */ + +extern void * +_mesa_malloc( size_t bytes ); + +extern void * +_mesa_calloc( size_t bytes ); + +extern void +_mesa_free( void *ptr ); + +extern void * +_mesa_align_malloc( size_t bytes, unsigned long alignment ); + +extern void * +_mesa_align_calloc( size_t bytes, unsigned long alignment ); + +extern void +_mesa_align_free( void *ptr ); + +extern void * +_mesa_exec_malloc( GLuint size ); + +extern void +_mesa_exec_free( void *addr ); + +extern void * +_mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize ); + +extern void * +_mesa_memcpy( void *dest, const void *src, size_t n ); + +extern void +_mesa_memset( void *dst, int val, size_t n ); + +extern void +_mesa_memset16( unsigned short *dst, unsigned short val, size_t n ); + +extern void +_mesa_bzero( void *dst, size_t n ); + + +extern double +_mesa_sin(double a); + +extern double +_mesa_cos(double a); + +extern double +_mesa_sqrtd(double x); + +extern float +_mesa_sqrtf(float x); + +extern float +_mesa_inv_sqrtf(float x); + +extern double +_mesa_pow(double x, double y); + +extern float +_mesa_log2(float x); + +extern unsigned int +_mesa_bitcount(unsigned int n); + +extern GLhalfARB +_mesa_float_to_half(float f); + +extern float +_mesa_half_to_float(GLhalfARB h); + + +extern char * +_mesa_getenv( const char *var ); + +extern char * +_mesa_strstr( const char *haystack, const char *needle ); + +extern char * +_mesa_strncat( char *dest, const char *src, size_t n ); + +extern char * +_mesa_strcpy( char *dest, const char *src ); + +extern char * +_mesa_strncpy( char *dest, const char *src, size_t n ); + +extern size_t +_mesa_strlen( const char *s ); + +extern int +_mesa_strcmp( const char *s1, const char *s2 ); + +extern int +_mesa_strncmp( const char *s1, const char *s2, size_t n ); + +extern char * +_mesa_strdup( const char *s ); + +extern int +_mesa_atoi( const char *s ); + +extern double +_mesa_strtod( const char *s, char **end ); + +extern int +_mesa_sprintf( char *str, const char *fmt, ... ); + +extern void +_mesa_printf( const char *fmtString, ... ); + + +extern void +_mesa_warning( __GLcontext *gc, const char *fmtString, ... ); + +extern void +_mesa_problem( const __GLcontext *ctx, const char *fmtString, ... ); + +extern void +_mesa_error( __GLcontext *ctx, GLenum error, const char *fmtString, ... ); + +extern void +_mesa_debug( const __GLcontext *ctx, const char *fmtString, ... ); + + +extern void +_mesa_init_default_imports( __GLimports *imports, void *driverCtx ); + + +#ifdef __cplusplus +} +#endif + + +#endif /* IMPORTS_H */ diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c new file mode 100644 index 00000000000..98934f39820 --- /dev/null +++ b/src/mesa/main/light.c @@ -0,0 +1,1313 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "enums.h" +#include "light.h" +#include "macros.h" +#include "simple_list.h" +#include "mtypes.h" +#include "math/m_matrix.h" + + +void GLAPIENTRY +_mesa_ShadeModel( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glShadeModel %s\n", _mesa_lookup_enum_by_nr(mode)); + + if (mode != GL_FLAT && mode != GL_SMOOTH) { + _mesa_error( ctx, GL_INVALID_ENUM, "glShadeModel" ); + return; + } + + if (ctx->Light.ShadeModel == mode) + return; + + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.ShadeModel = mode; + ctx->_TriangleCaps ^= DD_FLATSHADE; + if (ctx->Driver.ShadeModel) + (*ctx->Driver.ShadeModel)( ctx, mode ); +} + + +void GLAPIENTRY +_mesa_Lightf( GLenum light, GLenum pname, GLfloat param ) +{ + _mesa_Lightfv( light, pname, ¶m ); +} + + +void GLAPIENTRY +_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i = (GLint) (light - GL_LIGHT0); + struct gl_light *l = &ctx->Light.Light[i]; + + if (i < 0 || i >= (GLint) ctx->Const.MaxLights) { + _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light ); + return; + } + + switch (pname) { + case GL_AMBIENT: + if (TEST_EQ_4V(l->Ambient, params)) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + COPY_4V( l->Ambient, params ); + break; + case GL_DIFFUSE: + if (TEST_EQ_4V(l->Diffuse, params)) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + COPY_4V( l->Diffuse, params ); + break; + case GL_SPECULAR: + if (TEST_EQ_4V(l->Specular, params)) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + COPY_4V( l->Specular, params ); + break; + case GL_POSITION: { + GLfloat tmp[4]; + /* transform position by ModelView matrix */ + TRANSFORM_POINT( tmp, ctx->ModelviewMatrixStack.Top->m, params ); + if (TEST_EQ_4V(l->EyePosition, tmp)) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + COPY_4V(l->EyePosition, tmp); + if (l->EyePosition[3] != 0.0F) + l->_Flags |= LIGHT_POSITIONAL; + else + l->_Flags &= ~LIGHT_POSITIONAL; + break; + } + case GL_SPOT_DIRECTION: { + GLfloat tmp[4]; + /* transform direction by inverse modelview */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + } + TRANSFORM_NORMAL( tmp, params, ctx->ModelviewMatrixStack.Top->inv ); + if (TEST_EQ_3V(l->EyeDirection, tmp)) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + COPY_3V(l->EyeDirection, tmp); + break; + } + case GL_SPOT_EXPONENT: + if (params[0]<0.0 || params[0]>ctx->Const.MaxSpotExponent) { + _mesa_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + if (l->SpotExponent == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + l->SpotExponent = params[0]; + _mesa_invalidate_spot_exp_table( l ); + break; + case GL_SPOT_CUTOFF: + if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + if (l->SpotCutoff == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + l->SpotCutoff = params[0]; + l->_CosCutoff = (GLfloat) _mesa_cos(params[0]*DEG2RAD); + if (l->_CosCutoff < 0) + l->_CosCutoff = 0; + if (l->SpotCutoff != 180.0F) + l->_Flags |= LIGHT_SPOT; + else + l->_Flags &= ~LIGHT_SPOT; + break; + case GL_CONSTANT_ATTENUATION: + if (params[0]<0.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + if (l->ConstantAttenuation == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + l->ConstantAttenuation = params[0]; + break; + case GL_LINEAR_ATTENUATION: + if (params[0]<0.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + if (l->LinearAttenuation == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + l->LinearAttenuation = params[0]; + break; + case GL_QUADRATIC_ATTENUATION: + if (params[0]<0.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glLight" ); + return; + } + if (l->QuadraticAttenuation == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + l->QuadraticAttenuation = params[0]; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname ); + return; + } + + if (ctx->Driver.Lightfv) + ctx->Driver.Lightfv( ctx, light, pname, params ); +} + + +void GLAPIENTRY +_mesa_Lighti( GLenum light, GLenum pname, GLint param ) +{ + _mesa_Lightiv( light, pname, ¶m ); +} + + +void GLAPIENTRY +_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + + switch (pname) { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + fparam[0] = INT_TO_FLOAT( params[0] ); + fparam[1] = INT_TO_FLOAT( params[1] ); + fparam[2] = INT_TO_FLOAT( params[2] ); + fparam[3] = INT_TO_FLOAT( params[3] ); + break; + case GL_POSITION: + fparam[0] = (GLfloat) params[0]; + fparam[1] = (GLfloat) params[1]; + fparam[2] = (GLfloat) params[2]; + fparam[3] = (GLfloat) params[3]; + break; + case GL_SPOT_DIRECTION: + fparam[0] = (GLfloat) params[0]; + fparam[1] = (GLfloat) params[1]; + fparam[2] = (GLfloat) params[2]; + break; + case GL_SPOT_EXPONENT: + case GL_SPOT_CUTOFF: + case GL_CONSTANT_ATTENUATION: + case GL_LINEAR_ATTENUATION: + case GL_QUADRATIC_ATTENUATION: + fparam[0] = (GLfloat) params[0]; + break; + default: + /* error will be caught later in gl_Lightfv */ + ; + } + + _mesa_Lightfv( light, pname, fparam ); +} + + + +void GLAPIENTRY +_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint l = (GLint) (light - GL_LIGHT0); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (l < 0 || l >= (GLint) ctx->Const.MaxLights) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); + return; + } + + switch (pname) { + case GL_AMBIENT: + COPY_4V( params, ctx->Light.Light[l].Ambient ); + break; + case GL_DIFFUSE: + COPY_4V( params, ctx->Light.Light[l].Diffuse ); + break; + case GL_SPECULAR: + COPY_4V( params, ctx->Light.Light[l].Specular ); + break; + case GL_POSITION: + COPY_4V( params, ctx->Light.Light[l].EyePosition ); + break; + case GL_SPOT_DIRECTION: + COPY_3V( params, ctx->Light.Light[l].EyeDirection ); + break; + case GL_SPOT_EXPONENT: + params[0] = ctx->Light.Light[l].SpotExponent; + break; + case GL_SPOT_CUTOFF: + params[0] = ctx->Light.Light[l].SpotCutoff; + break; + case GL_CONSTANT_ATTENUATION: + params[0] = ctx->Light.Light[l].ConstantAttenuation; + break; + case GL_LINEAR_ATTENUATION: + params[0] = ctx->Light.Light[l].LinearAttenuation; + break; + case GL_QUADRATIC_ATTENUATION: + params[0] = ctx->Light.Light[l].QuadraticAttenuation; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" ); + break; + } +} + + +void GLAPIENTRY +_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint l = (GLint) (light - GL_LIGHT0); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (l < 0 || l >= (GLint) ctx->Const.MaxLights) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); + return; + } + + switch (pname) { + case GL_AMBIENT: + params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]); + break; + case GL_DIFFUSE: + params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]); + break; + case GL_SPECULAR: + params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]); + params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]); + params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]); + params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]); + break; + case GL_POSITION: + params[0] = (GLint) ctx->Light.Light[l].EyePosition[0]; + params[1] = (GLint) ctx->Light.Light[l].EyePosition[1]; + params[2] = (GLint) ctx->Light.Light[l].EyePosition[2]; + params[3] = (GLint) ctx->Light.Light[l].EyePosition[3]; + break; + case GL_SPOT_DIRECTION: + params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0]; + params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1]; + params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2]; + break; + case GL_SPOT_EXPONENT: + params[0] = (GLint) ctx->Light.Light[l].SpotExponent; + break; + case GL_SPOT_CUTOFF: + params[0] = (GLint) ctx->Light.Light[l].SpotCutoff; + break; + case GL_CONSTANT_ATTENUATION: + params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation; + break; + case GL_LINEAR_ATTENUATION: + params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation; + break; + case GL_QUADRATIC_ATTENUATION: + params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" ); + break; + } +} + + + +/**********************************************************************/ +/*** Light Model ***/ +/**********************************************************************/ + + +void GLAPIENTRY +_mesa_LightModelfv( GLenum pname, const GLfloat *params ) +{ + GLenum newenum; + GLboolean newbool; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + if (TEST_EQ_4V( ctx->Light.Model.Ambient, params )) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + COPY_4V( ctx->Light.Model.Ambient, params ); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + newbool = (params[0]!=0.0); + if (ctx->Light.Model.LocalViewer == newbool) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.Model.LocalViewer = newbool; + break; + case GL_LIGHT_MODEL_TWO_SIDE: + newbool = (params[0]!=0.0); + if (ctx->Light.Model.TwoSide == newbool) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.Model.TwoSide = newbool; + + if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) + ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; + else + ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE; + break; + case GL_LIGHT_MODEL_COLOR_CONTROL: + if (params[0] == (GLfloat) GL_SINGLE_COLOR) + newenum = GL_SINGLE_COLOR; + else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) + newenum = GL_SEPARATE_SPECULAR_COLOR; + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)", + (GLint) params[0] ); + return; + } + if (ctx->Light.Model.ColorControl == newenum) + return; + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.Model.ColorControl = newenum; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname ); + break; + } + + if (ctx->Driver.LightModelfv) + ctx->Driver.LightModelfv( ctx, pname, params ); +} + + +void GLAPIENTRY +_mesa_LightModeliv( GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + fparam[0] = INT_TO_FLOAT( params[0] ); + fparam[1] = INT_TO_FLOAT( params[1] ); + fparam[2] = INT_TO_FLOAT( params[2] ); + fparam[3] = INT_TO_FLOAT( params[3] ); + break; + case GL_LIGHT_MODEL_LOCAL_VIEWER: + case GL_LIGHT_MODEL_TWO_SIDE: + case GL_LIGHT_MODEL_COLOR_CONTROL: + fparam[0] = (GLfloat) params[0]; + break; + default: + /* Error will be caught later in gl_LightModelfv */ + ; + } + _mesa_LightModelfv( pname, fparam ); +} + + +void GLAPIENTRY +_mesa_LightModeli( GLenum pname, GLint param ) +{ + _mesa_LightModeliv( pname, ¶m ); +} + + +void GLAPIENTRY +_mesa_LightModelf( GLenum pname, GLfloat param ) +{ + _mesa_LightModelfv( pname, ¶m ); +} + + + +/********** MATERIAL **********/ + + +/* + * Given a face and pname value (ala glColorMaterial), compute a bitmask + * of the targeted material values. + */ +GLuint +_mesa_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname, + GLuint legal, const char *where ) +{ + GLuint bitmask = 0; + + /* Make a bitmask indicating what material attribute(s) we're updating */ + switch (pname) { + case GL_EMISSION: + bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION; + break; + case GL_AMBIENT: + bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT; + break; + case GL_DIFFUSE: + bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE; + break; + case GL_SPECULAR: + bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR; + break; + case GL_SHININESS: + bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS; + break; + case GL_AMBIENT_AND_DIFFUSE: + bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT; + bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE; + break; + case GL_COLOR_INDEXES: + bitmask |= MAT_BIT_FRONT_INDEXES | MAT_BIT_BACK_INDEXES; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, where ); + return 0; + } + + if (face==GL_FRONT) { + bitmask &= FRONT_MATERIAL_BITS; + } + else if (face==GL_BACK) { + bitmask &= BACK_MATERIAL_BITS; + } + else if (face != GL_FRONT_AND_BACK) { + _mesa_error( ctx, GL_INVALID_ENUM, where ); + return 0; + } + + if (bitmask & ~legal) { + _mesa_error( ctx, GL_INVALID_ENUM, where ); + return 0; + } + + return bitmask; +} + + + +/* Perform a straight copy between materials. + */ +void +_mesa_copy_materials( struct gl_material *dst, + const struct gl_material *src, + GLuint bitmask ) +{ + int i; + + for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) + if (bitmask & (1<<i)) + COPY_4FV( dst->Attrib[i], src->Attrib[i] ); +} + + + +/* Update derived values following a change in ctx->Light.Material + */ +void +_mesa_update_material( GLcontext *ctx, GLuint bitmask ) +{ + struct gl_light *light, *list = &ctx->Light.EnabledList; + GLfloat (*mat)[4] = ctx->Light.Material.Attrib; + + if (MESA_VERBOSE&VERBOSE_IMMEDIATE) + _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask); + + if (!bitmask) + return; + + /* update material ambience */ + if (bitmask & MAT_BIT_FRONT_AMBIENT) { + foreach (light, list) { + SCALE_3V( light->_MatAmbient[0], light->Ambient, + mat[MAT_ATTRIB_FRONT_AMBIENT]); + } + } + + if (bitmask & MAT_BIT_BACK_AMBIENT) { + foreach (light, list) { + SCALE_3V( light->_MatAmbient[1], light->Ambient, + mat[MAT_ATTRIB_BACK_AMBIENT]); + } + } + + /* update BaseColor = emission + scene's ambience * material's ambience */ + if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) { + COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] ); + ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT], + ctx->Light.Model.Ambient ); + } + + if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) { + COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] ); + ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT], + ctx->Light.Model.Ambient ); + } + + /* update material diffuse values */ + if (bitmask & MAT_BIT_FRONT_DIFFUSE) { + foreach (light, list) { + SCALE_3V( light->_MatDiffuse[0], light->Diffuse, + mat[MAT_ATTRIB_FRONT_DIFFUSE] ); + } + } + + if (bitmask & MAT_BIT_BACK_DIFFUSE) { + foreach (light, list) { + SCALE_3V( light->_MatDiffuse[1], light->Diffuse, + mat[MAT_ATTRIB_BACK_DIFFUSE] ); + } + } + + /* update material specular values */ + if (bitmask & MAT_BIT_FRONT_SPECULAR) { + foreach (light, list) { + SCALE_3V( light->_MatSpecular[0], light->Specular, + mat[MAT_ATTRIB_FRONT_SPECULAR]); + } + } + + if (bitmask & MAT_BIT_BACK_SPECULAR) { + foreach (light, list) { + SCALE_3V( light->_MatSpecular[1], light->Specular, + mat[MAT_ATTRIB_BACK_SPECULAR]); + } + } + + if (bitmask & MAT_BIT_FRONT_SHININESS) { + _mesa_invalidate_shine_table( ctx, 0 ); + } + + if (bitmask & MAT_BIT_BACK_SHININESS) { + _mesa_invalidate_shine_table( ctx, 1 ); + } +} + + +/* + * Update the current materials from the given rgba color + * according to the bitmask in ColorMaterialBitmask, which is + * set by glColorMaterial(). + */ +void +_mesa_update_color_material( GLcontext *ctx, const GLfloat color[4] ) +{ + GLuint bitmask = ctx->Light.ColorMaterialBitmask; + struct gl_material *mat = &ctx->Light.Material; + int i; + + for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) + if (bitmask & (1<<i)) + COPY_4FV( mat->Attrib[i], color ); + + _mesa_update_material( ctx, bitmask ); +} + + +void GLAPIENTRY +_mesa_ColorMaterial( GLenum face, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint bitmask; + GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION | + MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR | + MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE | + MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glColorMaterial %s %s\n", + _mesa_lookup_enum_by_nr(face), + _mesa_lookup_enum_by_nr(mode)); + + bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial"); + + if (ctx->Light.ColorMaterialBitmask == bitmask && + ctx->Light.ColorMaterialFace == face && + ctx->Light.ColorMaterialMode == mode) + return; + + FLUSH_VERTICES(ctx, _NEW_LIGHT); + ctx->Light.ColorMaterialBitmask = bitmask; + ctx->Light.ColorMaterialFace = face; + ctx->Light.ColorMaterialMode = mode; + + if (ctx->Light.ColorMaterialEnabled) { + FLUSH_CURRENT( ctx, 0 ); + _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); + } + + if (ctx->Driver.ColorMaterial) + (*ctx->Driver.ColorMaterial)( ctx, face, mode ); +} + + +void GLAPIENTRY +_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint f; + GLfloat (*mat)[4] = ctx->Light.Material.Attrib; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */ + + FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */ + + if (face==GL_FRONT) { + f = 0; + } + else if (face==GL_BACK) { + f = 1; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" ); + return; + } + + switch (pname) { + case GL_AMBIENT: + COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] ); + break; + case GL_DIFFUSE: + COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] ); + break; + case GL_SPECULAR: + COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] ); + break; + case GL_EMISSION: + COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] ); + break; + case GL_SHININESS: + *params = mat[MAT_ATTRIB_SHININESS(f)][0]; + break; + case GL_COLOR_INDEXES: + params[0] = mat[MAT_ATTRIB_INDEXES(f)][0]; + params[1] = mat[MAT_ATTRIB_INDEXES(f)][1]; + params[2] = mat[MAT_ATTRIB_INDEXES(f)][2]; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); + } +} + + +void GLAPIENTRY +_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint f; + GLfloat (*mat)[4] = ctx->Light.Material.Attrib; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* update materials */ + + FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */ + + if (face==GL_FRONT) { + f = 0; + } + else if (face==GL_BACK) { + f = 1; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" ); + return; + } + switch (pname) { + case GL_AMBIENT: + params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] ); + params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] ); + params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] ); + params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] ); + break; + case GL_DIFFUSE: + params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] ); + params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] ); + params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] ); + params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] ); + break; + case GL_SPECULAR: + params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] ); + params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] ); + params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] ); + params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] ); + break; + case GL_EMISSION: + params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] ); + params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] ); + params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] ); + params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] ); + break; + case GL_SHININESS: + *params = IROUND( mat[MAT_ATTRIB_SHININESS(f)][0] ); + break; + case GL_COLOR_INDEXES: + params[0] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][0] ); + params[1] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][1] ); + params[2] = IROUND( mat[MAT_ATTRIB_INDEXES(f)][2] ); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" ); + } +} + + + +/**********************************************************************/ +/***** Lighting computation *****/ +/**********************************************************************/ + + +/* + * Notes: + * When two-sided lighting is enabled we compute the color (or index) + * for both the front and back side of the primitive. Then, when the + * orientation of the facet is later learned, we can determine which + * color (or index) to use for rendering. + * + * KW: We now know orientation in advance and only shade for + * the side or sides which are actually required. + * + * Variables: + * n = normal vector + * V = vertex position + * P = light source position + * Pe = (0,0,0,1) + * + * Precomputed: + * IF P[3]==0 THEN + * // light at infinity + * IF local_viewer THEN + * _VP_inf_norm = unit vector from V to P // Precompute + * ELSE + * // eye at infinity + * _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute + * ENDIF + * ENDIF + * + * Functions: + * Normalize( v ) = normalized vector v + * Magnitude( v ) = length of vector v + */ + + + +/* + * Whenever the spotlight exponent for a light changes we must call + * this function to recompute the exponent lookup table. + */ +void +_mesa_invalidate_spot_exp_table( struct gl_light *l ) +{ + l->_SpotExpTable[0][0] = -1; +} + + +static void +validate_spot_exp_table( struct gl_light *l ) +{ + GLint i; + GLdouble exponent = l->SpotExponent; + GLdouble tmp = 0; + GLint clamp = 0; + + l->_SpotExpTable[0][0] = 0.0; + + for (i = EXP_TABLE_SIZE - 1; i > 0 ;i--) { + if (clamp == 0) { + tmp = _mesa_pow(i / (GLdouble) (EXP_TABLE_SIZE - 1), exponent); + if (tmp < FLT_MIN * 100.0) { + tmp = 0.0; + clamp = 1; + } + } + l->_SpotExpTable[i][0] = (GLfloat) tmp; + } + for (i = 0; i < EXP_TABLE_SIZE - 1; i++) { + l->_SpotExpTable[i][1] = (l->_SpotExpTable[i+1][0] - + l->_SpotExpTable[i][0]); + } + l->_SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0; +} + + + +/* Calculate a new shine table. Doing this here saves a branch in + * lighting, and the cost of doing it early may be partially offset + * by keeping a MRU cache of shine tables for various shine values. + */ +void +_mesa_invalidate_shine_table( GLcontext *ctx, GLuint side ) +{ + ASSERT(side < 2); + if (ctx->_ShineTable[side]) + ctx->_ShineTable[side]->refcount--; + ctx->_ShineTable[side] = NULL; +} + + +static void +validate_shine_table( GLcontext *ctx, GLuint side, GLfloat shininess ) +{ + struct gl_shine_tab *list = ctx->_ShineTabList; + struct gl_shine_tab *s; + + ASSERT(side < 2); + + foreach(s, list) + if ( s->shininess == shininess ) + break; + + if (s == list) { + GLint j; + GLfloat *m; + + foreach(s, list) + if (s->refcount == 0) + break; + + m = s->tab; + m[0] = 0.0; + if (shininess == 0.0) { + for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++) + m[j] = 1.0; + } + else { + for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) { + GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1); + if (x < 0.005) /* underflow check */ + x = 0.005; + t = _mesa_pow(x, shininess); + if (t > 1e-20) + m[j] = (GLfloat) t; + else + m[j] = 0.0; + } + m[SHINE_TABLE_SIZE] = 1.0; + } + + s->shininess = shininess; + } + + if (ctx->_ShineTable[side]) + ctx->_ShineTable[side]->refcount--; + + ctx->_ShineTable[side] = s; + move_to_tail( list, s ); + s->refcount++; +} + + +void +_mesa_validate_all_lighting_tables( GLcontext *ctx ) +{ + GLuint i; + GLfloat shininess; + + shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0]; + if (!ctx->_ShineTable[0] || ctx->_ShineTable[0]->shininess != shininess) + validate_shine_table( ctx, 0, shininess ); + + shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0]; + if (!ctx->_ShineTable[1] || ctx->_ShineTable[1]->shininess != shininess) + validate_shine_table( ctx, 1, shininess ); + + for (i = 0 ; i < MAX_LIGHTS ; i++) + if (ctx->Light.Light[i]._SpotExpTable[0][0] == -1) + validate_spot_exp_table( &ctx->Light.Light[i] ); +} + + + +/* + * Examine current lighting parameters to determine if the optimized lighting + * function can be used. + * Also, precompute some lighting values such as the products of light + * source and material ambient, diffuse and specular coefficients. + */ +void +_mesa_update_lighting( GLcontext *ctx ) +{ + struct gl_light *light; + ctx->Light._NeedEyeCoords = 0; + ctx->Light._Flags = 0; + + if (!ctx->Light.Enabled) + return; + + foreach(light, &ctx->Light.EnabledList) { + ctx->Light._Flags |= light->_Flags; + } + + ctx->Light._NeedVertices = + ((ctx->Light._Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) || + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR || + ctx->Light.Model.LocalViewer); + + ctx->Light._NeedEyeCoords = ((ctx->Light._Flags & LIGHT_POSITIONAL) || + ctx->Light.Model.LocalViewer); + + + + /* XXX: This test is overkill & needs to be fixed both for software and + * hardware t&l drivers. The above should be sufficient & should + * be tested to verify this. + */ + if (ctx->Light._NeedVertices) + ctx->Light._NeedEyeCoords = GL_TRUE; + + + /* Precompute some shading values. Although we reference + * Light.Material here, we can get away without flushing + * FLUSH_UPDATE_CURRENT, as when any outstanding material changes + * are flushed, they will update the derived state at that time. + */ + if (ctx->Visual.rgbMode) { + if (ctx->Light.Model.TwoSide) + _mesa_update_material( ctx, + MAT_BIT_FRONT_EMISSION | + MAT_BIT_FRONT_AMBIENT | + MAT_BIT_FRONT_DIFFUSE | + MAT_BIT_FRONT_SPECULAR | + MAT_BIT_BACK_EMISSION | + MAT_BIT_BACK_AMBIENT | + MAT_BIT_BACK_DIFFUSE | + MAT_BIT_BACK_SPECULAR); + else + _mesa_update_material( ctx, + MAT_BIT_FRONT_EMISSION | + MAT_BIT_FRONT_AMBIENT | + MAT_BIT_FRONT_DIFFUSE | + MAT_BIT_FRONT_SPECULAR); + } + else { + static const GLfloat ci[3] = { .30F, .59F, .11F }; + foreach(light, &ctx->Light.EnabledList) { + light->_dli = DOT3(ci, light->Diffuse); + light->_sli = DOT3(ci, light->Specular); + } + } +} + + +/* _NEW_MODELVIEW + * _NEW_LIGHT + * _TNL_NEW_NEED_EYE_COORDS + * + * Update on (_NEW_MODELVIEW | _NEW_LIGHT) when lighting is enabled. + * Also update on lighting space changes. + */ +static void +compute_light_positions( GLcontext *ctx ) +{ + struct gl_light *light; + static const GLfloat eye_z[3] = { 0, 0, 1 }; + + if (!ctx->Light.Enabled) + return; + + if (ctx->_NeedEyeCoords) { + COPY_3V( ctx->_EyeZDir, eye_z ); + } + else { + TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m ); + } + + foreach (light, &ctx->Light.EnabledList) { + + if (ctx->_NeedEyeCoords) { + COPY_4FV( light->_Position, light->EyePosition ); + } + else { + TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv, + light->EyePosition ); + } + + if (!(light->_Flags & LIGHT_POSITIONAL)) { + /* VP (VP) = Normalize( Position ) */ + COPY_3V( light->_VP_inf_norm, light->_Position ); + NORMALIZE_3FV( light->_VP_inf_norm ); + + if (!ctx->Light.Model.LocalViewer) { + /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */ + ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir); + NORMALIZE_3FV( light->_h_inf_norm ); + } + light->_VP_inf_spot_attenuation = 1.0; + } + + if (light->_Flags & LIGHT_SPOT) { + if (ctx->_NeedEyeCoords) { + COPY_3V( light->_NormDirection, light->EyeDirection ); + } + else { + TRANSFORM_NORMAL( light->_NormDirection, + light->EyeDirection, + ctx->ModelviewMatrixStack.Top->m); + } + + NORMALIZE_3FV( light->_NormDirection ); + + if (!(light->_Flags & LIGHT_POSITIONAL)) { + GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm, + light->_NormDirection); + + if (PV_dot_dir > light->_CosCutoff) { + double x = PV_dot_dir * (EXP_TABLE_SIZE-1); + int k = (int) x; + light->_VP_inf_spot_attenuation = + (GLfloat) (light->_SpotExpTable[k][0] + + (x-k)*light->_SpotExpTable[k][1]); + } + else { + light->_VP_inf_spot_attenuation = 0; + } + } + } + } +} + + + +static void +update_modelview_scale( GLcontext *ctx ) +{ + ctx->_ModelViewInvScale = 1.0F; + if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) { + const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv; + GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10]; + if (f < 1e-12) f = 1.0; + if (ctx->_NeedEyeCoords) + ctx->_ModelViewInvScale = (GLfloat) INV_SQRTF(f); + else + ctx->_ModelViewInvScale = (GLfloat) SQRTF(f); + } +} + + +/* Bring uptodate any state that relies on _NeedEyeCoords. + */ +void +_mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state ) +{ + const GLuint oldneedeyecoords = ctx->_NeedEyeCoords; + + (void) new_state; + ctx->_NeedEyeCoords = 0; + + if (ctx->_ForceEyeCoords || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) || + ctx->Point._Attenuated || + ctx->Light._NeedEyeCoords) + ctx->_NeedEyeCoords = 1; + + if (ctx->Light.Enabled && + !_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) + ctx->_NeedEyeCoords = 1; + + + /* Check if the truth-value interpretations of the bitfields have + * changed: + */ + if (oldneedeyecoords != ctx->_NeedEyeCoords) { + /* Recalculate all state that depends on _NeedEyeCoords. + */ + update_modelview_scale(ctx); + compute_light_positions( ctx ); + + if (ctx->Driver.LightingSpaceChange) + ctx->Driver.LightingSpaceChange( ctx ); + } + else { + GLuint new_state = ctx->NewState; + + /* Recalculate that same state only if it has been invalidated + * by other statechanges. + */ + if (new_state & _NEW_MODELVIEW) + update_modelview_scale(ctx); + + if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW)) + compute_light_positions( ctx ); + } +} + + +/* Drivers may need this if the hardware tnl unit doesn't support the + * light-in-modelspace optimization. It's also useful for debugging. + */ +void +_mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag ) +{ + ctx->_ForceEyeCoords = !flag; + ctx->NewState |= _NEW_POINT; /* one of the bits from + * _MESA_NEW_NEED_EYE_COORDS. + */ +} + + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +/** + * Initialize the n-th light data structure. + * + * \param l pointer to the gl_light structure to be initialized. + * \param n number of the light. + * \note The defaults for light 0 are different than the other lights. + */ +static void +init_light( struct gl_light *l, GLuint n ) +{ + make_empty_list( l ); + + ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 ); + if (n==0) { + ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 ); + ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 ); + } + else { + ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 ); + ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 ); + } + ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 ); + ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 ); + l->SpotExponent = 0.0; + _mesa_invalidate_spot_exp_table( l ); + l->SpotCutoff = 180.0; + l->_CosCutoff = 0.0; /* KW: -ve values not admitted */ + l->ConstantAttenuation = 1.0; + l->LinearAttenuation = 0.0; + l->QuadraticAttenuation = 0.0; + l->Enabled = GL_FALSE; +} + + +/** + * Initialize the light model data structure. + * + * \param lm pointer to the gl_lightmodel structure to be initialized. + */ +static void +init_lightmodel( struct gl_lightmodel *lm ) +{ + ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F ); + lm->LocalViewer = GL_FALSE; + lm->TwoSide = GL_FALSE; + lm->ColorControl = GL_SINGLE_COLOR; +} + + +/** + * Initialize the material data structure. + * + * \param m pointer to the gl_material structure to be initialized. + */ +static void +init_material( struct gl_material *m ) +{ + ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F ); + + ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT], 0.2F, 0.2F, 0.2F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE], 0.8F, 0.8F, 0.8F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F ); + ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F ); +} + + +void +_mesa_init_lighting( GLcontext *ctx ) +{ + GLuint i; + + /* Lighting group */ + for (i = 0; i < MAX_LIGHTS; i++) { + init_light( &ctx->Light.Light[i], i ); + } + make_empty_list( &ctx->Light.EnabledList ); + + init_lightmodel( &ctx->Light.Model ); + init_material( &ctx->Light.Material ); + ctx->Light.ShadeModel = GL_SMOOTH; + ctx->Light.Enabled = GL_FALSE; + ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK; + ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE; + ctx->Light.ColorMaterialBitmask = _mesa_material_bitmask( ctx, + GL_FRONT_AND_BACK, + GL_AMBIENT_AND_DIFFUSE, ~0, + NULL ); + + ctx->Light.ColorMaterialEnabled = GL_FALSE; + + /* Lighting miscellaneous */ + ctx->_ShineTabList = MALLOC_STRUCT( gl_shine_tab ); + make_empty_list( ctx->_ShineTabList ); + /* Allocate 10 (arbitrary) shininess lookup tables */ + for (i = 0 ; i < 10 ; i++) { + struct gl_shine_tab *s = MALLOC_STRUCT( gl_shine_tab ); + s->shininess = -1; + s->refcount = 0; + insert_at_tail( ctx->_ShineTabList, s ); + } + + /* Miscellaneous */ + ctx->Light._NeedEyeCoords = 0; + ctx->_NeedEyeCoords = 0; + ctx->_ModelViewInvScale = 1.0; +} + + +void +_mesa_free_lighting_data( GLcontext *ctx ) +{ + struct gl_shine_tab *s, *tmps; + + /* Free lighting shininess exponentiation table */ + foreach_s( s, tmps, ctx->_ShineTabList ) { + FREE( s ); + } + FREE( ctx->_ShineTabList ); +} diff --git a/src/mesa/main/light.h b/src/mesa/main/light.h new file mode 100644 index 00000000000..1f19019450f --- /dev/null +++ b/src/mesa/main/light.h @@ -0,0 +1,141 @@ +/** + * \file light.h + * Lighting. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef LIGHT_H +#define LIGHT_H + + +#include "mtypes.h" + +extern void GLAPIENTRY +_mesa_ShadeModel( GLenum mode ); + +#if _HAVE_FULL_GL +extern void GLAPIENTRY +_mesa_ColorMaterial( GLenum face, GLenum mode ); + +extern void GLAPIENTRY +_mesa_Lightf( GLenum light, GLenum pname, GLfloat param ); + +extern void GLAPIENTRY +_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params ); + +extern void GLAPIENTRY +_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params ); + +extern void GLAPIENTRY +_mesa_Lighti( GLenum light, GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_LightModelf( GLenum pname, GLfloat param ); + +extern void GLAPIENTRY +_mesa_LightModelfv( GLenum pname, const GLfloat *params ); + +extern void GLAPIENTRY +_mesa_LightModeli( GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_LightModeliv( GLenum pname, const GLint *params ); + +extern void GLAPIENTRY +_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params ); + +extern void GLAPIENTRY +_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params ); + + +/* Lerp between adjacent values in the f(x) lookup table, giving a + * continuous function, with adequeate overall accuracy. (Though + * still pretty good compared to a straight lookup). + * Result should be a GLfloat. + */ +#define GET_SHINE_TAB_ENTRY( table, dp, result ) \ +do { \ + struct gl_shine_tab *_tab = table; \ + float f = (dp * (SHINE_TABLE_SIZE-1)); \ + int k = (int) f; \ + if (k > SHINE_TABLE_SIZE-2) \ + result = (GLfloat) _mesa_pow( dp, _tab->shininess ); \ + else \ + result = _tab->tab[k] + (f-k)*(_tab->tab[k+1]-_tab->tab[k]); \ +} while (0) + + +extern GLuint _mesa_material_bitmask( GLcontext *ctx, + GLenum face, GLenum pname, + GLuint legal, + const char * ); + +extern void _mesa_invalidate_spot_exp_table( struct gl_light *l ); + +extern void _mesa_invalidate_shine_table( GLcontext *ctx, GLuint i ); + +extern void _mesa_validate_all_lighting_tables( GLcontext *ctx ); + +extern void _mesa_update_lighting( GLcontext *ctx ); + +extern void _mesa_update_tnl_spaces( GLcontext *ctx, GLuint new_state ); + +extern void _mesa_update_material( GLcontext *ctx, + GLuint bitmask ); + +extern void _mesa_copy_materials( struct gl_material *dst, + const struct gl_material *src, + GLuint bitmask ); + +extern void _mesa_update_color_material( GLcontext *ctx, + const GLfloat rgba[4] ); + +extern void _mesa_init_lighting( GLcontext *ctx ); + +extern void _mesa_free_lighting_data( GLcontext *ctx ); + +extern void _mesa_allow_light_in_model( GLcontext *ctx, GLboolean flag ); + +#else +#define _mesa_update_color_material( c, r ) ((void)0) +#define _mesa_validate_all_lighting_tables( c ) ((void)0) +#define _mesa_invalidate_spot_exp_table( l ) ((void)0) +#define _mesa_material_bitmask( c, f, p, l, s ) 0 +#define _mesa_init_lighting( c ) ((void)0) +#define _mesa_free_lighting_data( c ) ((void)0) +#define _mesa_update_lighting( c ) ((void)0) +#define _mesa_update_tnl_spaces( c, n ) ((void)0) +#define GET_SHINE_TAB_ENTRY( table, dp, result ) ((result)=0) +#endif + +#endif diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c new file mode 100644 index 00000000000..c30d9ac109e --- /dev/null +++ b/src/mesa/main/lines.c @@ -0,0 +1,134 @@ +/** + * \file lines.c + * Line operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "depth.h" +#include "lines.h" +#include "macros.h" +#include "texstate.h" +#include "mtypes.h" + + +/** + * Set the line width. + * + * \param width line width in pixels. + * + * \sa glLineWidth(). + * + * Verifies the parameter and updates gl_line_attrib::Width. On a change, + * flushes the vertices, updates the clamped line width and marks the + * DD_LINE_WIDTH flag in __GLcontextRec::_TriangleCaps for the drivers if the + * width is different from one. Notifies the driver via the + * dd_function_table::LineWidth callback. + */ +void GLAPIENTRY +_mesa_LineWidth( GLfloat width ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (width<=0.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); + return; + } + + if (ctx->Line.Width == width) + return; + + FLUSH_VERTICES(ctx, _NEW_LINE); + ctx->Line.Width = width; + ctx->Line._Width = CLAMP(width, + ctx->Const.MinLineWidth, + ctx->Const.MaxLineWidth); + + + if (width != 1.0) + ctx->_TriangleCaps |= DD_LINE_WIDTH; + else + ctx->_TriangleCaps &= ~DD_LINE_WIDTH; + + if (ctx->Driver.LineWidth) + (*ctx->Driver.LineWidth)(ctx, width); +} + + +/** + * Set the line stipple pattern. + * + * \param factor pattern scale factor. + * \param pattern bit pattern. + * + * \sa glLineStipple(). + * + * Updates gl_line_attrib::StippleFactor and gl_line_attrib::StipplePattern. On + * change flushes the vertices and notifies the driver via + * the dd_function_table::LineStipple callback. + */ +void GLAPIENTRY +_mesa_LineStipple( GLint factor, GLushort pattern ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + factor = CLAMP( factor, 1, 256 ); + + if (ctx->Line.StippleFactor == factor && + ctx->Line.StipplePattern == pattern) + return; + + FLUSH_VERTICES(ctx, _NEW_LINE); + ctx->Line.StippleFactor = factor; + ctx->Line.StipplePattern = pattern; + + if (ctx->Driver.LineStipple) + ctx->Driver.LineStipple( ctx, factor, pattern ); +} + + +/** + * Initialize the context line state. + * + * \param ctx GL context. + * + * Initializes __GLcontextRec::Line and line related constants in + * __GLcontextRec::Const. + */ +void GLAPIENTRY _mesa_init_line( GLcontext * ctx ) +{ + /* Line group */ + ctx->Line.SmoothFlag = GL_FALSE; + ctx->Line.StippleFlag = GL_FALSE; + ctx->Line.Width = 1.0; + ctx->Line._Width = 1.0; + ctx->Line.StipplePattern = 0xffff; + ctx->Line.StippleFactor = 1; +} diff --git a/src/mesa/main/lines.h b/src/mesa/main/lines.h new file mode 100644 index 00000000000..5a47e9858d5 --- /dev/null +++ b/src/mesa/main/lines.h @@ -0,0 +1,48 @@ +/** + * \file lines.h + * Line operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef LINES_H +#define LINES_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_LineWidth( GLfloat width ); + +extern void GLAPIENTRY +_mesa_LineStipple( GLint factor, GLushort pattern ); + +extern void GLAPIENTRY +_mesa_init_line( GLcontext * ctx ); + +#endif diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h new file mode 100644 index 00000000000..f13357d391b --- /dev/null +++ b/src/mesa/main/macros.h @@ -0,0 +1,657 @@ +/** + * \file macros.h + * A collection of useful macros. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.0 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef MACROS_H +#define MACROS_H + +#include "imports.h" + + +/** + * \name Integer / float conversion for colors, normals, etc. + */ +/*@{*/ + +/** Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */ +extern GLfloat _mesa_ubyte_to_float_color_tab[256]; +#define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)] + +/** Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */ +#define FLOAT_TO_UBYTE(X) ((GLubyte) (GLint) ((X) * 255.0F)) + + +/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */ +#define BYTE_TO_FLOAT(B) ((2.0F * (B) + 1.0F) * (1.0F/255.0F)) + +/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */ +#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 ) + + +/** Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */ +#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F)) + +/** Convert GLfloat in [0.0,1.0] to GLushort in [0,65536] */ +#define FLOAT_TO_USHORT(X) ((GLushort) (GLint) ((X) * 65535.0F)) + +/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */ +#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) + +/** Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */ +#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 ) + + +/** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */ +#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0F)) + +/** Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */ +#define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0)) + + +/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */ +#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F)) + +/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */ +/* causes overflow: +#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0F * (X))) - 1) / 2 ) +*/ +/* a close approximation: */ +#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) ) + + +#define BYTE_TO_UBYTE(b) ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b))) +#define SHORT_TO_UBYTE(s) ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7))) +#define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8)) +#define INT_TO_UBYTE(i) ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23))) +#define UINT_TO_UBYTE(i) ((GLubyte) ((i) >> 24)) + + +#define BYTE_TO_USHORT(b) ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255))) +#define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b)) +#define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767)))) +#define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15))) +#define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) +#define UNCLAMPED_FLOAT_TO_USHORT(us, f) \ + us = ( (GLushort) IROUND( CLAMP((f), 0.0, 1.0) * 65535.0F) ) +#define CLAMPED_FLOAT_TO_USHORT(us, f) \ + us = ( (GLushort) IROUND( (f) * 65535.0F) ) + +/*@}*/ + + +/** Stepping a GLfloat pointer by a byte stride */ +#define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i)) +/** Stepping a GLuint pointer by a byte stride */ +#define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i)) +/** Stepping a GLubyte[4] pointer by a byte stride */ +#define STRIDE_4UB(p, i) (p = (GLubyte (*)[4])((GLubyte *)p + i)) +/** Stepping a GLfloat[4] pointer by a byte stride */ +#define STRIDE_4F(p, i) (p = (GLfloat (*)[4])((GLubyte *)p + i)) +/** Stepping a GLchan[4] pointer by a byte stride */ +#define STRIDE_4CHAN(p, i) (p = (GLchan (*)[4])((GLubyte *)p + i)) +/** Stepping a GLchan pointer by a byte stride */ +#define STRIDE_CHAN(p, i) (p = (GLchan *)((GLubyte *)p + i)) +/** Stepping a \p t pointer by a byte stride */ +#define STRIDE_T(p, t, i) (p = (t)((GLubyte *)p + i)) + + +/**********************************************************************/ +/** \name 4-element vector operations */ +/*@{*/ + +/** Zero */ +#define ZERO_4V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0 + +/** Test for equality */ +#define TEST_EQ_4V(a,b) ((a)[0] == (b)[0] && \ + (a)[1] == (b)[1] && \ + (a)[2] == (b)[2] && \ + (a)[3] == (b)[3]) + +/** Test for equality (unsigned bytes) */ +#if defined(__i386__) +#define TEST_EQ_4UBV(DST, SRC) *((GLuint*)(DST)) == *((GLuint*)(SRC)) +#else +#define TEST_EQ_4UBV(DST, SRC) TEST_EQ_4V(DST, SRC) +#endif + +/** Copy a 4-element vector */ +#define COPY_4V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ + (DST)[3] = (SRC)[3]; \ +} while (0) + +/** Copy a 4-element vector with cast */ +#define COPY_4V_CAST( DST, SRC, CAST ) \ +do { \ + (DST)[0] = (CAST)(SRC)[0]; \ + (DST)[1] = (CAST)(SRC)[1]; \ + (DST)[2] = (CAST)(SRC)[2]; \ + (DST)[3] = (CAST)(SRC)[3]; \ +} while (0) + +/** Copy a 4-element unsigned byte vector */ +#if defined(__i386__) +#define COPY_4UBV(DST, SRC) \ +do { \ + *((GLuint*)(DST)) = *((GLuint*)(SRC)); \ +} while (0) +#else +/* The GLuint cast might fail if DST or SRC are not dword-aligned (RISC) */ +#define COPY_4UBV(DST, SRC) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ + (DST)[3] = (SRC)[3]; \ +} while (0) +#endif + +/** Copy a 4-element float vector (Use COPY_FLOAT to avoid loading FPU) */ +#define COPY_4FV( DST, SRC ) \ +do { \ + COPY_FLOAT((DST)[0], (SRC)[0]); \ + COPY_FLOAT((DST)[1], (SRC)[1]); \ + COPY_FLOAT((DST)[2], (SRC)[2]); \ + COPY_FLOAT((DST)[3], (SRC)[3]); \ +} while (0) + + +/** Copy \p SZ elements into a 4-element vector */ +#define COPY_SZ_4V(DST, SZ, SRC) \ +do { \ + switch (SZ) { \ + case 4: (DST)[3] = (SRC)[3]; \ + case 3: (DST)[2] = (SRC)[2]; \ + case 2: (DST)[1] = (SRC)[1]; \ + case 1: (DST)[0] = (SRC)[0]; \ + } \ +} while(0) + +/** Copy \p SZ elements into a homegeneous (4-element) vector, giving + * default values to the remaining */ +#define COPY_CLEAN_4V(DST, SZ, SRC) \ +do { \ + ASSIGN_4V( DST, 0, 0, 0, 1 ); \ + COPY_SZ_4V( DST, SZ, SRC ); \ +} while (0) + +/** Subtraction */ +#define SUB_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ + (DST)[3] = (SRCA)[3] - (SRCB)[3]; \ +} while (0) + +/** Addition */ +#define ADD_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ + (DST)[3] = (SRCA)[3] + (SRCB)[3]; \ +} while (0) + +/** Element-wise multiplication */ +#define SCALE_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ + (DST)[3] = (SRCA)[3] * (SRCB)[3]; \ +} while (0) + +/** In-place addition */ +#define ACC_4V( DST, SRC ) \ +do { \ + (DST)[0] += (SRC)[0]; \ + (DST)[1] += (SRC)[1]; \ + (DST)[2] += (SRC)[2]; \ + (DST)[3] += (SRC)[3]; \ +} while (0) + +/** Element-wise multiplication and addition */ +#define ACC_SCALE_4V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ + (DST)[3] += (SRCA)[3] * (SRCB)[3]; \ +} while (0) + +/** In-place scalar multiplication and addition */ +#define ACC_SCALE_SCALAR_4V( DST, S, SRCB ) \ +do { \ + (DST)[0] += S * (SRCB)[0]; \ + (DST)[1] += S * (SRCB)[1]; \ + (DST)[2] += S * (SRCB)[2]; \ + (DST)[3] += S * (SRCB)[3]; \ +} while (0) + +/** Scalar multiplication */ +#define SCALE_SCALAR_4V( DST, S, SRCB ) \ +do { \ + (DST)[0] = S * (SRCB)[0]; \ + (DST)[1] = S * (SRCB)[1]; \ + (DST)[2] = S * (SRCB)[2]; \ + (DST)[3] = S * (SRCB)[3]; \ +} while (0) + +/** In-place scalar multiplication */ +#define SELF_SCALE_SCALAR_4V( DST, S ) \ +do { \ + (DST)[0] *= S; \ + (DST)[1] *= S; \ + (DST)[2] *= S; \ + (DST)[3] *= S; \ +} while (0) + +/** Assignment */ +#define ASSIGN_4V( V, V0, V1, V2, V3 ) \ +do { \ + V[0] = V0; \ + V[1] = V1; \ + V[2] = V2; \ + V[3] = V3; \ +} while(0) + +/*@}*/ + + +/**********************************************************************/ +/** \name 3-element vector operations*/ +/*@{*/ + +/** Zero */ +#define ZERO_3V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = 0 + +/** Test for equality */ +#define TEST_EQ_3V(a,b) \ + ((a)[0] == (b)[0] && \ + (a)[1] == (b)[1] && \ + (a)[2] == (b)[2]) + +/** Copy a 3-element vector */ +#define COPY_3V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ +} while (0) + +/** Copy a 3-element vector with cast */ +#define COPY_3V_CAST( DST, SRC, CAST ) \ +do { \ + (DST)[0] = (CAST)(SRC)[0]; \ + (DST)[1] = (CAST)(SRC)[1]; \ + (DST)[2] = (CAST)(SRC)[2]; \ +} while (0) + +/** Copy a 3-element float vector */ +#define COPY_3FV( DST, SRC ) \ +do { \ + const GLfloat *_tmp = (SRC); \ + (DST)[0] = _tmp[0]; \ + (DST)[1] = _tmp[1]; \ + (DST)[2] = _tmp[2]; \ +} while (0) + +/** Subtraction */ +#define SUB_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ +} while (0) + +/** Addition */ +#define ADD_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ +} while (0) + +/** In-place scalar multiplication */ +#define SCALE_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ +} while (0) + +/** In-place element-wise multiplication */ +#define SELF_SCALE_3V( DST, SRC ) \ +do { \ + (DST)[0] *= (SRC)[0]; \ + (DST)[1] *= (SRC)[1]; \ + (DST)[2] *= (SRC)[2]; \ +} while (0) + +/** In-place addition */ +#define ACC_3V( DST, SRC ) \ +do { \ + (DST)[0] += (SRC)[0]; \ + (DST)[1] += (SRC)[1]; \ + (DST)[2] += (SRC)[2]; \ +} while (0) + +/** Element-wise multiplication and addition */ +#define ACC_SCALE_3V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ + (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ +} while (0) + +/** Scalar multiplication */ +#define SCALE_SCALAR_3V( DST, S, SRCB ) \ +do { \ + (DST)[0] = S * (SRCB)[0]; \ + (DST)[1] = S * (SRCB)[1]; \ + (DST)[2] = S * (SRCB)[2]; \ +} while (0) + +/** In-place scalar multiplication and addition */ +#define ACC_SCALE_SCALAR_3V( DST, S, SRCB ) \ +do { \ + (DST)[0] += S * (SRCB)[0]; \ + (DST)[1] += S * (SRCB)[1]; \ + (DST)[2] += S * (SRCB)[2]; \ +} while (0) + +/** In-place scalar multiplication */ +#define SELF_SCALE_SCALAR_3V( DST, S ) \ +do { \ + (DST)[0] *= S; \ + (DST)[1] *= S; \ + (DST)[2] *= S; \ +} while (0) + +/** In-place scalar addition */ +#define ACC_SCALAR_3V( DST, S ) \ +do { \ + (DST)[0] += S; \ + (DST)[1] += S; \ + (DST)[2] += S; \ +} while (0) + +/** Assignment */ +#define ASSIGN_3V( V, V0, V1, V2 ) \ +do { \ + V[0] = V0; \ + V[1] = V1; \ + V[2] = V2; \ +} while(0) + +/*@}*/ + + +/**********************************************************************/ +/** \name 2-element vector operations*/ +/*@{*/ + +/** Zero */ +#define ZERO_2V( DST ) (DST)[0] = (DST)[1] = 0 + +/** Copy a 2-element vector */ +#define COPY_2V( DST, SRC ) \ +do { \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ +} while (0) + +/** Copy a 2-element vector with cast */ +#define COPY_2V_CAST( DST, SRC, CAST ) \ +do { \ + (DST)[0] = (CAST)(SRC)[0]; \ + (DST)[1] = (CAST)(SRC)[1]; \ +} while (0) + +/** Copy a 2-element float vector */ +#define COPY_2FV( DST, SRC ) \ +do { \ + const GLfloat *_tmp = (SRC); \ + (DST)[0] = _tmp[0]; \ + (DST)[1] = _tmp[1]; \ +} while (0) + +/** Subtraction */ +#define SUB_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ +} while (0) + +/** Addition */ +#define ADD_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ +} while (0) + +/** In-place scalar multiplication */ +#define SCALE_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ +} while (0) + +/** In-place addition */ +#define ACC_2V( DST, SRC ) \ +do { \ + (DST)[0] += (SRC)[0]; \ + (DST)[1] += (SRC)[1]; \ +} while (0) + +/** Element-wise multiplication and addition */ +#define ACC_SCALE_2V( DST, SRCA, SRCB ) \ +do { \ + (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ + (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ +} while (0) + +/** Scalar multiplication */ +#define SCALE_SCALAR_2V( DST, S, SRCB ) \ +do { \ + (DST)[0] = S * (SRCB)[0]; \ + (DST)[1] = S * (SRCB)[1]; \ +} while (0) + +/** In-place scalar multiplication and addition */ +#define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \ +do { \ + (DST)[0] += S * (SRCB)[0]; \ + (DST)[1] += S * (SRCB)[1]; \ +} while (0) + +/** In-place scalar multiplication */ +#define SELF_SCALE_SCALAR_2V( DST, S ) \ +do { \ + (DST)[0] *= S; \ + (DST)[1] *= S; \ +} while (0) + +/** In-place scalar addition */ +#define ACC_SCALAR_2V( DST, S ) \ +do { \ + (DST)[0] += S; \ + (DST)[1] += S; \ +} while (0) + + + +/** + * Linear interpolation + * + * \note \p OUT argument is evaluated twice! + * \note Be wary of using *coord++ as an argument to any of these macros! + */ +#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT))) + +/* Can do better with integer math + */ +#define INTERP_UB( t, dstub, outub, inub ) \ +do { \ + GLfloat inf = UBYTE_TO_FLOAT( inub ); \ + GLfloat outf = UBYTE_TO_FLOAT( outub ); \ + GLfloat dstf = LINTERP( t, outf, inf ); \ + UNCLAMPED_FLOAT_TO_UBYTE( dstub, dstf ); \ +} while (0) + +#define INTERP_CHAN( t, dstc, outc, inc ) \ +do { \ + GLfloat inf = CHAN_TO_FLOAT( inc ); \ + GLfloat outf = CHAN_TO_FLOAT( outc ); \ + GLfloat dstf = LINTERP( t, outf, inf ); \ + UNCLAMPED_FLOAT_TO_CHAN( dstc, dstf ); \ +} while (0) + +#define INTERP_UI( t, dstui, outui, inui ) \ + dstui = (GLuint) (GLint) LINTERP( (t), (GLfloat) (outui), (GLfloat) (inui) ) + +#define INTERP_F( t, dstf, outf, inf ) \ + dstf = LINTERP( t, outf, inf ) + +#define INTERP_4F( t, dst, out, in ) \ +do { \ + dst[0] = LINTERP( (t), (out)[0], (in)[0] ); \ + dst[1] = LINTERP( (t), (out)[1], (in)[1] ); \ + dst[2] = LINTERP( (t), (out)[2], (in)[2] ); \ + dst[3] = LINTERP( (t), (out)[3], (in)[3] ); \ +} while (0) + +#define INTERP_3F( t, dst, out, in ) \ +do { \ + dst[0] = LINTERP( (t), (out)[0], (in)[0] ); \ + dst[1] = LINTERP( (t), (out)[1], (in)[1] ); \ + dst[2] = LINTERP( (t), (out)[2], (in)[2] ); \ +} while (0) + +#define INTERP_4CHAN( t, dst, out, in ) \ +do { \ + INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] ); \ + INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] ); \ + INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] ); \ + INTERP_CHAN( (t), (dst)[3], (out)[3], (in)[3] ); \ +} while (0) + +#define INTERP_3CHAN( t, dst, out, in ) \ +do { \ + INTERP_CHAN( (t), (dst)[0], (out)[0], (in)[0] ); \ + INTERP_CHAN( (t), (dst)[1], (out)[1], (in)[1] ); \ + INTERP_CHAN( (t), (dst)[2], (out)[2], (in)[2] ); \ +} while (0) + +#define INTERP_SZ( t, vec, to, out, in, sz ) \ +do { \ + switch (sz) { \ + case 4: vec[to][3] = LINTERP( (t), (vec)[out][3], (vec)[in][3] ); \ + case 3: vec[to][2] = LINTERP( (t), (vec)[out][2], (vec)[in][2] ); \ + case 2: vec[to][1] = LINTERP( (t), (vec)[out][1], (vec)[in][1] ); \ + case 1: vec[to][0] = LINTERP( (t), (vec)[out][0], (vec)[in][0] ); \ + } \ +} while(0) + + + +/** Assign scalers to short vectors */ +#define ASSIGN_2V( V, V0, V1 ) \ +do { \ + V[0] = V0; \ + V[1] = V1; \ +} while(0) + +/*@}*/ + + + +/** Clamp X to [MIN,MAX] */ +#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) + +/** Assign X to CLAMP(X, MIN, MAX) */ +#define CLAMP_SELF(x, mn, mx) \ + ( (x)<(mn) ? ((x) = (mn)) : ((x)>(mx) ? ((x)=(mx)) : (x)) ) + + + +/** Minimum of two values: */ +#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) + +/** Maximum of two values: */ +#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) + +/** Dot product of two 2-element vectors */ +#define DOT2( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] ) + +/** Dot product of two 3-element vectors */ +#define DOT3( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] ) + +/** Dot product of two 4-element vectors */ +#define DOT4( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + \ + (a)[2]*(b)[2] + (a)[3]*(b)[3] ) + +/** Dot product of two 4-element vectors */ +#define DOT4V(v,a,b,c,d) (v[0]*(a) + v[1]*(b) + v[2]*(c) + v[3]*(d)) + + +/** Cross product of two 3-element vectors */ +#define CROSS3(n, u, v) \ +do { \ + (n)[0] = (u)[1]*(v)[2] - (u)[2]*(v)[1]; \ + (n)[1] = (u)[2]*(v)[0] - (u)[0]*(v)[2]; \ + (n)[2] = (u)[0]*(v)[1] - (u)[1]*(v)[0]; \ +} while (0) + + +/* Normalize a 3-element vector to unit length. */ +#define NORMALIZE_3FV( V ) \ +do { \ + GLfloat len = (GLfloat) LEN_SQUARED_3FV(V); \ + if (len) { \ + len = INV_SQRTF(len); \ + (V)[0] = (GLfloat) ((V)[0] * len); \ + (V)[1] = (GLfloat) ((V)[1] * len); \ + (V)[2] = (GLfloat) ((V)[2] * len); \ + } \ +} while(0) + +#define LEN_3FV( V ) (SQRTF((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2])) +#define LEN_2FV( V ) (SQRTF((V)[0]*(V)[0]+(V)[1]*(V)[1])) + +#define LEN_SQUARED_3FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2]) +#define LEN_SQUARED_2FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]) + + +#endif diff --git a/src/mesa/main/matrix.c b/src/mesa/main/matrix.c new file mode 100644 index 00000000000..f4ec9735630 --- /dev/null +++ b/src/mesa/main/matrix.c @@ -0,0 +1,943 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file matrix.c + * Matrix operations. + * + * \note + * -# 4x4 transformation matrices are stored in memory in column major order. + * -# Points/vertices are to be thought of as column vectors. + * -# Transformation of a point p by a matrix M is: p' = M * p + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "enums.h" +#include "macros.h" +#include "matrix.h" +#include "mtypes.h" +#include "math/m_matrix.h" +#include "math/m_xform.h" + + +/** + * Apply a perspective projection matrix. + * + * \param left left clipping plane coordinate. + * \param right right clipping plane coordinate. + * \param bottom bottom clipping plane coordinate. + * \param top top clipping plane coordinate. + * \param nearval distance to the near clipping plane. + * \param farval distance to the far clipping plane. + * + * \sa glFrustum(). + * + * Flushes vertices and validates parameters. Calls _math_matrix_frustum() with + * the top matrix of the current matrix stack and sets + * __GLcontextRec::NewState. + */ +void GLAPIENTRY +_mesa_Frustum( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (nearval <= 0.0 || + farval <= 0.0 || + nearval == farval || + left == right || + top == bottom) + { + _mesa_error( ctx, GL_INVALID_VALUE, "glFrustum" ); + return; + } + + _math_matrix_frustum( ctx->CurrentStack->Top, + (GLfloat) left, (GLfloat) right, + (GLfloat) bottom, (GLfloat) top, + (GLfloat) nearval, (GLfloat) farval ); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +/** + * Apply an orthographic projection matrix. + * + * \param left left clipping plane coordinate. + * \param right right clipping plane coordinate. + * \param bottom bottom clipping plane coordinate. + * \param top top clipping plane coordinate. + * \param nearval distance to the near clipping plane. + * \param farval distance to the far clipping plane. + * + * \sa glOrtho(). + * + * Flushes vertices and validates parameters. Calls _math_matrix_ortho() with + * the top matrix of the current matrix stack and sets + * __GLcontextRec::NewState. + */ +void GLAPIENTRY +_mesa_Ortho( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glOrtho(%f, %f, %f, %f, %f, %f)\n", + left, right, bottom, top, nearval, farval); + + if (left == right || + bottom == top || + nearval == farval) + { + _mesa_error( ctx, GL_INVALID_VALUE, "glOrtho" ); + return; + } + + _math_matrix_ortho( ctx->CurrentStack->Top, + (GLfloat) left, (GLfloat) right, + (GLfloat) bottom, (GLfloat) top, + (GLfloat) nearval, (GLfloat) farval ); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +/** + * Set the current matrix stack. + * + * \param mode matrix stack. + * + * \sa glMatrixMode(). + * + * Flushes the vertices, validates the parameter and updates + * __GLcontextRec::CurrentStack and gl_transform_attrib::MatrixMode with the + * specified matrix stack. + */ +void GLAPIENTRY +_mesa_MatrixMode( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->Transform.MatrixMode == mode && mode != GL_TEXTURE) + return; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + + switch (mode) { + case GL_MODELVIEW: + ctx->CurrentStack = &ctx->ModelviewMatrixStack; + break; + case GL_PROJECTION: + ctx->CurrentStack = &ctx->ProjectionMatrixStack; + break; + case GL_TEXTURE: + ctx->CurrentStack = &ctx->TextureMatrixStack[ctx->Texture.CurrentUnit]; + break; + case GL_COLOR: + ctx->CurrentStack = &ctx->ColorMatrixStack; + break; + case GL_MATRIX0_NV: + case GL_MATRIX1_NV: + case GL_MATRIX2_NV: + case GL_MATRIX3_NV: + case GL_MATRIX4_NV: + case GL_MATRIX5_NV: + case GL_MATRIX6_NV: + case GL_MATRIX7_NV: + if (ctx->Extensions.NV_vertex_program) { + ctx->CurrentStack = &ctx->ProgramMatrixStack[mode - GL_MATRIX0_NV]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glMatrixMode(mode)" ); + return; + } + break; + case GL_MATRIX0_ARB: + case GL_MATRIX1_ARB: + case GL_MATRIX2_ARB: + case GL_MATRIX3_ARB: + case GL_MATRIX4_ARB: + case GL_MATRIX5_ARB: + case GL_MATRIX6_ARB: + case GL_MATRIX7_ARB: + if (ctx->Extensions.ARB_vertex_program || + ctx->Extensions.ARB_fragment_program) { + const GLuint m = mode - GL_MATRIX0_ARB; + if (m > ctx->Const.MaxProgramMatrices) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glMatrixMode(GL_MATRIX%d_ARB)", m); + return; + } + ctx->CurrentStack = &ctx->ProgramMatrixStack[m]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glMatrixMode(mode)" ); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glMatrixMode(mode)" ); + return; + } + + ctx->Transform.MatrixMode = mode; +} + + +/** + * Push the current matrix stack. + * + * \sa glPushMatrix(). + * + * Verifies the current matrix stack is not full, and duplicates the top-most + * matrix in the stack. Marks __GLcontextRec::NewState with the stack dirty + * flag. + */ +void GLAPIENTRY +_mesa_PushMatrix( void ) +{ + GET_CURRENT_CONTEXT(ctx); + struct matrix_stack *stack = ctx->CurrentStack; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glPushMatrix %s\n", + _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + + if (stack->Depth + 1 >= stack->MaxDepth) { + if (ctx->Transform.MatrixMode == GL_TEXTURE) { + _mesa_error(ctx, GL_STACK_OVERFLOW, + "glPushMatrix(mode=GL_TEXTURE, unit=%d)", + ctx->Texture.CurrentUnit); + } + else { + _mesa_error(ctx, GL_STACK_OVERFLOW, "glPushMatrix(mode=%s)", + _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + } + return; + } + _math_matrix_copy( &stack->Stack[stack->Depth + 1], + &stack->Stack[stack->Depth] ); + stack->Depth++; + stack->Top = &(stack->Stack[stack->Depth]); + ctx->NewState |= stack->DirtyFlag; +} + + +/** + * Pop the current matrix stack. + * + * \sa glPopMatrix(). + * + * Flushes the vertices, verifies the current matrix stack is not empty, and + * moves the stack head down. Marks __GLcontextRec::NewState with the dirty + * stack flag. + */ +void GLAPIENTRY +_mesa_PopMatrix( void ) +{ + GET_CURRENT_CONTEXT(ctx); + struct matrix_stack *stack = ctx->CurrentStack; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glPopMatrix %s\n", + _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + + if (stack->Depth == 0) { + if (ctx->Transform.MatrixMode == GL_TEXTURE) { + _mesa_error(ctx, GL_STACK_UNDERFLOW, + "glPopMatrix(mode=GL_TEXTURE, unit=%d)", + ctx->Texture.CurrentUnit); + } + else { + _mesa_error(ctx, GL_STACK_UNDERFLOW, "glPopMatrix(mode=%s)", + _mesa_lookup_enum_by_nr(ctx->Transform.MatrixMode)); + } + return; + } + stack->Depth--; + stack->Top = &(stack->Stack[stack->Depth]); + ctx->NewState |= stack->DirtyFlag; +} + + +/** + * Replace the current matrix with the identity matrix. + * + * \sa glLoadIdentity(). + * + * Flushes the vertices and calls _math_matrix_set_identity() with the top-most + * matrix in the current stack. Marks __GLcontextRec::NewState with the stack + * dirty flag. + */ +void GLAPIENTRY +_mesa_LoadIdentity( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLoadIdentity()"); + + _math_matrix_set_identity( ctx->CurrentStack->Top ); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +/** + * Replace the current matrix with a given matrix. + * + * \param m matrix. + * + * \sa glLoadMatrixf(). + * + * Flushes the vertices and calls _math_matrix_loadf() with the top-most matrix + * in the current stack and the given matrix. Marks __GLcontextRec::NewState + * with the dirty stack flag. + */ +void GLAPIENTRY +_mesa_LoadMatrixf( const GLfloat *m ) +{ + GET_CURRENT_CONTEXT(ctx); + if (!m) return; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glLoadMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n", + m[0], m[4], m[8], m[12], + m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15]); + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _math_matrix_loadf( ctx->CurrentStack->Top, m ); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +/** + * Multiply the current matrix with a given matrix. + * + * \param m matrix. + * + * \sa glMultMatrixf(). + * + * Flushes the vertices and calls _math_matrix_mul_floats() with the top-most + * matrix in the current stack and the given matrix. Marks + * __GLcontextRec::NewState with the dirty stack flag. + */ +void GLAPIENTRY +_mesa_MultMatrixf( const GLfloat *m ) +{ + GET_CURRENT_CONTEXT(ctx); + if (!m) return; + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glMultMatrix(%f %f %f %f, %f %f %f %f, %f %f %f %f, %f %f %f %f\n", + m[0], m[4], m[8], m[12], + m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15]); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _math_matrix_mul_floats( ctx->CurrentStack->Top, m ); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +/** + * Multiply the current matrix with a rotation matrix. + * + * \param angle angle of rotation, in degrees. + * \param x rotation vector x coordinate. + * \param y rotation vector y coordinate. + * \param z rotation vector z coordinate. + * + * \sa glRotatef(). + * + * Flushes the vertices and calls _math_matrix_rotate() with the top-most + * matrix in the current stack and the given parameters. Marks + * __GLcontextRec::NewState with the dirty stack flag. + */ +void GLAPIENTRY +_mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + if (angle != 0.0F) { + _math_matrix_rotate( ctx->CurrentStack->Top, angle, x, y, z); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; + } +} + + +/** + * Multiply the current matrix with a general scaling matrix. + * + * \param x x axis scale factor. + * \param y y axis scale factor. + * \param z z axis scale factor. + * + * \sa glScalef(). + * + * Flushes the vertices and calls _math_matrix_scale() with the top-most + * matrix in the current stack and the given parameters. Marks + * __GLcontextRec::NewState with the dirty stack flag. + */ +void GLAPIENTRY +_mesa_Scalef( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _math_matrix_scale( ctx->CurrentStack->Top, x, y, z); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +/** + * Multiply the current matrix with a general scaling matrix. + * + * \param x translation vector x coordinate. + * \param y translation vector y coordinate. + * \param z translation vector z coordinate. + * + * \sa glTranslatef(). + * + * Flushes the vertices and calls _math_matrix_translate() with the top-most + * matrix in the current stack and the given parameters. Marks + * __GLcontextRec::NewState with the dirty stack flag. + */ +void GLAPIENTRY +_mesa_Translatef( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _math_matrix_translate( ctx->CurrentStack->Top, x, y, z); + ctx->NewState |= ctx->CurrentStack->DirtyFlag; +} + + +#if _HAVE_FULL_GL +void GLAPIENTRY +_mesa_LoadMatrixd( const GLdouble *m ) +{ + GLint i; + GLfloat f[16]; + if (!m) return; + for (i = 0; i < 16; i++) + f[i] = (GLfloat) m[i]; + _mesa_LoadMatrixf(f); +} + +void GLAPIENTRY +_mesa_MultMatrixd( const GLdouble *m ) +{ + GLint i; + GLfloat f[16]; + if (!m) return; + for (i = 0; i < 16; i++) + f[i] = (GLfloat) m[i]; + _mesa_MultMatrixf( f ); +} + + +void GLAPIENTRY +_mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ) +{ + _mesa_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z); +} + + +void GLAPIENTRY +_mesa_Scaled( GLdouble x, GLdouble y, GLdouble z ) +{ + _mesa_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z); +} + + +void GLAPIENTRY +_mesa_Translated( GLdouble x, GLdouble y, GLdouble z ) +{ + _mesa_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z); +} +#endif + + +#if _HAVE_FULL_GL +void GLAPIENTRY +_mesa_LoadTransposeMatrixfARB( const GLfloat *m ) +{ + GLfloat tm[16]; + if (!m) return; + _math_transposef(tm, m); + _mesa_LoadMatrixf(tm); +} + + +void GLAPIENTRY +_mesa_LoadTransposeMatrixdARB( const GLdouble *m ) +{ + GLfloat tm[16]; + if (!m) return; + _math_transposefd(tm, m); + _mesa_LoadMatrixf(tm); +} + + +void GLAPIENTRY +_mesa_MultTransposeMatrixfARB( const GLfloat *m ) +{ + GLfloat tm[16]; + if (!m) return; + _math_transposef(tm, m); + _mesa_MultMatrixf(tm); +} + + +void GLAPIENTRY +_mesa_MultTransposeMatrixdARB( const GLdouble *m ) +{ + GLfloat tm[16]; + if (!m) return; + _math_transposefd(tm, m); + _mesa_MultMatrixf(tm); +} +#endif + +/** + * Set the viewport. + * + * \param x, y coordinates of the lower-left corner of the viewport rectangle. + * \param width width of the viewport rectangle. + * \param height height of the viewport rectangle. + * + * \sa Called via glViewport() or display list execution. + * + * Flushes the vertices and calls _mesa_set_viewport() with the given + * parameters. + */ +void GLAPIENTRY +_mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + _mesa_set_viewport(ctx, x, y, width, height); +} + +/** + * Set new viewport parameters and update derived state (the _WindowMap + * matrix). Usually called from _mesa_Viewport(). + * + * \param ctx GL context. + * \param x, y coordinates of the lower left corner of the viewport rectangle. + * \param width width of the viewport rectangle. + * \param height height of the viewport rectangle. + * + * Verifies the parameters, clamps them to the implementation dependent range + * and updates __GLcontextRec::Viewport. Computes the scale and bias values for + * the drivers and notifies the driver via the dd_function_table::Viewport + * callback. + */ +void +_mesa_set_viewport( GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height ) +{ + const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; + const GLfloat n = ctx->Viewport.Near; + const GLfloat f = ctx->Viewport.Far; + + ASSERT(depthMax > 0); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glViewport %d %d %d %d\n", x, y, width, height); + + if (width < 0 || height < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, + "glViewport(%d, %d, %d, %d)", x, y, width, height ); + return; + } + + /* clamp width, and height to implementation dependent range */ + width = CLAMP( width, 1, ctx->Const.MaxViewportWidth ); + height = CLAMP( height, 1, ctx->Const.MaxViewportHeight ); + + /* Save viewport */ + ctx->Viewport.X = x; + ctx->Viewport.Width = width; + ctx->Viewport.Y = y; + ctx->Viewport.Height = height; + + /* XXX send transposed width/height to Driver.Viewport() below??? */ + if (ctx->_RotateMode) { + GLint tmp, tmps; + tmp = x; x = y; y = tmp; + tmps = width; width = height; height = tmps; + } + + /* Compute scale and bias values. This is really driver-specific + * and should be maintained elsewhere if at all. + * NOTE: RasterPos uses this. + */ + _math_matrix_viewport(&ctx->Viewport._WindowMap, x, y, width, height, + n, f, depthMax); + + ctx->NewState |= _NEW_VIEWPORT; + + if (ctx->Driver.Viewport) { + /* Many drivers will use this call to check for window size changes + * and reallocate the z/stencil/accum/etc buffers if needed. + */ + (*ctx->Driver.Viewport)( ctx, x, y, width, height ); + } +} + + +#if _HAVE_FULL_GL +void GLAPIENTRY +_mesa_DepthRange( GLclampd nearval, GLclampd farval ) +{ + /* + * nearval - specifies mapping of the near clipping plane to window + * coordinates, default is 0 + * farval - specifies mapping of the far clipping plane to window + * coordinates, default is 1 + * + * After clipping and div by w, z coords are in -1.0 to 1.0, + * corresponding to near and far clipping planes. glDepthRange + * specifies a linear mapping of the normalized z coords in + * this range to window z coords. + */ + GLfloat depthMax; + GLfloat n, f; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + depthMax = ctx->DrawBuffer->_DepthMaxF; + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glDepthRange %f %f\n", nearval, farval); + + n = (GLfloat) CLAMP( nearval, 0.0, 1.0 ); + f = (GLfloat) CLAMP( farval, 0.0, 1.0 ); + + ctx->Viewport.Near = n; + ctx->Viewport.Far = f; + ctx->Viewport._WindowMap.m[MAT_SZ] = depthMax * ((f - n) / 2.0F); + ctx->Viewport._WindowMap.m[MAT_TZ] = depthMax * ((f - n) / 2.0F + n); + ctx->NewState |= _NEW_VIEWPORT; + + if (ctx->Driver.DepthRange) { + (*ctx->Driver.DepthRange)( ctx, nearval, farval ); + } +} +#endif + + + +/**********************************************************************/ +/** \name State management */ +/*@{*/ + + +/** + * Update the projection matrix stack. + * + * \param ctx GL context. + * + * Calls _math_matrix_analyse() with the top-matrix of the projection matrix + * stack, and recomputes user clip positions if necessary. + * + * \note This routine references __GLcontextRec::Tranform attribute values to + * compute userclip positions in clip space, but is only called on + * _NEW_PROJECTION. The _mesa_ClipPlane() function keeps these values up to + * date across changes to the __GLcontextRec::Transform attributes. + */ +static void +update_projection( GLcontext *ctx ) +{ + _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); + +#if FEATURE_userclip + /* Recompute clip plane positions in clipspace. This is also done + * in _mesa_ClipPlane(). + */ + if (ctx->Transform.ClipPlanesEnabled) { + GLuint p; + for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { + if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { + _mesa_transform_vector( ctx->Transform._ClipUserPlane[p], + ctx->Transform.EyeUserPlane[p], + ctx->ProjectionMatrixStack.Top->inv ); + } + } + } +#endif +} + + +/** + * Calculate the combined modelview-projection matrix. + * + * \param ctx GL context. + * + * Multiplies the top matrices of the projection and model view stacks into + * __GLcontextRec::_ModelProjectMatrix via _math_matrix_mul_matrix() and + * analyzes the resulting matrix via _math_matrix_analyse(). + */ +static void +calculate_model_project_matrix( GLcontext *ctx ) +{ + _math_matrix_mul_matrix( &ctx->_ModelProjectMatrix, + ctx->ProjectionMatrixStack.Top, + ctx->ModelviewMatrixStack.Top ); + + _math_matrix_analyse( &ctx->_ModelProjectMatrix ); +} + + +/** + * Updates the combined modelview-projection matrix. + * + * \param ctx GL context. + * \param new_state new state bit mask. + * + * If there is a new model view matrix then analyzes it. If there is a new + * projection matrix, updates it. Finally calls + * calculate_model_project_matrix() to recalculate the modelview-projection + * matrix. + */ +void _mesa_update_modelview_project( GLcontext *ctx, GLuint new_state ) +{ + if (new_state & _NEW_MODELVIEW) { + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + + /* Bring cull position uptodate. + */ + TRANSFORM_POINT3( ctx->Transform.CullObjPos, + ctx->ModelviewMatrixStack.Top->inv, + ctx->Transform.CullEyePos ); + } + + + if (new_state & _NEW_PROJECTION) + update_projection( ctx ); + + /* Keep ModelviewProject uptodate always to allow tnl + * implementations that go model->clip even when eye is required. + */ + calculate_model_project_matrix(ctx); +} + +/*@}*/ + + +/**********************************************************************/ +/** Matrix stack initialization */ +/*@{*/ + + +/** + * Initialize a matrix stack. + * + * \param stack matrix stack. + * \param maxDepth maximum stack depth. + * \param dirtyFlag dirty flag. + * + * Allocates an array of \p maxDepth elements for the matrix stack and calls + * _math_matrix_ctr() and _math_matrix_alloc_inv() for each element to + * initialize it. + */ +static void +init_matrix_stack( struct matrix_stack *stack, + GLuint maxDepth, GLuint dirtyFlag ) +{ + GLuint i; + + stack->Depth = 0; + stack->MaxDepth = maxDepth; + stack->DirtyFlag = dirtyFlag; + /* The stack */ + stack->Stack = (GLmatrix *) CALLOC(maxDepth * sizeof(GLmatrix)); + for (i = 0; i < maxDepth; i++) { + _math_matrix_ctr(&stack->Stack[i]); + _math_matrix_alloc_inv(&stack->Stack[i]); + } + stack->Top = stack->Stack; +} + +/** + * Free matrix stack. + * + * \param stack matrix stack. + * + * Calls _math_matrix_dtr() for each element of the matrix stack and + * frees the array. + */ +static void +free_matrix_stack( struct matrix_stack *stack ) +{ + GLuint i; + for (i = 0; i < stack->MaxDepth; i++) { + _math_matrix_dtr(&stack->Stack[i]); + } + FREE(stack->Stack); + stack->Stack = stack->Top = NULL; +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Initialization */ +/*@{*/ + + +/** + * Initialize the context matrix data. + * + * \param ctx GL context. + * + * Initializes each of the matrix stacks and the combined modelview-projection + * matrix. + */ +void _mesa_init_matrix( GLcontext * ctx ) +{ + GLint i; + + /* Initialize matrix stacks */ + init_matrix_stack(&ctx->ModelviewMatrixStack, MAX_MODELVIEW_STACK_DEPTH, + _NEW_MODELVIEW); + init_matrix_stack(&ctx->ProjectionMatrixStack, MAX_PROJECTION_STACK_DEPTH, + _NEW_PROJECTION); + init_matrix_stack(&ctx->ColorMatrixStack, MAX_COLOR_STACK_DEPTH, + _NEW_COLOR_MATRIX); + for (i = 0; i < MAX_TEXTURE_UNITS; i++) + init_matrix_stack(&ctx->TextureMatrixStack[i], MAX_TEXTURE_STACK_DEPTH, + _NEW_TEXTURE_MATRIX); + for (i = 0; i < MAX_PROGRAM_MATRICES; i++) + init_matrix_stack(&ctx->ProgramMatrixStack[i], + MAX_PROGRAM_MATRIX_STACK_DEPTH, _NEW_TRACK_MATRIX); + ctx->CurrentStack = &ctx->ModelviewMatrixStack; + + /* Init combined Modelview*Projection matrix */ + _math_matrix_ctr( &ctx->_ModelProjectMatrix ); +} + + +/** + * Free the context matrix data. + * + * \param ctx GL context. + * + * Frees each of the matrix stacks and the combined modelview-projection + * matrix. + */ +void _mesa_free_matrix_data( GLcontext *ctx ) +{ + GLint i; + + free_matrix_stack(&ctx->ModelviewMatrixStack); + free_matrix_stack(&ctx->ProjectionMatrixStack); + free_matrix_stack(&ctx->ColorMatrixStack); + for (i = 0; i < MAX_TEXTURE_UNITS; i++) + free_matrix_stack(&ctx->TextureMatrixStack[i]); + for (i = 0; i < MAX_PROGRAM_MATRICES; i++) + free_matrix_stack(&ctx->ProgramMatrixStack[i]); + /* combined Modelview*Projection matrix */ + _math_matrix_dtr( &ctx->_ModelProjectMatrix ); + +} + + +/** + * Initialize the context transform attribute group. + * + * \param ctx GL context. + * + * \todo Move this to a new file with other 'transform' routines. + */ +void _mesa_init_transform( GLcontext *ctx ) +{ + GLint i; + + /* Transformation group */ + ctx->Transform.MatrixMode = GL_MODELVIEW; + ctx->Transform.Normalize = GL_FALSE; + ctx->Transform.RescaleNormals = GL_FALSE; + ctx->Transform.RasterPositionUnclipped = GL_FALSE; + for (i=0;i<MAX_CLIP_PLANES;i++) { + ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 ); + } + ctx->Transform.ClipPlanesEnabled = 0; + + ASSIGN_4V( ctx->Transform.CullObjPos, 0.0, 0.0, 1.0, 0.0 ); + ASSIGN_4V( ctx->Transform.CullEyePos, 0.0, 0.0, 1.0, 0.0 ); +} + + +/** + * Initialize the context viewport attribute group. + * + * \param ctx GL context. + * + * \todo Move this to a new file with other 'viewport' routines. + */ +void _mesa_init_viewport( GLcontext *ctx ) +{ + GLfloat depthMax = 65535.0F; /* sorf of arbitrary */ + + /* Viewport group */ + ctx->Viewport.X = 0; + ctx->Viewport.Y = 0; + ctx->Viewport.Width = 0; + ctx->Viewport.Height = 0; + ctx->Viewport.Near = 0.0; + ctx->Viewport.Far = 1.0; + _math_matrix_ctr(&ctx->Viewport._WindowMap); + + _math_matrix_viewport(&ctx->Viewport._WindowMap, 0, 0, 0, 0, + 0.0F, 1.0F, depthMax); +} + + +/** + * Free the context viewport attribute group data. + * + * \param ctx GL context. + * + * \todo Move this to a new file with other 'viewport' routines. + */ +void _mesa_free_viewport_data( GLcontext *ctx ) +{ + _math_matrix_dtr(&ctx->Viewport._WindowMap); +} + +/*@}*/ diff --git a/src/mesa/main/matrix.h b/src/mesa/main/matrix.h new file mode 100644 index 00000000000..38769867a75 --- /dev/null +++ b/src/mesa/main/matrix.h @@ -0,0 +1,131 @@ +/** + * \file matrix.h + * Matrix operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef MATRIX_H +#define MATRIX_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_Frustum( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ); + +extern void GLAPIENTRY +_mesa_Ortho( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble nearval, GLdouble farval ); + +extern void GLAPIENTRY +_mesa_PushMatrix( void ); + +extern void GLAPIENTRY +_mesa_PopMatrix( void ); + +extern void GLAPIENTRY +_mesa_LoadIdentity( void ); + +extern void GLAPIENTRY +_mesa_LoadMatrixf( const GLfloat *m ); + +extern void GLAPIENTRY +_mesa_LoadMatrixd( const GLdouble *m ); + +extern void GLAPIENTRY +_mesa_MatrixMode( GLenum mode ); + +extern void GLAPIENTRY +_mesa_MultMatrixf( const GLfloat *m ); + +extern void GLAPIENTRY +_mesa_MultMatrixd( const GLdouble *m ); + +extern void GLAPIENTRY +_mesa_Rotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ); + +extern void GLAPIENTRY +_mesa_Rotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ); + +extern void GLAPIENTRY +_mesa_Scalef( GLfloat x, GLfloat y, GLfloat z ); + +extern void GLAPIENTRY +_mesa_Scaled( GLdouble x, GLdouble y, GLdouble z ); + +extern void GLAPIENTRY +_mesa_Translatef( GLfloat x, GLfloat y, GLfloat z ); + +extern void GLAPIENTRY +_mesa_Translated( GLdouble x, GLdouble y, GLdouble z ); + +extern void GLAPIENTRY +_mesa_LoadTransposeMatrixfARB( const GLfloat *m ); + +extern void GLAPIENTRY +_mesa_LoadTransposeMatrixdARB( const GLdouble *m ); + +extern void GLAPIENTRY +_mesa_MultTransposeMatrixfARB( const GLfloat *m ); + +extern void GLAPIENTRY +_mesa_MultTransposeMatrixdARB( const GLdouble *m ); + +extern void GLAPIENTRY +_mesa_Viewport( GLint x, GLint y, GLsizei width, GLsizei height ); + +extern void +_mesa_set_viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height ); + +extern void GLAPIENTRY +_mesa_DepthRange( GLclampd nearval, GLclampd farval ); + + +extern void +_mesa_init_matrix( GLcontext * ctx ); + +extern void +_mesa_init_transform( GLcontext *ctx ); + +extern void +_mesa_init_viewport( GLcontext *ctx ); + +extern void +_mesa_free_matrix_data( GLcontext *ctx ); + +extern void +_mesa_free_viewport_data( GLcontext *ctx ); + +extern void +_mesa_update_modelview_project( GLcontext *ctx, GLuint newstate ); + + +#endif diff --git a/src/mesa/main/mm.c b/src/mesa/main/mm.c new file mode 100644 index 00000000000..e4c96821732 --- /dev/null +++ b/src/mesa/main/mm.c @@ -0,0 +1,220 @@ +/* + * GLX Hardware Device Driver common code + * Copyright (C) 1999 Wittawat Yamwong + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "mm.h" + + +void +mmDumpMemInfo(const memHeap_t *heap) +{ + const TMemBlock *p; + + fprintf(stderr, "Memory heap %p:\n", (void *)heap); + if (heap == 0) { + fprintf(stderr, " heap == 0\n"); + } else { + p = (TMemBlock *)heap; + while (p) { + fprintf(stderr, " Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, + p->free ? '.':'U', + p->reserved ? 'R':'.'); + p = p->next; + } + } + fprintf(stderr, "End of memory blocks\n"); +} + +memHeap_t * +mmInit(int ofs, int size) +{ + PMemBlock blocks; + + if (size <= 0) { + return NULL; + } + blocks = (TMemBlock *) _mesa_calloc(sizeof(TMemBlock)); + if (blocks) { + blocks->ofs = ofs; + blocks->size = size; + blocks->free = 1; + return (memHeap_t *)blocks; + } + else { + return NULL; + } +} + + +static TMemBlock * +SliceBlock(TMemBlock *p, + int startofs, int size, + int reserved, int alignment) +{ + TMemBlock *newblock; + + /* break left */ + if (startofs > p->ofs) { + newblock = (TMemBlock*) _mesa_calloc(sizeof(TMemBlock)); + if (!newblock) + return NULL; + newblock->ofs = startofs; + newblock->size = p->size - (startofs - p->ofs); + newblock->free = 1; + newblock->next = p->next; + p->size -= newblock->size; + p->next = newblock; + p = newblock; + } + + /* break right */ + if (size < p->size) { + newblock = (TMemBlock*) _mesa_calloc(sizeof(TMemBlock)); + if (!newblock) + return NULL; + newblock->ofs = startofs + size; + newblock->size = p->size - size; + newblock->free = 1; + newblock->next = p->next; + p->size = size; + p->next = newblock; + } + + /* p = middle block */ + p->align = alignment; + p->free = 0; + p->reserved = reserved; + return p; +} + + +PMemBlock +mmAllocMem(memHeap_t *heap, int size, int align2, int startSearch) +{ + int mask,startofs,endofs; + TMemBlock *p; + + if (!heap || align2 < 0 || size <= 0) + return NULL; + mask = (1 << align2)-1; + startofs = 0; + p = (TMemBlock *)heap; + while (p) { + if ((p)->free) { + startofs = (p->ofs + mask) & ~mask; + if ( startofs < startSearch ) { + startofs = startSearch; + } + endofs = startofs+size; + if (endofs <= (p->ofs+p->size)) + break; + } + p = p->next; + } + if (!p) + return NULL; + p = SliceBlock(p,startofs,size,0,mask+1); + p->heap = heap; + return p; +} + + +PMemBlock +mmFindBlock(memHeap_t *heap, int start) +{ + TMemBlock *p = (TMemBlock *)heap; + + while (p) { + if (p->ofs == start && p->free) + return p; + + p = p->next; + } + + return NULL; +} + + +static INLINE int +Join2Blocks(TMemBlock *p) +{ + /* XXX there should be some assertions here */ + if (p->free && p->next && p->next->free) { + TMemBlock *q = p->next; + p->size += q->size; + p->next = q->next; + _mesa_free(q); + return 1; + } + return 0; +} + +int +mmFreeMem(PMemBlock b) +{ + TMemBlock *p,*prev; + + if (!b) + return 0; + if (!b->heap) { + fprintf(stderr, "no heap\n"); + return -1; + } + p = b->heap; + prev = NULL; + while (p && p != b) { + prev = p; + p = p->next; + } + if (!p || p->free || p->reserved) { + if (!p) + fprintf(stderr, "block not found in heap\n"); + else if (p->free) + fprintf(stderr, "block already free\n"); + else + fprintf(stderr, "block is reserved\n"); + return -1; + } + p->free = 1; + Join2Blocks(p); + if (prev) + Join2Blocks(prev); + return 0; +} + + +void +mmDestroy(memHeap_t *heap) +{ + TMemBlock *p; + + if (!heap) + return; + + p = (TMemBlock *) heap; + while (p) { + TMemBlock *next = p->next; + _mesa_free(p); + p = next; + } +} diff --git a/src/mesa/main/mm.h b/src/mesa/main/mm.h new file mode 100644 index 00000000000..33c986b4c7d --- /dev/null +++ b/src/mesa/main/mm.h @@ -0,0 +1,115 @@ +/* + * GLX Hardware Device Driver common code + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * Memory manager code. Primarily used by device drivers to manage texture + * heaps, etc. + */ + + +#ifndef MM_H +#define MM_H + + +#include "imports.h" + + +struct mem_block_t { + struct mem_block_t *next; + struct mem_block_t *heap; + int ofs,size; + int align; + unsigned int free:1; + unsigned int reserved:1; +}; + +typedef struct mem_block_t TMemBlock; + +typedef struct mem_block_t *PMemBlock; + +/* a heap is just the first block in a chain */ +typedef struct mem_block_t memHeap_t; + + +/* XXX are these needed? */ +#if 0 +static INLINE int +mmBlockSize(PMemBlock b) +{ + return b->size; +} + +static INLINE int +mmOffset(PMemBlock b) +{ + return b->ofs; +} +#endif + + + +/** + * input: total size in bytes + * return: a heap pointer if OK, NULL if error + */ +extern memHeap_t *mmInit(int ofs, int size); + +/** + * Allocate 'size' bytes with 2^align2 bytes alignment, + * restrict the search to free memory after 'startSearch' + * depth and back buffers should be in different 4mb banks + * to get better page hits if possible + * input: size = size of block + * align2 = 2^align2 bytes alignment + * startSearch = linear offset from start of heap to begin search + * return: pointer to the allocated block, 0 if error + */ +extern PMemBlock mmAllocMem(memHeap_t *heap, int size, int align2, + int startSearch); + +/** + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +extern int mmFreeMem(PMemBlock b); + +/** + * Free block starts at offset + * input: pointer to a heap, start offset + * return: pointer to a block + */ +extern PMemBlock mmFindBlock(memHeap_t *heap, int start); + +/** + * destroy MM + */ +extern void mmDestroy(memHeap_t *mmInit); + +/** + * For debuging purpose. + */ +extern void mmDumpMemInfo(const memHeap_t *mmInit); + +#endif diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h new file mode 100644 index 00000000000..2a0bbd94211 --- /dev/null +++ b/src/mesa/main/mtypes.h @@ -0,0 +1,2930 @@ +/** + * \file mtypes.h + * Main Mesa data structures. + * + * Please try to mark derived values with a leading underscore ('_'). + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +#ifndef TYPES_H +#define TYPES_H + + +#include "glheader.h" +#include "config.h" /* Hardwired parameters */ +#include "glapitable.h" +#include "glthread.h" +#include "math/m_matrix.h" /* GLmatrix */ + + +/** + * Color channel data type. + */ +#if CHAN_BITS == 8 + typedef GLubyte GLchan; +#define CHAN_MAX 255 +#define CHAN_MAXF 255.0F +#define CHAN_TYPE GL_UNSIGNED_BYTE +#elif CHAN_BITS == 16 + typedef GLushort GLchan; +#define CHAN_MAX 65535 +#define CHAN_MAXF 65535.0F +#define CHAN_TYPE GL_UNSIGNED_SHORT +#elif CHAN_BITS == 32 + typedef GLfloat GLchan; +#define CHAN_MAX 1.0 +#define CHAN_MAXF 1.0F +#define CHAN_TYPE GL_FLOAT +#else +#error "illegal number of color channel bits" +#endif + + +#if ACCUM_BITS != 16 +/* Software accum done with GLshort at this time */ +# error "illegal number of accumulation bits" +#endif + + +/** + * Stencil buffer data type. + */ +#if STENCIL_BITS==8 + typedef GLubyte GLstencil; +# define STENCIL_MAX 0xff +#elif STENCIL_BITS==16 + typedef GLushort GLstencil; +# define STENCIL_MAX 0xffff +#else +# error "illegal number of stencil bits" +#endif + + +/** + * Used for storing intermediate depth buffer values. + * The actual depth/Z buffer might use 16 or 32-bit values. + * + * \note Must be 32-bits! + */ +typedef GLuint GLdepth; + + +/** + * Fixed point data type. + */ +typedef int GLfixed; +/* + * Fixed point arithmetic macros + */ +#ifndef FIXED_FRAC_BITS +#define FIXED_FRAC_BITS 11 +#endif + +#define FIXED_SHIFT FIXED_FRAC_BITS +#define FIXED_ONE (1 << FIXED_SHIFT) +#define FIXED_HALF (1 << (FIXED_SHIFT-1)) +#define FIXED_FRAC_MASK (FIXED_ONE - 1) +#define FIXED_INT_MASK (~FIXED_FRAC_MASK) +#define FIXED_EPSILON 1 +#define FIXED_SCALE ((float) FIXED_ONE) +#define FIXED_DBL_SCALE ((double) FIXED_ONE) +#define FloatToFixed(X) (IROUND((X) * FIXED_SCALE)) +#define FixedToDouble(X) ((X) * (1.0 / FIXED_DBL_SCALE)) +#define IntToFixed(I) ((I) << FIXED_SHIFT) +#define FixedToInt(X) ((X) >> FIXED_SHIFT) +#define FixedToUns(X) (((unsigned int)(X)) >> FIXED_SHIFT) +#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK) +#define FixedFloor(X) ((X) & FIXED_INT_MASK) +#define FixedToFloat(X) ((X) * (1.0F / FIXED_SCALE)) +#define PosFloatToFixed(X) FloatToFixed(X) +#define SignedFloatToFixed(X) FloatToFixed(X) + + + +/** + * \name Some forward type declarations + */ +/*@{*/ +struct _mesa_HashTable; +struct gl_pixelstore_attrib; +struct gl_texture_format; +struct gl_texture_image; +struct gl_texture_object; +typedef struct __GLcontextRec GLcontext; +typedef struct __GLcontextModesRec GLvisual; +typedef struct gl_framebuffer GLframebuffer; +/*@}*/ + + + +/** + * Indexes for vertex program attributes. + * GL_NV_vertex_program aliases generic attributes over the conventional + * attributes. In GL_ARB_vertex_program shader the aliasing is optional. + * In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the + * generic attributes are distinct/separate). + */ +enum +{ + VERT_ATTRIB_POS = 0, + VERT_ATTRIB_WEIGHT = 1, + VERT_ATTRIB_NORMAL = 2, + VERT_ATTRIB_COLOR0 = 3, + VERT_ATTRIB_COLOR1 = 4, + VERT_ATTRIB_FOG = 5, + VERT_ATTRIB_SIX = 6, + VERT_ATTRIB_SEVEN = 7, + VERT_ATTRIB_TEX0 = 8, + VERT_ATTRIB_TEX1 = 9, + VERT_ATTRIB_TEX2 = 10, + VERT_ATTRIB_TEX3 = 11, + VERT_ATTRIB_TEX4 = 12, + VERT_ATTRIB_TEX5 = 13, + VERT_ATTRIB_TEX6 = 14, + VERT_ATTRIB_TEX7 = 15, + VERT_ATTRIB_GENERIC0 = 16, + VERT_ATTRIB_GENERIC1 = 17, + VERT_ATTRIB_GENERIC2 = 18, + VERT_ATTRIB_GENERIC3 = 19, + VERT_ATTRIB_MAX = 16 +}; + +/** + * Bitflags for vertex attributes. + * These are used in bitfields in many places. + */ +/*@{*/ +#define VERT_BIT_POS (1 << VERT_ATTRIB_POS) +#define VERT_BIT_WEIGHT (1 << VERT_ATTRIB_WEIGHT) +#define VERT_BIT_NORMAL (1 << VERT_ATTRIB_NORMAL) +#define VERT_BIT_COLOR0 (1 << VERT_ATTRIB_COLOR0) +#define VERT_BIT_COLOR1 (1 << VERT_ATTRIB_COLOR1) +#define VERT_BIT_FOG (1 << VERT_ATTRIB_FOG) +#define VERT_BIT_SIX (1 << VERT_ATTRIB_SIX) +#define VERT_BIT_SEVEN (1 << VERT_ATTRIB_SEVEN) +#define VERT_BIT_TEX0 (1 << VERT_ATTRIB_TEX0) +#define VERT_BIT_TEX1 (1 << VERT_ATTRIB_TEX1) +#define VERT_BIT_TEX2 (1 << VERT_ATTRIB_TEX2) +#define VERT_BIT_TEX3 (1 << VERT_ATTRIB_TEX3) +#define VERT_BIT_TEX4 (1 << VERT_ATTRIB_TEX4) +#define VERT_BIT_TEX5 (1 << VERT_ATTRIB_TEX5) +#define VERT_BIT_TEX6 (1 << VERT_ATTRIB_TEX6) +#define VERT_BIT_TEX7 (1 << VERT_ATTRIB_TEX7) +#define VERT_BIT_GENERIC0 (1 << VERT_ATTRIB_GENERIC0) +#define VERT_BIT_GENERIC1 (1 << VERT_ATTRIB_GENERIC1) +#define VERT_BIT_GENERIC2 (1 << VERT_ATTRIB_GENERIC2) +#define VERT_BIT_GENERIC3 (1 << VERT_ATTRIB_GENERIC3) + +#define VERT_BIT_TEX(u) (1 << (VERT_ATTRIB_TEX0 + (u))) +#define VERT_BIT_GENERIC(g) (1 << (VERT_ATTRIB_GENERIC0 + (g))) +/*@}*/ + + +/** + * Indexes for vertex program result attributes + */ +#define VERT_RESULT_HPOS 0 +#define VERT_RESULT_COL0 1 +#define VERT_RESULT_COL1 2 +#define VERT_RESULT_BFC0 3 +#define VERT_RESULT_BFC1 4 +#define VERT_RESULT_FOGC 5 +#define VERT_RESULT_PSIZ 6 +#define VERT_RESULT_TEX0 7 +#define VERT_RESULT_TEX1 8 +#define VERT_RESULT_TEX2 9 +#define VERT_RESULT_TEX3 10 +#define VERT_RESULT_TEX4 11 +#define VERT_RESULT_TEX5 12 +#define VERT_RESULT_TEX6 13 +#define VERT_RESULT_TEX7 14 +#define VERT_RESULT_MAX 15 + + +/** + * Indexes for fragment program input attributes. + */ +enum +{ + FRAG_ATTRIB_WPOS = 0, + FRAG_ATTRIB_COL0 = 1, + FRAG_ATTRIB_COL1 = 2, + FRAG_ATTRIB_FOGC = 3, + FRAG_ATTRIB_TEX0 = 4, + FRAG_ATTRIB_TEX1 = 5, + FRAG_ATTRIB_TEX2 = 6, + FRAG_ATTRIB_TEX3 = 7, + FRAG_ATTRIB_TEX4 = 8, + FRAG_ATTRIB_TEX5 = 9, + FRAG_ATTRIB_TEX6 = 10, + FRAG_ATTRIB_TEX7 = 11 +}; + +/* + * Bitflags for fragment attributes. + */ +/*@{*/ +#define FRAG_BIT_WPOS (1 << FRAG_ATTRIB_WPOS) +#define FRAG_BIT_COL0 (1 << FRAG_ATTRIB_COL0) +#define FRAG_BIT_COL1 (1 << FRAG_ATTRIB_COL1) +#define FRAG_BIT_FOGC (1 << FRAG_ATTRIB_FOGC) +#define FRAG_BIT_TEX0 (1 << FRAG_ATTRIB_TEX0) +#define FRAG_BIT_TEX1 (1 << FRAG_ATTRIB_TEX1) +#define FRAG_BIT_TEX2 (1 << FRAG_ATTRIB_TEX2) +#define FRAG_BIT_TEX3 (1 << FRAG_ATTRIB_TEX3) +#define FRAG_BIT_TEX4 (1 << FRAG_ATTRIB_TEX4) +#define FRAG_BIT_TEX5 (1 << FRAG_ATTRIB_TEX5) +#define FRAG_BIT_TEX6 (1 << FRAG_ATTRIB_TEX6) +#define FRAG_BIT_TEX7 (1 << FRAG_ATTRIB_TEX7) + +#define FRAG_BITS_TEX_ANY (FRAG_BIT_TEX0| \ + FRAG_BIT_TEX1| \ + FRAG_BIT_TEX2| \ + FRAG_BIT_TEX3| \ + FRAG_BIT_TEX4| \ + FRAG_BIT_TEX5| \ + FRAG_BIT_TEX6| \ + FRAG_BIT_TEX7) +/*@}*/ + + +/** + * Indexes for all renderbuffers + */ +enum { + BUFFER_FRONT_LEFT = 0, /* the four standard color buffers */ + BUFFER_BACK_LEFT = 1, + BUFFER_FRONT_RIGHT = 2, + BUFFER_BACK_RIGHT = 3, + BUFFER_AUX0 = 4, /* optional aux buffer */ + BUFFER_AUX1 = 5, + BUFFER_AUX2 = 6, + BUFFER_AUX3 = 7, + BUFFER_DEPTH = 8, + BUFFER_STENCIL = 9, + BUFFER_ACCUM = 10, + BUFFER_COLOR0 = 11, /* generic renderbuffers */ + BUFFER_COLOR1 = 12, + BUFFER_COLOR2 = 13, + BUFFER_COLOR3 = 14, + BUFFER_COLOR4 = 15, + BUFFER_COLOR5 = 16, + BUFFER_COLOR6 = 17, + BUFFER_COLOR7 = 18, + BUFFER_COUNT = 19 +}; + +/** + * Bit flags for all renderbuffers + */ +#define BUFFER_BIT_FRONT_LEFT (1 << BUFFER_FRONT_LEFT) +#define BUFFER_BIT_BACK_LEFT (1 << BUFFER_BACK_LEFT) +#define BUFFER_BIT_FRONT_RIGHT (1 << BUFFER_FRONT_RIGHT) +#define BUFFER_BIT_BACK_RIGHT (1 << BUFFER_BACK_RIGHT) +#define BUFFER_BIT_AUX0 (1 << BUFFER_AUX0) +#define BUFFER_BIT_AUX1 (1 << BUFFER_AUX1) +#define BUFFER_BIT_AUX2 (1 << BUFFER_AUX2) +#define BUFFER_BIT_AUX3 (1 << BUFFER_AUX3) +#define BUFFER_BIT_DEPTH (1 << BUFFER_DEPTH) +#define BUFFER_BIT_STENCIL (1 << BUFFER_STENCIL) +#define BUFFER_BIT_ACCUM (1 << BUFFER_ACCUM) +#define BUFFER_BIT_COLOR0 (1 << BUFFER_COLOR0) +#define BUFFER_BIT_COLOR1 (1 << BUFFER_COLOR1) +#define BUFFER_BIT_COLOR2 (1 << BUFFER_COLOR2) +#define BUFFER_BIT_COLOR3 (1 << BUFFER_COLOR3) +#define BUFFER_BIT_COLOR4 (1 << BUFFER_COLOR4) +#define BUFFER_BIT_COLOR5 (1 << BUFFER_COLOR5) +#define BUFFER_BIT_COLOR6 (1 << BUFFER_COLOR6) +#define BUFFER_BIT_COLOR7 (1 << BUFFER_COLOR7) + + +/** + * Data structure for color tables + */ +struct gl_color_table +{ + GLenum Format; /**< GL_ALPHA, GL_RGB, GL_RGB, etc */ + GLenum IntFormat; + GLuint Size; /**< number of entries (rows) in table */ + GLvoid *Table; /**< points to data of <Type> */ + GLenum Type; /**< GL_UNSIGNED_BYTE or GL_FLOAT */ + GLubyte RedSize; + GLubyte GreenSize; + GLubyte BlueSize; + GLubyte AlphaSize; + GLubyte LuminanceSize; + GLubyte IntensitySize; +}; + + +/** + * \name Bit flags used for updating material values. + */ +/*@{*/ +#define MAT_ATTRIB_FRONT_AMBIENT 0 +#define MAT_ATTRIB_BACK_AMBIENT 1 +#define MAT_ATTRIB_FRONT_DIFFUSE 2 +#define MAT_ATTRIB_BACK_DIFFUSE 3 +#define MAT_ATTRIB_FRONT_SPECULAR 4 +#define MAT_ATTRIB_BACK_SPECULAR 5 +#define MAT_ATTRIB_FRONT_EMISSION 6 +#define MAT_ATTRIB_BACK_EMISSION 7 +#define MAT_ATTRIB_FRONT_SHININESS 8 +#define MAT_ATTRIB_BACK_SHININESS 9 +#define MAT_ATTRIB_FRONT_INDEXES 10 +#define MAT_ATTRIB_BACK_INDEXES 11 +#define MAT_ATTRIB_MAX 12 + +#define MAT_ATTRIB_AMBIENT(f) (MAT_ATTRIB_FRONT_AMBIENT+(f)) +#define MAT_ATTRIB_DIFFUSE(f) (MAT_ATTRIB_FRONT_DIFFUSE+(f)) +#define MAT_ATTRIB_SPECULAR(f) (MAT_ATTRIB_FRONT_SPECULAR+(f)) +#define MAT_ATTRIB_EMISSION(f) (MAT_ATTRIB_FRONT_EMISSION+(f)) +#define MAT_ATTRIB_SHININESS(f)(MAT_ATTRIB_FRONT_SHININESS+(f)) +#define MAT_ATTRIB_INDEXES(f) (MAT_ATTRIB_FRONT_INDEXES+(f)) + +#define MAT_INDEX_AMBIENT 0 +#define MAT_INDEX_DIFFUSE 1 +#define MAT_INDEX_SPECULAR 2 + +#define MAT_BIT_FRONT_AMBIENT (1<<MAT_ATTRIB_FRONT_AMBIENT) +#define MAT_BIT_BACK_AMBIENT (1<<MAT_ATTRIB_BACK_AMBIENT) +#define MAT_BIT_FRONT_DIFFUSE (1<<MAT_ATTRIB_FRONT_DIFFUSE) +#define MAT_BIT_BACK_DIFFUSE (1<<MAT_ATTRIB_BACK_DIFFUSE) +#define MAT_BIT_FRONT_SPECULAR (1<<MAT_ATTRIB_FRONT_SPECULAR) +#define MAT_BIT_BACK_SPECULAR (1<<MAT_ATTRIB_BACK_SPECULAR) +#define MAT_BIT_FRONT_EMISSION (1<<MAT_ATTRIB_FRONT_EMISSION) +#define MAT_BIT_BACK_EMISSION (1<<MAT_ATTRIB_BACK_EMISSION) +#define MAT_BIT_FRONT_SHININESS (1<<MAT_ATTRIB_FRONT_SHININESS) +#define MAT_BIT_BACK_SHININESS (1<<MAT_ATTRIB_BACK_SHININESS) +#define MAT_BIT_FRONT_INDEXES (1<<MAT_ATTRIB_FRONT_INDEXES) +#define MAT_BIT_BACK_INDEXES (1<<MAT_ATTRIB_BACK_INDEXES) + + +#define FRONT_MATERIAL_BITS (MAT_BIT_FRONT_EMISSION | \ + MAT_BIT_FRONT_AMBIENT | \ + MAT_BIT_FRONT_DIFFUSE | \ + MAT_BIT_FRONT_SPECULAR | \ + MAT_BIT_FRONT_SHININESS | \ + MAT_BIT_FRONT_INDEXES) + +#define BACK_MATERIAL_BITS (MAT_BIT_BACK_EMISSION | \ + MAT_BIT_BACK_AMBIENT | \ + MAT_BIT_BACK_DIFFUSE | \ + MAT_BIT_BACK_SPECULAR | \ + MAT_BIT_BACK_SHININESS | \ + MAT_BIT_BACK_INDEXES) + +#define ALL_MATERIAL_BITS (FRONT_MATERIAL_BITS | BACK_MATERIAL_BITS) +/*@}*/ + + +#define EXP_TABLE_SIZE 512 /**< Specular exponent lookup table sizes */ +#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */ + +/** + * Material shininess lookup table. + */ +struct gl_shine_tab +{ + struct gl_shine_tab *next, *prev; + GLfloat tab[SHINE_TABLE_SIZE+1]; + GLfloat shininess; + GLuint refcount; +}; + + +/** + * Light source state. + */ +struct gl_light +{ + struct gl_light *next; /**< double linked list with sentinel */ + struct gl_light *prev; + + GLfloat Ambient[4]; /**< ambient color */ + GLfloat Diffuse[4]; /**< diffuse color */ + GLfloat Specular[4]; /**< specular color */ + GLfloat EyePosition[4]; /**< position in eye coordinates */ + GLfloat EyeDirection[4]; /**< spotlight dir in eye coordinates */ + GLfloat SpotExponent; + GLfloat SpotCutoff; /**< in degrees */ + GLfloat _CosCutoff; /**< = MAX(0, cos(SpotCutoff)) */ + GLfloat ConstantAttenuation; + GLfloat LinearAttenuation; + GLfloat QuadraticAttenuation; + GLboolean Enabled; /**< On/off flag */ + + /** + * \name Derived fields + */ + /*@{*/ + GLuint _Flags; /**< State */ + + GLfloat _Position[4]; /**< position in eye/obj coordinates */ + GLfloat _VP_inf_norm[3]; /**< Norm direction to infinite light */ + GLfloat _h_inf_norm[3]; /**< Norm( _VP_inf_norm + <0,0,1> ) */ + GLfloat _NormDirection[4]; /**< normalized spotlight direction */ + GLfloat _VP_inf_spot_attenuation; + + GLfloat _SpotExpTable[EXP_TABLE_SIZE][2]; /**< to replace a pow() call */ + GLfloat _MatAmbient[2][3]; /**< material ambient * light ambient */ + GLfloat _MatDiffuse[2][3]; /**< material diffuse * light diffuse */ + GLfloat _MatSpecular[2][3]; /**< material spec * light specular */ + GLfloat _dli; /**< CI diffuse light intensity */ + GLfloat _sli; /**< CI specular light intensity */ + /*@}*/ +}; + + +/** + * Light model state. + */ +struct gl_lightmodel +{ + GLfloat Ambient[4]; /**< ambient color */ + GLboolean LocalViewer; /**< Local (or infinite) view point? */ + GLboolean TwoSide; /**< Two (or one) sided lighting? */ + GLenum ColorControl; /**< either GL_SINGLE_COLOR + * or GL_SEPARATE_SPECULAR_COLOR */ +}; + + +/** + * Material state. + */ +struct gl_material +{ + GLfloat Attrib[MAT_ATTRIB_MAX][4]; +}; + + +/** + * Accumulation buffer attribute group (GL_ACCUM_BUFFER_BIT) + */ +struct gl_accum_attrib +{ + GLfloat ClearColor[4]; /**< Accumulation buffer clear color */ +}; + + +/** + * Color buffer attribute group (GL_COLOR_BUFFER_BIT). + */ +struct gl_colorbuffer_attrib +{ + GLuint ClearIndex; /**< Index to use for glClear */ + GLclampf ClearColor[4]; /**< Color to use for glClear */ + + GLuint IndexMask; /**< Color index write mask */ + GLubyte ColorMask[4]; /**< Each flag is 0xff or 0x0 */ + + GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */ + + /** + * \name alpha testing + */ + /*@{*/ + GLboolean AlphaEnabled; /**< Alpha test enabled flag */ + GLenum AlphaFunc; /**< Alpha test function */ + GLclampf AlphaRef; /**< Alpha reference value */ + /*@}*/ + + /** + * \name Blending + */ + /*@{*/ + GLboolean BlendEnabled; /**< Blending enabled flag */ + GLenum BlendSrcRGB; /**< Blending source operator */ + GLenum BlendDstRGB; /**< Blending destination operator */ + GLenum BlendSrcA; /**< GL_INGR_blend_func_separate */ + GLenum BlendDstA; /**< GL_INGR_blend_func_separate */ + GLenum BlendEquationRGB; /**< Blending equation */ + GLenum BlendEquationA; /**< GL_EXT_blend_equation_separate */ + GLfloat BlendColor[4]; /**< Blending color */ + /*@}*/ + + /** + * \name Logic op + */ + /*@{*/ + GLenum LogicOp; /**< Logic operator */ + GLboolean IndexLogicOpEnabled; /**< Color index logic op enabled flag */ + GLboolean ColorLogicOpEnabled; /**< RGBA logic op enabled flag */ + GLboolean _LogicOpEnabled; /**< RGBA logic op + EXT_blend_logic_op enabled flag */ + /*@}*/ + + GLboolean DitherFlag; /**< Dither enable flag */ +}; + + +/** + * Current attribute group (GL_CURRENT_BIT). + */ +struct gl_current_attrib +{ + /** + * \name Values valid only when FLUSH_VERTICES has been called. + */ + /*@{*/ + GLfloat Attrib[VERT_ATTRIB_MAX][4]; /**< Current vertex attributes + * indexed by VERT_ATTRIB_* */ + GLfloat Index; /**< Current color index */ + GLboolean EdgeFlag; /**< Current edge flag */ + /*@}*/ + + /** + * \name Values are always valid. + * + * \note BTW, note how similar this set of attributes is to the SWvertex + * data type in the software rasterizer... + */ + /*@{*/ + GLfloat RasterPos[4]; /**< Current raster position */ + GLfloat RasterDistance; /**< Current raster distance */ + GLfloat RasterColor[4]; /**< Current raster color */ + GLfloat RasterSecondaryColor[4]; /**< Current raster secondary color */ + GLfloat RasterIndex; /**< Current raster index */ + GLfloat RasterTexCoords[MAX_TEXTURE_UNITS][4];/**< Current raster texcoords */ + GLboolean RasterPosValid; /**< Raster pos valid flag */ + /*@}*/ +}; + + +/** + * Depth buffer attribute group (GL_DEPTH_BUFFER_BIT). + */ +struct gl_depthbuffer_attrib +{ + GLenum Func; /**< Function for depth buffer compare */ + GLclampd Clear; /**< Value to clear depth buffer to */ + GLboolean Test; /**< Depth buffering enabled flag */ + GLboolean Mask; /**< Depth buffer writable? */ + GLboolean OcclusionTest; /**< GL_HP_occlusion_test */ + GLboolean BoundsTest; /**< GL_EXT_depth_bounds_test */ + GLfloat BoundsMin, BoundsMax;/**< GL_EXT_depth_bounds_test */ +}; + + +/** + * glEnable()/glDisable() attribute group (GL_ENABLE_BIT). + */ +struct gl_enable_attrib +{ + GLboolean AlphaTest; + GLboolean AutoNormal; + GLboolean Blend; + GLuint ClipPlanes; + GLboolean ColorMaterial; + GLboolean ColorTable; /* SGI_color_table */ + GLboolean PostColorMatrixColorTable; /* SGI_color_table */ + GLboolean PostConvolutionColorTable; /* SGI_color_table */ + GLboolean Convolution1D; + GLboolean Convolution2D; + GLboolean Separable2D; + GLboolean CullFace; + GLboolean DepthTest; + GLboolean Dither; + GLboolean Fog; + GLboolean Histogram; + GLboolean Light[MAX_LIGHTS]; + GLboolean Lighting; + GLboolean LineSmooth; + GLboolean LineStipple; + GLboolean IndexLogicOp; + GLboolean ColorLogicOp; + GLboolean Map1Color4; + GLboolean Map1Index; + GLboolean Map1Normal; + GLboolean Map1TextureCoord1; + GLboolean Map1TextureCoord2; + GLboolean Map1TextureCoord3; + GLboolean Map1TextureCoord4; + GLboolean Map1Vertex3; + GLboolean Map1Vertex4; + GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */ + GLboolean Map2Color4; + GLboolean Map2Index; + GLboolean Map2Normal; + GLboolean Map2TextureCoord1; + GLboolean Map2TextureCoord2; + GLboolean Map2TextureCoord3; + GLboolean Map2TextureCoord4; + GLboolean Map2Vertex3; + GLboolean Map2Vertex4; + GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */ + GLboolean MinMax; + GLboolean Normalize; + GLboolean PixelTexture; + GLboolean PointSmooth; + GLboolean PolygonOffsetPoint; + GLboolean PolygonOffsetLine; + GLboolean PolygonOffsetFill; + GLboolean PolygonSmooth; + GLboolean PolygonStipple; + GLboolean RescaleNormals; + GLboolean Scissor; + GLboolean Stencil; + GLboolean StencilTwoSide; /* GL_EXT_stencil_two_side */ + GLboolean MultisampleEnabled; /* GL_ARB_multisample */ + GLboolean SampleAlphaToCoverage; /* GL_ARB_multisample */ + GLboolean SampleAlphaToOne; /* GL_ARB_multisample */ + GLboolean SampleCoverage; /* GL_ARB_multisample */ + GLboolean SampleCoverageInvert; /* GL_ARB_multisample */ + GLboolean RasterPositionUnclipped; /* GL_IBM_rasterpos_clip */ + GLuint Texture[MAX_TEXTURE_IMAGE_UNITS]; + GLuint TexGen[MAX_TEXTURE_COORD_UNITS]; + /* SGI_texture_color_table */ + GLboolean TextureColorTable[MAX_TEXTURE_IMAGE_UNITS]; + /* GL_NV_vertex_program */ + GLboolean VertexProgram; + GLboolean VertexProgramPointSize; + GLboolean VertexProgramTwoSide; + /* GL_ARB_point_sprite / GL_NV_point_sprite */ + GLboolean PointSprite; + GLboolean FragmentShaderATI; +}; + + +/** + * Evaluator attribute group (GL_EVAL_BIT). + */ +struct gl_eval_attrib +{ + /** + * \name Enable bits + */ + /*@{*/ + GLboolean Map1Color4; + GLboolean Map1Index; + GLboolean Map1Normal; + GLboolean Map1TextureCoord1; + GLboolean Map1TextureCoord2; + GLboolean Map1TextureCoord3; + GLboolean Map1TextureCoord4; + GLboolean Map1Vertex3; + GLboolean Map1Vertex4; + GLboolean Map1Attrib[16]; /* GL_NV_vertex_program */ + GLboolean Map2Color4; + GLboolean Map2Index; + GLboolean Map2Normal; + GLboolean Map2TextureCoord1; + GLboolean Map2TextureCoord2; + GLboolean Map2TextureCoord3; + GLboolean Map2TextureCoord4; + GLboolean Map2Vertex3; + GLboolean Map2Vertex4; + GLboolean Map2Attrib[16]; /* GL_NV_vertex_program */ + GLboolean AutoNormal; + /*@}*/ + + /** + * \name Map Grid endpoints and divisions and calculated du values + */ + /*@{*/ + GLint MapGrid1un; + GLfloat MapGrid1u1, MapGrid1u2, MapGrid1du; + GLint MapGrid2un, MapGrid2vn; + GLfloat MapGrid2u1, MapGrid2u2, MapGrid2du; + GLfloat MapGrid2v1, MapGrid2v2, MapGrid2dv; + /*@}*/ +}; + + +/** + * Fog attribute group (GL_FOG_BIT). + */ +struct gl_fog_attrib +{ + GLboolean Enabled; /**< Fog enabled flag */ + GLfloat Color[4]; /**< Fog color */ + GLfloat Density; /**< Density >= 0.0 */ + GLfloat Start; /**< Start distance in eye coords */ + GLfloat End; /**< End distance in eye coords */ + GLfloat Index; /**< Fog index */ + GLenum Mode; /**< Fog mode */ + GLboolean ColorSumEnabled; + GLenum FogCoordinateSource; /**< GL_EXT_fog_coord */ +}; + + +/** + * Hint attribute group (GL_HINT_BIT). + * + * Values are always one of GL_FASTEST, GL_NICEST, or GL_DONT_CARE. + */ +struct gl_hint_attrib +{ + GLenum PerspectiveCorrection; + GLenum PointSmooth; + GLenum LineSmooth; + GLenum PolygonSmooth; + GLenum Fog; + GLenum ClipVolumeClipping; /**< GL_EXT_clip_volume_hint */ + GLenum TextureCompression; /**< GL_ARB_texture_compression */ + GLenum GenerateMipmap; /**< GL_SGIS_generate_mipmap */ + GLenum FragmentShaderDerivative; /**< GL_ARB_fragment_shader */ +}; + + +/** + * Histogram attributes. + */ +struct gl_histogram_attrib +{ + GLuint Width; /**< number of table entries */ + GLint Format; /**< GL_ALPHA, GL_RGB, etc */ + GLuint Count[HISTOGRAM_TABLE_SIZE][4]; /**< the histogram */ + GLboolean Sink; /**< terminate image transfer? */ + GLubyte RedSize; /**< Bits per counter */ + GLubyte GreenSize; + GLubyte BlueSize; + GLubyte AlphaSize; + GLubyte LuminanceSize; +}; + + +/** + * Color Min/max state. + */ +struct gl_minmax_attrib +{ + GLenum Format; + GLboolean Sink; + GLfloat Min[4], Max[4]; /**< RGBA */ +}; + + +/** + * Image convolution state. + */ +struct gl_convolution_attrib +{ + GLenum Format; + GLenum InternalFormat; + GLuint Width; + GLuint Height; + GLfloat Filter[MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_HEIGHT * 4]; +}; + + +/** + * Light state flags. + */ +/*@{*/ +#define LIGHT_SPOT 0x1 +#define LIGHT_LOCAL_VIEWER 0x2 +#define LIGHT_POSITIONAL 0x4 +#define LIGHT_NEED_VERTICES (LIGHT_POSITIONAL|LIGHT_LOCAL_VIEWER) +/*@}*/ + + +/** + * Lighting attribute group (GL_LIGHT_BIT). + */ +struct gl_light_attrib +{ + struct gl_light Light[MAX_LIGHTS]; /**< Array of light sources */ + struct gl_lightmodel Model; /**< Lighting model */ + + /** + * Must flush FLUSH_VERTICES before referencing: + */ + /*@{*/ + struct gl_material Material; /**< Includes front & back values */ + /*@}*/ + + GLboolean Enabled; /**< Lighting enabled flag */ + GLenum ShadeModel; /**< GL_FLAT or GL_SMOOTH */ + GLenum ColorMaterialFace; /**< GL_FRONT, BACK or FRONT_AND_BACK */ + GLenum ColorMaterialMode; /**< GL_AMBIENT, GL_DIFFUSE, etc */ + GLuint ColorMaterialBitmask; /**< bitmask formed from Face and Mode */ + GLboolean ColorMaterialEnabled; + + struct gl_light EnabledList; /**< List sentinel */ + + /** + * Derived state for optimizations: + */ + /*@{*/ + GLboolean _NeedEyeCoords; + GLboolean _NeedVertices; /**< Use fast shader? */ + GLuint _Flags; /**< LIGHT_* flags, see above */ + GLfloat _BaseColor[2][3]; + /*@}*/ +}; + + +/** + * Line attribute group (GL_LINE_BIT). + */ +struct gl_line_attrib +{ + GLboolean SmoothFlag; /**< GL_LINE_SMOOTH enabled? */ + GLboolean StippleFlag; /**< GL_LINE_STIPPLE enabled? */ + GLushort StipplePattern; /**< Stipple pattern */ + GLint StippleFactor; /**< Stipple repeat factor */ + GLfloat Width; /**< Line width */ + GLfloat _Width; /**< Clamped Line width */ +}; + + +/** + * Display list attribute group (GL_LIST_BIT). + */ +struct gl_list_attrib +{ + GLuint ListBase; +}; + + +/** + * Used by device drivers to hook new commands into display lists. + */ +struct gl_list_instruction +{ + GLuint Size; + void (*Execute)( GLcontext *ctx, void *data ); + void (*Destroy)( GLcontext *ctx, void *data ); + void (*Print)( GLcontext *ctx, void *data ); +}; + +#define MAX_DLIST_EXT_OPCODES 16 + +/** + * Used by device drivers to hook new commands into display lists. + */ +struct gl_list_extensions +{ + struct gl_list_instruction Opcode[MAX_DLIST_EXT_OPCODES]; + GLuint NumOpcodes; +}; + + +/** + * Multisample attribute group (GL_MULTISAMPLE_BIT). + */ +struct gl_multisample_attrib +{ + GLboolean Enabled; + GLboolean SampleAlphaToCoverage; + GLboolean SampleAlphaToOne; + GLboolean SampleCoverage; + GLfloat SampleCoverageValue; + GLboolean SampleCoverageInvert; +}; + + +/** + * Pixel attribute group (GL_PIXEL_MODE_BIT). + */ +struct gl_pixel_attrib +{ + GLenum ReadBuffer; /**< source buffer for glRead/CopyPixels() */ + GLfloat RedBias, RedScale; + GLfloat GreenBias, GreenScale; + GLfloat BlueBias, BlueScale; + GLfloat AlphaBias, AlphaScale; + GLfloat DepthBias, DepthScale; + GLint IndexShift, IndexOffset; + GLboolean MapColorFlag; + GLboolean MapStencilFlag; + GLfloat ZoomX, ZoomY; + /* XXX move these out of gl_pixel_attrib */ + GLint MapStoSsize; /**< Size of each pixel map */ + GLint MapItoIsize; + GLint MapItoRsize; + GLint MapItoGsize; + GLint MapItoBsize; + GLint MapItoAsize; + GLint MapRtoRsize; + GLint MapGtoGsize; + GLint MapBtoBsize; + GLint MapAtoAsize; + GLint MapStoS[MAX_PIXEL_MAP_TABLE]; /**< Pixel map tables */ + GLfloat MapItoI[MAX_PIXEL_MAP_TABLE]; + GLfloat MapItoR[MAX_PIXEL_MAP_TABLE]; + GLfloat MapItoG[MAX_PIXEL_MAP_TABLE]; + GLfloat MapItoB[MAX_PIXEL_MAP_TABLE]; + GLfloat MapItoA[MAX_PIXEL_MAP_TABLE]; + GLubyte MapItoR8[MAX_PIXEL_MAP_TABLE]; /**< converted to 8-bit color */ + GLubyte MapItoG8[MAX_PIXEL_MAP_TABLE]; + GLubyte MapItoB8[MAX_PIXEL_MAP_TABLE]; + GLubyte MapItoA8[MAX_PIXEL_MAP_TABLE]; + GLfloat MapRtoR[MAX_PIXEL_MAP_TABLE]; + GLfloat MapGtoG[MAX_PIXEL_MAP_TABLE]; + GLfloat MapBtoB[MAX_PIXEL_MAP_TABLE]; + GLfloat MapAtoA[MAX_PIXEL_MAP_TABLE]; + /** GL_EXT_histogram */ + GLboolean HistogramEnabled; + GLboolean MinMaxEnabled; + /** GL_SGIS_pixel_texture */ + GLboolean PixelTextureEnabled; + GLenum FragmentRgbSource; + GLenum FragmentAlphaSource; + /** GL_SGI_color_matrix */ + GLfloat PostColorMatrixScale[4]; /**< RGBA */ + GLfloat PostColorMatrixBias[4]; /**< RGBA */ + /** GL_SGI_color_table */ + GLfloat ColorTableScale[4]; + GLfloat ColorTableBias[4]; + GLboolean ColorTableEnabled; + GLfloat PCCTscale[4]; + GLfloat PCCTbias[4]; + GLboolean PostConvolutionColorTableEnabled; + GLfloat PCMCTscale[4]; + GLfloat PCMCTbias[4]; + GLboolean PostColorMatrixColorTableEnabled; + /** GL_SGI_texture_color_table */ + GLfloat TextureColorTableScale[4]; + GLfloat TextureColorTableBias[4]; + /** Convolution */ + GLboolean Convolution1DEnabled; + GLboolean Convolution2DEnabled; + GLboolean Separable2DEnabled; + GLfloat ConvolutionBorderColor[3][4]; + GLenum ConvolutionBorderMode[3]; + GLfloat ConvolutionFilterScale[3][4]; + GLfloat ConvolutionFilterBias[3][4]; + GLfloat PostConvolutionScale[4]; /**< RGBA */ + GLfloat PostConvolutionBias[4]; /**< RGBA */ +}; + + +/** + * Point attribute group (GL_POINT_BIT). + */ +struct gl_point_attrib +{ + GLboolean SmoothFlag; /**< True if GL_POINT_SMOOTH is enabled */ + GLfloat Size; /**< User-specified point size */ + GLfloat _Size; /**< Size clamped to Const.Min/MaxPointSize */ + GLfloat Params[3]; /**< GL_EXT_point_parameters */ + GLfloat MinSize, MaxSize; /**< GL_EXT_point_parameters */ + GLfloat Threshold; /**< GL_EXT_point_parameters */ + GLboolean _Attenuated; /**< True if Params != [1, 0, 0] */ + GLboolean PointSprite; /**< GL_NV_point_sprite / GL_NV_point_sprite */ + GLboolean CoordReplace[MAX_TEXTURE_UNITS]; /**< GL_NV/ARB_point_sprite */ + GLenum SpriteRMode; /**< GL_NV_point_sprite (only!) */ + GLenum SpriteOrigin; /**< GL_ARB_point_sprite */ +}; + + +/** + * Polygon attribute group (GL_POLYGON_BIT). + */ +struct gl_polygon_attrib +{ + GLenum FrontFace; /**< Either GL_CW or GL_CCW */ + GLenum FrontMode; /**< Either GL_POINT, GL_LINE or GL_FILL */ + GLenum BackMode; /**< Either GL_POINT, GL_LINE or GL_FILL */ + GLboolean _FrontBit; /**< 0=GL_CCW, 1=GL_CW */ + GLboolean CullFlag; /**< Culling on/off flag */ + GLboolean SmoothFlag; /**< True if GL_POLYGON_SMOOTH is enabled */ + GLboolean StippleFlag; /**< True if GL_POLYGON_STIPPLE is enabled */ + GLenum CullFaceMode; /**< Culling mode GL_FRONT or GL_BACK */ + GLfloat OffsetFactor; /**< Polygon offset factor, from user */ + GLfloat OffsetUnits; /**< Polygon offset units, from user */ + GLboolean OffsetPoint; /**< Offset in GL_POINT mode */ + GLboolean OffsetLine; /**< Offset in GL_LINE mode */ + GLboolean OffsetFill; /**< Offset in GL_FILL mode */ +}; + + +/** + * Scissor attributes (GL_SCISSOR_BIT). + */ +struct gl_scissor_attrib +{ + GLboolean Enabled; /**< Scissor test enabled? */ + GLint X, Y; /**< Lower left corner of box */ + GLsizei Width, Height; /**< Size of box */ +}; + + +/** + * Stencil attribute group (GL_STENCIL_BUFFER_BIT). + */ +struct gl_stencil_attrib +{ + GLboolean Enabled; /**< Enabled flag */ + GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */ + GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 1) */ + GLenum Function[2]; /**< Stencil function */ + GLenum FailFunc[2]; /**< Fail function */ + GLenum ZPassFunc[2]; /**< Depth buffer pass function */ + GLenum ZFailFunc[2]; /**< Depth buffer fail function */ + GLstencil Ref[2]; /**< Reference value */ + GLstencil ValueMask[2]; /**< Value mask */ + GLstencil WriteMask[2]; /**< Write mask */ + GLstencil Clear; /**< Clear value */ +}; + + +#define NUM_TEXTURE_TARGETS 5 /* 1D, 2D, 3D, CUBE and RECT */ + +/** + * An index for each type of texture object + */ +/*@{*/ +#define TEXTURE_1D_INDEX 0 +#define TEXTURE_2D_INDEX 1 +#define TEXTURE_3D_INDEX 2 +#define TEXTURE_CUBE_INDEX 3 +#define TEXTURE_RECT_INDEX 4 +/*@}*/ + +/** + * Bit flags for each type of texture object + * Used for Texture.Unit[]._ReallyEnabled flags. + */ +/*@{*/ +#define TEXTURE_1D_BIT (1 << TEXTURE_1D_INDEX) +#define TEXTURE_2D_BIT (1 << TEXTURE_2D_INDEX) +#define TEXTURE_3D_BIT (1 << TEXTURE_3D_INDEX) +#define TEXTURE_CUBE_BIT (1 << TEXTURE_CUBE_INDEX) +#define TEXTURE_RECT_BIT (1 << TEXTURE_RECT_INDEX) +/*@}*/ + + +/** + * TexGenEnabled flags. + */ +/*@{*/ +#define S_BIT 1 +#define T_BIT 2 +#define R_BIT 4 +#define Q_BIT 8 +/*@}*/ + + +/** + * Bit flag versions of the corresponding GL_ constants. + */ +/*@{*/ +#define TEXGEN_SPHERE_MAP 0x1 +#define TEXGEN_OBJ_LINEAR 0x2 +#define TEXGEN_EYE_LINEAR 0x4 +#define TEXGEN_REFLECTION_MAP_NV 0x8 +#define TEXGEN_NORMAL_MAP_NV 0x10 + +#define TEXGEN_NEED_NORMALS (TEXGEN_SPHERE_MAP | \ + TEXGEN_REFLECTION_MAP_NV | \ + TEXGEN_NORMAL_MAP_NV) +#define TEXGEN_NEED_EYE_COORD (TEXGEN_SPHERE_MAP | \ + TEXGEN_REFLECTION_MAP_NV | \ + TEXGEN_NORMAL_MAP_NV | \ + TEXGEN_EYE_LINEAR) +/*@}*/ + + +/* A selection of state flags to make driver and module's lives easier. */ +#define ENABLE_TEXGEN0 0x1 +#define ENABLE_TEXGEN1 0x2 +#define ENABLE_TEXGEN2 0x4 +#define ENABLE_TEXGEN3 0x8 +#define ENABLE_TEXGEN4 0x10 +#define ENABLE_TEXGEN5 0x20 +#define ENABLE_TEXGEN6 0x40 +#define ENABLE_TEXGEN7 0x80 + +#define ENABLE_TEXMAT0 0x1 /* Ie. not the identity matrix */ +#define ENABLE_TEXMAT1 0x2 +#define ENABLE_TEXMAT2 0x4 +#define ENABLE_TEXMAT3 0x8 +#define ENABLE_TEXMAT4 0x10 +#define ENABLE_TEXMAT5 0x20 +#define ENABLE_TEXMAT6 0x40 +#define ENABLE_TEXMAT7 0x80 + +#define ENABLE_TEXGEN(i) (ENABLE_TEXGEN0 << (i)) +#define ENABLE_TEXMAT(i) (ENABLE_TEXMAT0 << (i)) + + +/** + * Texel fetch function prototype. We use texel fetch functions to + * extract RGBA, color indexes and depth components out of 1D, 2D and 3D + * texture images. These functions help to isolate us from the gritty + * details of all the various texture image encodings. + * + * \param texImage texture image. + * \param col texel column. + * \param row texel row. + * \param img texel image level/layer. + * \param texelOut output texel (up to 4 GLchans) + */ +typedef void (*FetchTexelFuncC)( const struct gl_texture_image *texImage, + GLint col, GLint row, GLint img, + GLchan *texelOut ); + +/** + * As above, but returns floats. + * Used for depth component images and for upcoming signed/float + * texture images. + */ +typedef void (*FetchTexelFuncF)( const struct gl_texture_image *texImage, + GLint col, GLint row, GLint img, + GLfloat *texelOut ); + + +typedef void (*StoreTexelFunc)(struct gl_texture_image *texImage, + GLint col, GLint row, GLint img, + const void *texel); + +/** + * TexImage store function. This is called by the glTex[Sub]Image + * functions and is responsible for converting the user-specified texture + * image into a specific (hardware) image format. + */ +typedef GLboolean (*StoreTexImageFunc)(GLcontext *ctx, GLuint dims, + GLenum baseInternalFormat, + const struct gl_texture_format *dstFormat, + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking); + + + +/** + * Texture format record + */ +struct gl_texture_format +{ + GLint MesaFormat; /**< One of the MESA_FORMAT_* values */ + + GLenum BaseFormat; /**< Either GL_RGB, GL_RGBA, GL_ALPHA, + * GL_LUMINANCE, GL_LUMINANCE_ALPHA, + * GL_INTENSITY, GL_COLOR_INDEX or + * GL_DEPTH_COMPONENT. + */ + GLenum DataType; /**< GL_FLOAT or GL_UNSIGNED_NORMALIZED_ARB */ + GLubyte RedBits; /**< Bits per texel component */ + GLubyte GreenBits; /**< These are just rough approximations for */ + GLubyte BlueBits; /**< compressed texture formats. */ + GLubyte AlphaBits; + GLubyte LuminanceBits; + GLubyte IntensityBits; + GLubyte IndexBits; + GLubyte DepthBits; + + GLuint TexelBytes; /**< Bytes per texel, 0 if compressed format */ + + StoreTexImageFunc StoreImage; + + /** + * \name Texel fetch function pointers + */ + /*@{*/ + FetchTexelFuncC FetchTexel1D; + FetchTexelFuncC FetchTexel2D; + FetchTexelFuncC FetchTexel3D; + FetchTexelFuncF FetchTexel1Df; + FetchTexelFuncF FetchTexel2Df; + FetchTexelFuncF FetchTexel3Df; + /*@}*/ + + StoreTexelFunc StoreTexel; +}; + + +/** + * Texture image state. Describes the dimensions of a texture image, + * the texel format and pointers to Texel Fetch functions. + */ +struct gl_texture_image +{ + GLenum Format; /**< Either GL_RGB, GL_RGBA, GL_ALPHA, + * GL_LUMINANCE, GL_LUMINANCE_ALPHA, + * GL_INTENSITY, GL_COLOR_INDEX or + * GL_DEPTH_COMPONENT only. + * Used for choosing TexEnv arithmetic. + */ + GLint IntFormat; /**< Internal format as given by the user */ + GLuint Border; /**< 0 or 1 */ + GLuint Width; /**< = 2^WidthLog2 + 2*Border */ + GLuint Height; /**< = 2^HeightLog2 + 2*Border */ + GLuint Depth; /**< = 2^DepthLog2 + 2*Border */ + GLuint RowStride; /**< == Width unless IsClientData and padded */ + GLuint Width2; /**< = Width - 2*Border */ + GLuint Height2; /**< = Height - 2*Border */ + GLuint Depth2; /**< = Depth - 2*Border */ + GLuint WidthLog2; /**< = log2(Width2) */ + GLuint HeightLog2; /**< = log2(Height2) */ + GLuint DepthLog2; /**< = log2(Depth2) */ + GLuint MaxLog2; /**< = MAX(WidthLog2, HeightLog2) */ + GLfloat WidthScale; /**< used for mipmap LOD computation */ + GLfloat HeightScale; /**< used for mipmap LOD computation */ + GLfloat DepthScale; /**< used for mipmap LOD computation */ + GLvoid *Data; /**< Image data, accessed via FetchTexel() */ + GLboolean IsClientData; /**< Data owned by client? */ + GLboolean _IsPowerOfTwo; /**< Are all dimensions powers of two? */ + + const struct gl_texture_format *TexFormat; + + struct gl_texture_object *TexObject; /**< Pointer back to parent object */ + + FetchTexelFuncC FetchTexelc; /**< GLchan texel fetch function pointer */ + FetchTexelFuncF FetchTexelf; /**< Float texel fetch function pointer */ + + GLboolean IsCompressed; /**< GL_ARB_texture_compression */ + GLuint CompressedSize; /**< GL_ARB_texture_compression */ + + /** + * \name For device driver: + */ + /*@{*/ + void *DriverData; /**< Arbitrary device driver data */ + /*@}*/ +}; + + +/** + * Indexes for cube map faces. + */ +/*@{*/ +#define FACE_POS_X 0 +#define FACE_NEG_X 1 +#define FACE_POS_Y 2 +#define FACE_NEG_Y 3 +#define FACE_POS_Z 4 +#define FACE_NEG_Z 5 +#define MAX_FACES 6 +/*@}*/ + + +/** + * Texture object state. Contains the array of mipmap images, border color, + * wrap modes, filter modes, shadow/texcompare state, and the per-texture + * color palette. + */ +struct gl_texture_object +{ + _glthread_Mutex Mutex; /**< for thread safety */ + GLint RefCount; /**< reference count */ + GLuint Name; /**< the user-visible texture object ID */ + GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */ + GLfloat Priority; /**< in [0,1] */ + GLfloat BorderColor[4]; /**< unclamped */ + GLchan _BorderChan[4]; /**< clamped, as GLchan */ + GLenum WrapS; /**< S-axis texture image wrap mode */ + GLenum WrapT; /**< T-axis texture image wrap mode */ + GLenum WrapR; /**< R-axis texture image wrap mode */ + GLenum MinFilter; /**< minification filter */ + GLenum MagFilter; /**< magnification filter */ + GLfloat MinLod; /**< min lambda, OpenGL 1.2 */ + GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */ + GLfloat LodBias; /**< OpenGL 1.4 */ + GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */ + GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */ + GLfloat MaxAnisotropy; /**< GL_EXT_texture_filter_anisotropic */ + GLboolean CompareFlag; /**< GL_SGIX_shadow */ + GLenum CompareOperator; /**< GL_SGIX_shadow */ + GLfloat ShadowAmbient; /**< GL_ARB_shadow_ambient */ + GLenum CompareMode; /**< GL_ARB_shadow */ + GLenum CompareFunc; /**< GL_ARB_shadow */ + GLenum DepthMode; /**< GL_ARB_depth_texture */ + GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */ + GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */ + GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */ + GLboolean _IsPowerOfTwo; /**< Are all image dimensions powers of two? */ + GLboolean Complete; /**< Is texture object complete? */ + + /** Actual texture images, indexed by [cube face] and [mipmap level] */ + struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS]; + + /** GL_EXT_paletted_texture */ + struct gl_color_table Palette; + + + /** + * \name For device driver. + * Note: instead of attaching driver data to this pointer, it's preferable + * to instead use this struct as a base class for your own texture object + * class. Driver->NewTextureObject() can be used to implement the + * allocation. + */ + void *DriverData; /**< Arbitrary device driver data */ +}; + + +/** + * Texture combine environment state. + * + * \todo + * If GL_NV_texture_env_combine4 is ever supported, the arrays in this + * structure will need to be expanded for 4 elements. + */ +struct gl_tex_env_combine_state +{ + GLenum ModeRGB; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */ + GLenum ModeA; /**< GL_REPLACE, GL_DECAL, GL_ADD, etc. */ + GLenum SourceRGB[3]; /**< GL_PRIMARY_COLOR, GL_TEXTURE, etc. */ + GLenum SourceA[3]; /**< GL_PRIMARY_COLOR, GL_TEXTURE, etc. */ + GLenum OperandRGB[3]; /**< SRC_COLOR, ONE_MINUS_SRC_COLOR, etc */ + GLenum OperandA[3]; /**< SRC_ALPHA, ONE_MINUS_SRC_ALPHA, etc */ + GLuint ScaleShiftRGB; /**< 0, 1 or 2 */ + GLuint ScaleShiftA; /**< 0, 1 or 2 */ + GLuint _NumArgsRGB; /**< Number of inputs used for the combine mode. */ + GLuint _NumArgsA; /**< Number of inputs used for the combine mode. */ +}; + + +/** + * Texture unit state. Contains enable flags, texture environment/function/ + * combiners, texgen state, pointers to current texture objects and + * post-filter color tables. + */ +struct gl_texture_unit +{ + GLuint Enabled; /**< bitmask of TEXTURE_*_BIT flags */ + GLuint _ReallyEnabled; /**< 0 or exactly one of TEXTURE_*_BIT flags */ + + GLenum EnvMode; /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */ + GLfloat EnvColor[4]; + GLuint TexGenEnabled; /**< Bitwise-OR of [STRQ]_BIT values */ + /** \name Tex coord generation mode + * Either GL_OBJECT_LINEAR, GL_EYE_LINEAR or GL_SPHERE_MAP. */ + /*@{*/ + GLenum GenModeS; + GLenum GenModeT; + GLenum GenModeR; + GLenum GenModeQ; + /*@}*/ + GLuint _GenBitS; + GLuint _GenBitT; + GLuint _GenBitR; + GLuint _GenBitQ; + GLuint _GenFlags; /**< bitwise or of GenBit[STRQ] */ + GLfloat ObjectPlaneS[4]; + GLfloat ObjectPlaneT[4]; + GLfloat ObjectPlaneR[4]; + GLfloat ObjectPlaneQ[4]; + GLfloat EyePlaneS[4]; + GLfloat EyePlaneT[4]; + GLfloat EyePlaneR[4]; + GLfloat EyePlaneQ[4]; + GLfloat LodBias; /**< for biasing mipmap levels */ + + /** + * \name GL_EXT_texture_env_combine + */ + struct gl_tex_env_combine_state Combine; + + /** + * Derived state based on \c EnvMode and the \c BaseFormat of the + * currently enabled texture. + */ + struct gl_tex_env_combine_state _EnvMode; + + /** + * Currently enabled combiner state. This will point to either + * \c Combine or \c _EnvMode. + */ + struct gl_tex_env_combine_state *_CurrentCombine; + + struct gl_texture_object *Current1D; + struct gl_texture_object *Current2D; + struct gl_texture_object *Current3D; + struct gl_texture_object *CurrentCubeMap; /**< GL_ARB_texture_cube_map */ + struct gl_texture_object *CurrentRect; /**< GL_NV_texture_rectangle */ + + struct gl_texture_object *_Current; /**< Points to really enabled tex obj */ + + struct gl_texture_object Saved1D; /**< only used by glPush/PopAttrib */ + struct gl_texture_object Saved2D; + struct gl_texture_object Saved3D; + struct gl_texture_object SavedCubeMap; + struct gl_texture_object SavedRect; + + /* GL_SGI_texture_color_table */ + struct gl_color_table ColorTable; + struct gl_color_table ProxyColorTable; + GLboolean ColorTableEnabled; +}; + +struct texenvprog_cache { + GLuint hash; + void *key; + void *data; + struct texenvprog_cache *next; +}; + +/** + * Texture attribute group (GL_TEXTURE_BIT). + */ +struct gl_texture_attrib +{ + /** + * name multitexture + */ + /**@{*/ + GLuint CurrentUnit; /**< Active texture unit */ + GLuint _EnabledUnits; /**< one bit set for each really-enabled unit */ + GLuint _EnabledCoordUnits; /**< one bit per enabled coordinate unit */ + GLuint _GenFlags; /**< for texgen */ + GLuint _TexGenEnabled; + GLuint _TexMatEnabled; + /**@}*/ + + struct gl_texture_unit Unit[MAX_TEXTURE_UNITS]; + + struct gl_texture_object *Proxy1D; + struct gl_texture_object *Proxy2D; + struct gl_texture_object *Proxy3D; + struct gl_texture_object *ProxyCubeMap; + struct gl_texture_object *ProxyRect; + + /** GL_EXT_shared_texture_palette */ + GLboolean SharedPalette; + struct gl_color_table Palette; + + /** Cached texenv fragment programs */ + struct texenvprog_cache *env_fp_cache; +}; + + +/** + * Transformation attribute group (GL_TRANSFORM_BIT). + */ +struct gl_transform_attrib +{ + GLenum MatrixMode; /**< Matrix mode */ + GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */ + GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */ + GLuint ClipPlanesEnabled; /**< on/off bitmask */ + GLboolean Normalize; /**< Normalize all normals? */ + GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */ + GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */ + + GLboolean CullVertexFlag; /**< True if GL_CULL_VERTEX_EXT is enabled */ + GLfloat CullEyePos[4]; + GLfloat CullObjPos[4]; +}; + + +/** + * Viewport attribute group (GL_VIEWPORT_BIT). + */ +struct gl_viewport_attrib +{ + GLint X, Y; /**< position */ + GLsizei Width, Height; /**< size */ + GLfloat Near, Far; /**< Depth buffer range */ + GLmatrix _WindowMap; /**< Mapping transformation as a matrix. */ +}; + + +/** + * Node for the attribute stack. + */ +struct gl_attrib_node +{ + GLbitfield kind; + void *data; + struct gl_attrib_node *next; +}; + + +/** + * GL_ARB_vertex/pixel_buffer_object buffer object + */ +struct gl_buffer_object +{ + GLint RefCount; + GLuint Name; + GLenum Usage; + GLenum Access; + GLvoid *Pointer; /**< Only valid while buffer is mapped */ + GLsizeiptrARB Size; /**< Size of storage in bytes */ + GLubyte *Data; /**< Location of storage either in RAM or VRAM. */ + GLboolean OnCard; /**< Is buffer in VRAM? (hardware drivers) */ +}; + + + +/** + * Client pixel packing/unpacking attributes + */ +struct gl_pixelstore_attrib +{ + GLint Alignment; + GLint RowLength; + GLint SkipPixels; + GLint SkipRows; + GLint ImageHeight; /**< for GL_EXT_texture3D */ + GLint SkipImages; /**< for GL_EXT_texture3D */ + GLboolean SwapBytes; + GLboolean LsbFirst; + GLboolean ClientStorage; /**< GL_APPLE_client_storage */ + GLboolean Invert; /**< GL_MESA_pack_invert */ + struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */ +}; + + +#define CA_CLIENT_DATA 0x1 /**< Data not allocated by mesa */ + + +/** + * Client vertex array attributes + */ +struct gl_client_array +{ + GLint Size; /**< components per element (1,2,3,4) */ + GLenum Type; /**< datatype: GL_FLOAT, GL_INT, etc */ + GLsizei Stride; /**< user-specified stride */ + GLsizei StrideB; /**< actual stride in bytes */ + const GLubyte *Ptr; /**< Points to array data */ + GLuint Enabled; /**< one of the _NEW_ARRAY_ bits */ + GLboolean Normalized; /**< GL_ARB_vertex_program */ + + /**< GL_ARB_vertex_buffer_object */ + struct gl_buffer_object *BufferObj; + GLuint _MaxElement; + + GLuint Flags; +}; + + +/** + * Vertex array state + */ +struct gl_array_attrib +{ + struct gl_client_array Vertex; /**< client data descriptors */ + struct gl_client_array Normal; + struct gl_client_array Color; + struct gl_client_array SecondaryColor; + struct gl_client_array FogCoord; + struct gl_client_array Index; + struct gl_client_array TexCoord[MAX_TEXTURE_COORD_UNITS]; + struct gl_client_array EdgeFlag; + + struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX]; /**< GL_NV_vertex_program */ + + GLint ActiveTexture; /**< Client Active Texture */ + GLuint LockFirst; /**< GL_EXT_compiled_vertex_array */ + GLuint LockCount; /**< GL_EXT_compiled_vertex_array */ + + GLuint _Enabled; /**< _NEW_ARRAY_* - bit set if array enabled */ + GLuint NewState; /**< _NEW_ARRAY_* */ + +#if FEATURE_ARB_vertex_buffer_object + struct gl_buffer_object *NullBufferObj; + struct gl_buffer_object *ArrayBufferObj; + struct gl_buffer_object *ElementArrayBufferObj; +#endif + GLuint _MaxElement; /* Min of all enabled array's maxes */ +}; + + +/** + * Feedback buffer state + */ +struct gl_feedback +{ + GLenum Type; + GLuint _Mask; /* FB_* bits */ + GLfloat *Buffer; + GLuint BufferSize; + GLuint Count; +}; + + +/** + * Selection buffer state + */ +struct gl_selection +{ + GLuint *Buffer; /**< selection buffer */ + GLuint BufferSize; /**< size of the selection buffer */ + GLuint BufferCount; /**< number of values in the selection buffer */ + GLuint Hits; /**< number of records in the selection buffer */ + GLuint NameStackDepth; /**< name stack depth */ + GLuint NameStack[MAX_NAME_STACK_DEPTH]; /**< name stack */ + GLboolean HitFlag; /**< hit flag */ + GLfloat HitMinZ; /**< minimum hit depth */ + GLfloat HitMaxZ; /**< maximum hit depth */ +}; + + +/** + * 1-D Evaluator control points + */ +struct gl_1d_map +{ + GLuint Order; /**< Number of control points */ + GLfloat u1, u2, du; /**< u1, u2, 1.0/(u2-u1) */ + GLfloat *Points; /**< Points to contiguous control points */ +}; + + +/** + * 2-D Evaluator control points + */ +struct gl_2d_map +{ + GLuint Uorder; /**< Number of control points in U dimension */ + GLuint Vorder; /**< Number of control points in V dimension */ + GLfloat u1, u2, du; + GLfloat v1, v2, dv; + GLfloat *Points; /**< Points to contiguous control points */ +}; + + +/** + * All evaluator control point state + */ +struct gl_evaluators +{ + /** + * \name 1-D maps + */ + /*@{*/ + struct gl_1d_map Map1Vertex3; + struct gl_1d_map Map1Vertex4; + struct gl_1d_map Map1Index; + struct gl_1d_map Map1Color4; + struct gl_1d_map Map1Normal; + struct gl_1d_map Map1Texture1; + struct gl_1d_map Map1Texture2; + struct gl_1d_map Map1Texture3; + struct gl_1d_map Map1Texture4; + struct gl_1d_map Map1Attrib[16]; /**< GL_NV_vertex_program */ + /*@}*/ + + /** + * \name 2-D maps + */ + /*@{*/ + struct gl_2d_map Map2Vertex3; + struct gl_2d_map Map2Vertex4; + struct gl_2d_map Map2Index; + struct gl_2d_map Map2Color4; + struct gl_2d_map Map2Normal; + struct gl_2d_map Map2Texture1; + struct gl_2d_map Map2Texture2; + struct gl_2d_map Map2Texture3; + struct gl_2d_map Map2Texture4; + struct gl_2d_map Map2Attrib[16]; /**< GL_NV_vertex_program */ + /*@}*/ +}; + + +/** + * NV_fragment_program runtime state + */ +struct fp_machine +{ + GLfloat Temporaries[MAX_NV_FRAGMENT_PROGRAM_TEMPS][4]; + GLfloat Inputs[MAX_NV_FRAGMENT_PROGRAM_INPUTS][4]; + GLfloat Outputs[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS][4]; + GLuint CondCodes[4]; +}; + +/** + * ATI_fragment_shader runtime state + */ +#define ATI_FS_INPUT_PRIMARY 0 +#define ATI_FS_INPUT_SECONDARY 1 + +/* 6 register sets - 2 inputs (primary, secondary) */ +struct atifs_machine +{ + GLfloat Registers[6][4]; + GLfloat PrevPassRegisters[6][4]; + GLfloat Inputs[2][4]; + GLuint pass; +}; + + +/** + * Names of the various vertex/fragment register files + */ +enum register_file +{ + PROGRAM_TEMPORARY, + PROGRAM_INPUT, + PROGRAM_OUTPUT, + PROGRAM_LOCAL_PARAM, + PROGRAM_ENV_PARAM, + PROGRAM_NAMED_PARAM, + PROGRAM_STATE_VAR, + PROGRAM_WRITE_ONLY, + PROGRAM_ADDRESS, + PROGRAM_UNDEFINED /* invalid value */ +}; + + +/** Vertex and fragment instructions */ +struct vp_instruction; +struct fp_instruction; +struct atifs_instruction; +struct program_parameter_list; + + +/** + * Base class for any kind of program object + */ +struct program +{ + GLuint Id; + GLubyte *String; /**< Null-terminated program text */ + GLint RefCount; + GLenum Target; + GLenum Format; /**< String encoding format */ + GLboolean Resident; + GLfloat LocalParams[MAX_PROGRAM_LOCAL_PARAMS][4]; + GLuint NumInstructions; /* GL_ARB_vertex/fragment_program */ + GLuint NumTemporaries; + GLuint NumParameters; + GLuint NumAttributes; + GLuint NumAddressRegs; +}; + + +/** Vertex program object */ +struct vertex_program +{ + struct program Base; /* base class */ + struct vp_instruction *Instructions; /* Compiled instructions */ + GLboolean IsNVProgram; /* GL_NV_vertex_program ? */ + GLboolean IsPositionInvariant; /* GL_NV_vertex_program1_1 */ + GLuint InputsRead; /* Bitmask of which input regs are read */ + GLuint OutputsWritten; /* Bitmask of which output regs are written to */ + struct program_parameter_list *Parameters; /**< array [NumParameters] */ + void *TnlData; /* should probably use Base.DriverData */ +}; + + +/** Fragment program object */ +struct fragment_program +{ + struct program Base; /**< base class */ + struct fp_instruction *Instructions; /**< Compiled instructions */ + GLuint InputsRead; /**< Bitmask of which input regs are read */ + GLuint OutputsWritten; /**< Bitmask of which output regs are written to */ + GLuint TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_INDEX bitmask */ + GLuint NumAluInstructions; /**< GL_ARB_fragment_program */ + GLuint NumTexInstructions; + GLuint NumTexIndirections; + GLenum FogOption; + struct program_parameter_list *Parameters; /**< array [NumParameters] */ + +#ifdef USE_TCC + char c_str[4096]; /* experimental... */ + int c_strlen; +#endif +}; + +struct ati_fragment_shader +{ + struct program Base; + struct atifs_instruction *Instructions; + GLfloat Constants[8][4]; + GLint NumPasses; + GLint cur_pass; +}; + +/** + * State common to vertex and fragment programs. + */ +struct gl_program_state +{ + GLint ErrorPos; /* GL_PROGRAM_ERROR_POSITION_NV */ + const char *ErrorString; /* GL_PROGRAM_ERROR_STRING_NV */ +}; + + +/** + * State vars for GL_ARB/GL_NV_vertex_program + */ +struct gl_vertex_program_state +{ + GLboolean Enabled; /**< GL_VERTEX_PROGRAM_NV */ + GLboolean _Enabled; /**< Really enabled? */ + GLboolean PointSizeEnabled; /**< GL_VERTEX_PROGRAM_POINT_SIZE_NV */ + GLboolean TwoSideEnabled; /**< GL_VERTEX_PROGRAM_TWO_SIDE_NV */ + struct vertex_program *Current; /**< ptr to currently bound program */ + + GLenum TrackMatrix[MAX_NV_VERTEX_PROGRAM_PARAMS / 4]; + GLenum TrackMatrixTransform[MAX_NV_VERTEX_PROGRAM_PARAMS / 4]; + + GLfloat Parameters[MAX_NV_VERTEX_PROGRAM_PARAMS][4]; /* Env params */ + /* Only used during program execution (may be moved someday): */ + GLfloat Temporaries[MAX_NV_VERTEX_PROGRAM_TEMPS][4]; + GLfloat Inputs[MAX_NV_VERTEX_PROGRAM_INPUTS][4]; + GLuint InputsSize[MAX_NV_VERTEX_PROGRAM_INPUTS]; + GLfloat Outputs[MAX_NV_VERTEX_PROGRAM_OUTPUTS][4]; + GLint AddressReg[4]; + +#if FEATURE_MESA_program_debug + GLprogramcallbackMESA Callback; + GLvoid *CallbackData; + GLboolean CallbackEnabled; + GLuint CurrentPosition; +#endif +}; + + +/* + * State for GL_ARB/NV_fragment_program + */ +struct gl_fragment_program_state +{ + GLboolean Enabled; /* GL_VERTEX_PROGRAM_NV */ + GLboolean _Enabled; /* Really enabled? */ + GLboolean _Active; /* Really really enabled? */ + struct fragment_program *Current; /* ptr to currently bound program */ + struct fragment_program *_Current; /* ptr to currently active program */ + struct fp_machine Machine; /* machine state */ + GLfloat Parameters[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4]; /* Env params */ + +#if FEATURE_MESA_program_debug + GLprogramcallbackMESA Callback; + GLvoid *CallbackData; + GLboolean CallbackEnabled; + GLuint CurrentPosition; +#endif +}; + +/* + * State for GL_fragment_shader + */ +struct gl_ati_fragment_shader_state +{ + GLboolean Enabled; + GLboolean _Enabled; + GLboolean Compiling; + struct atifs_machine Machine; /* machine state */ + struct ati_fragment_shader *Current; +}; + +/* + * State for GL_ARB_occlusion_query + */ +struct gl_occlusion_state +{ + GLboolean Active; + GLuint CurrentQueryObject; + GLuint PassedCounter; + struct _mesa_HashTable *QueryObjects; +}; + +/** + * gl2 unique interface identifier. + * Each gl2 interface has its own interface id used for object queries. + */ +enum gl2_uiid +{ + UIID_UNKNOWN, /* supported by all objects */ + UIID_GENERIC, /* generic object */ + UIID_CONTAINER, /* contains generic objects */ + UIID_SHADER, /* shader object */ + UIID_FRAGMENT_SHADER, /* fragment shader */ + UIID_VERTEX_SHADER, /* vertex shader */ + UIID_PROGRAM, /* program object */ + UIID_3DLABS_SHHANDLE /* encapsulates 3dlabs' ShHandle */ +}; + +struct gl2_unknown_intf +{ + GLvoid (* AddRef) (struct gl2_unknown_intf **); + GLvoid (* Release) (struct gl2_unknown_intf **); + struct gl2_unknown_intf **(* QueryInterface) (struct gl2_unknown_intf **, enum gl2_uiid uiid); +}; + +struct gl2_generic_intf +{ + struct gl2_unknown_intf _unknown; + GLvoid (* Delete) (struct gl2_generic_intf **); + GLenum (* GetType) (struct gl2_generic_intf **); + GLhandleARB (* GetName) (struct gl2_generic_intf **); + GLboolean (* GetDeleteStatus) (struct gl2_generic_intf **); + const GLcharARB *(* GetInfoLog) (struct gl2_generic_intf **); +}; + +struct gl2_container_intf +{ + struct gl2_generic_intf _generic; + GLboolean (* Attach) (struct gl2_container_intf **, struct gl2_generic_intf **); + GLboolean (* Detach) (struct gl2_container_intf **, struct gl2_generic_intf **); + GLsizei (* GetAttachedCount) (struct gl2_container_intf **); + struct gl2_generic_intf **(* GetAttached) (struct gl2_container_intf **, GLuint); +}; + +struct gl2_shader_intf +{ + struct gl2_generic_intf _generic; + GLenum (* GetSubType) (struct gl2_shader_intf **); + GLboolean (* GetCompileStatus) (struct gl2_shader_intf **); + GLvoid (* SetSource) (struct gl2_shader_intf **, GLcharARB *, GLint *, GLsizei); + const GLcharARB *(* GetSource) (struct gl2_shader_intf **); + GLvoid (* Compile) (struct gl2_shader_intf **); +}; + +struct gl2_program_intf +{ + struct gl2_container_intf _container; + GLboolean (* GetLinkStatus) (struct gl2_program_intf **); + GLboolean (* GetValidateStatus) (struct gl2_program_intf **); + GLvoid (* Link) (struct gl2_program_intf **); + GLvoid (* Validate) (struct gl2_program_intf **); +}; + +struct gl2_fragment_shader_intf +{ + struct gl2_shader_intf _shader; +}; + +struct gl2_vertex_shader_intf +{ + struct gl2_shader_intf _shader; +}; + +struct gl2_3dlabs_shhandle_intf +{ + struct gl2_unknown_intf _unknown; + GLvoid *(* GetShHandle) (struct gl2_3dlabs_shhandle_intf **); +}; + +struct gl_shader_objects_state +{ + struct gl2_program_intf **current_program; +}; + + +/** + * State which can be shared by multiple contexts: + */ +struct gl_shared_state +{ + _glthread_Mutex Mutex; /**< for thread safety */ + GLint RefCount; /**< Reference count */ + struct _mesa_HashTable *DisplayList; /**< Display lists hash table */ + struct _mesa_HashTable *TexObjects; /**< Texture objects hash table */ + + /** + * \name Default texture objects (shared by all multi-texture units) + */ + /*@{*/ + struct gl_texture_object *Default1D; + struct gl_texture_object *Default2D; + struct gl_texture_object *Default3D; + struct gl_texture_object *DefaultCubeMap; + struct gl_texture_object *DefaultRect; + /*@}*/ + + /** + * \name Vertex/fragment programs + */ + /*@{*/ + struct _mesa_HashTable *Programs; +#if FEATURE_ARB_vertex_program + struct program *DefaultVertexProgram; +#endif +#if FEATURE_ARB_fragment_program + struct program *DefaultFragmentProgram; +#endif +#if FEATURE_ATI_fragment_shader + struct program *DefaultFragmentShader; +#endif + /*@}*/ + +#if FEATURE_ARB_vertex_buffer_object || FEATURE_ARB_pixel_buffer_object + struct _mesa_HashTable *BufferObjects; +#endif + + struct _mesa_HashTable *GL2Objects; + +#if FEATURE_EXT_framebuffer_object + struct _mesa_HashTable *RenderBuffers; + struct _mesa_HashTable *FrameBuffers; +#endif + + void *DriverData; /**< Device driver shared state */ +}; + + + + +/** + * A renderbuffer stores colors or depth values or stencil values. + * A framebuffer object will have a collection of these. + * Data are read/written to the buffer with a handful of Get/Put functions. + * + * Instances of this object are allocated with the Driver's NewRenderbuffer + * hook. Drivers will likely wrap this class inside a driver-specific + * class to simulate inheritance. + */ +struct gl_renderbuffer +{ + GLuint Name; + GLint RefCount; + GLuint Width, Height; + GLenum InternalFormat; /* The user-specified value */ + GLenum _BaseFormat; /* Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or */ + /* GL_STENCIL_INDEX. */ + GLenum DataType; /* Type of values passed to the Get/Put functions */ + GLubyte ComponentSizes[4]; /* bits per component or channel */ + GLvoid *Data; + + /* Used to wrap one renderbuffer around another: */ + struct gl_renderbuffer *Wrapped; + + /* Delete this renderbuffer */ + void (*Delete)(struct gl_renderbuffer *rb); + + /* Allocate new storage for this renderbuffer */ + GLboolean (*AllocStorage)(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height); + + /* Lock/Unlock are called before/after calling the Get/Put functions. + * Not sure this is the right place for these yet. + void (*Lock)(GLcontext *ctx, struct gl_renderbuffer *rb); + void (*Unlock)(GLcontext *ctx, struct gl_renderbuffer *rb); + */ + + /* Return a pointer to the element/pixel at (x,y). + * Should return NULL if the buffer memory can't be directly addressed. + */ + void *(*GetPointer)(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y); + + /* Get/Read a row of values. + * The values will be of format _BaseFormat and type DataType. + */ + void (*GetRow)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values); + + /* Get/Read values at arbitrary locations. + * The values will be of format _BaseFormat and type DataType. + */ + void (*GetValues)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values); + + /* Put/Write a row of values. + * The values will be of format _BaseFormat and type DataType. + */ + void (*PutRow)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask); + + /* Put/Write a row of RGB values. This is a special-case routine that's + * only used for RGBA renderbuffers when the source data is GL_RGB. That's + * a common case for glDrawPixels and some triangle routines. + * The values will be of format GL_RGB and type DataType. + */ + void (*PutRowRGB)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask); + + + /* Put/Write a row of identical values. + * The values will be of format _BaseFormat and type DataType. + */ + void (*PutMonoRow)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask); + + /* Put/Write values at arbitrary locations. + * The values will be of format _BaseFormat and type DataType. + */ + void (*PutValues)(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask); + /* Put/Write identical values at arbitrary locations. + * The values will be of format _BaseFormat and type DataType. + */ + void (*PutMonoValues)(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask); +}; + + +/** + * A renderbuffer attachment point points to either a texture object + * (and specifies a mipmap level, cube face or 3D texture slice) or + * points to a renderbuffer. + */ +struct gl_renderbuffer_attachment +{ + GLenum Type; /* GL_NONE or GL_TEXTURE or GL_RENDERBUFFER_EXT */ + GLboolean Complete; + + /* IF Type == GL_RENDERBUFFER_EXT: */ + struct gl_renderbuffer *Renderbuffer; + + /* IF Type == GL_TEXTURE: */ + struct gl_texture_object *Texture; + GLuint TextureLevel; + GLuint CubeMapFace; /* 0 .. 5, for cube map textures */ + GLuint Zoffset; /* for 3D textures */ +}; + + +/** + * A framebuffer is a collection of renderbuffers (color, depth, stencil, etc). + * In C++ terms, think of this as a base class from which device drivers + * will make derived classes. + */ +struct gl_framebuffer +{ + GLuint Name; /* if zero, this is a window system framebuffer */ + GLint RefCount; + + GLvisual Visual; /**< The corresponding visual */ + + GLboolean Initialized; + + GLuint Width, Height; /**< size of frame buffer in pixels */ + + /** \name Drawing bounds (Intersection of buffer size and scissor box) */ + /*@{*/ + GLint _Xmin, _Xmax; /**< inclusive */ + GLint _Ymin, _Ymax; /**< exclusive */ + /*@}*/ + + /** \name Derived Z buffer stuff */ + /*@{*/ + GLuint _DepthMax; /**< Max depth buffer value */ + GLfloat _DepthMaxF; /**< Float max depth buffer value */ + GLfloat _MRD; /**< minimum resolvable difference in Z values */ + /*@}*/ + + GLenum _Status; /* One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */ + + /* Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */ + struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT]; + + /* In unextended OpenGL these vars are part of the GL_COLOR_BUFFER + * attribute group and GL_PIXEL attribute group, respectively. + */ + GLenum ColorDrawBuffer[MAX_DRAW_BUFFERS]; + GLenum ColorReadBuffer; + + /* These are computed from ColorDrawBuffer and ColorReadBuffer */ + GLuint _ColorDrawBufferMask[MAX_DRAW_BUFFERS]; /* Mask of BUFFER_BIT_* flags */ + GLuint _ColorReadBufferMask; /* Zero or one of BUFFER_BIT_ flags */ + + /* These are computed from _Draw/ReadBufferMask, above. */ + GLuint _NumColorDrawBuffers[MAX_DRAW_BUFFERS]; + struct gl_renderbuffer *_ColorDrawBuffers[MAX_DRAW_BUFFERS][4]; + struct gl_renderbuffer *_ColorReadBuffer; + +#if OLD_RENDERBUFFER + /* XXX THIS IS TEMPORARY */ + GLuint _ColorDrawBit[MAX_DRAW_BUFFERS][4]; +#endif + + /** Delete this framebuffer */ + void (*Delete)(struct gl_framebuffer *fb); +}; + + +/** + * Constants which may be overridden by device driver during context creation + * but are never changed after that. + */ +struct gl_constants +{ + GLint MaxTextureLevels; /**< Maximum number of allowed mipmap levels. */ + GLint Max3DTextureLevels; /**< Maximum number of allowed mipmap levels for 3D texture targets. */ + GLint MaxCubeTextureLevels; /**< Maximum number of allowed mipmap levels for GL_ARB_texture_cube_map */ + GLint MaxTextureRectSize; /* GL_NV_texture_rectangle */ + GLuint MaxTextureCoordUnits; + GLuint MaxTextureImageUnits; + GLuint MaxTextureUnits; /* = MAX(CoordUnits, ImageUnits) */ + GLfloat MaxTextureMaxAnisotropy; /* GL_EXT_texture_filter_anisotropic */ + GLfloat MaxTextureLodBias; /* GL_EXT_texture_lod_bias */ + GLuint MaxArrayLockSize; + GLint SubPixelBits; + GLfloat MinPointSize, MaxPointSize; /* aliased */ + GLfloat MinPointSizeAA, MaxPointSizeAA; /* antialiased */ + GLfloat PointSizeGranularity; + GLfloat MinLineWidth, MaxLineWidth; /* aliased */ + GLfloat MinLineWidthAA, MaxLineWidthAA; /* antialiased */ + GLfloat LineWidthGranularity; + GLuint MaxColorTableSize; + GLuint MaxConvolutionWidth; + GLuint MaxConvolutionHeight; + GLuint MaxClipPlanes; + GLuint MaxLights; + GLfloat MaxShininess; /* GL_NV_light_max_exponent */ + GLfloat MaxSpotExponent; /* GL_NV_light_max_exponent */ + GLuint MaxViewportWidth, MaxViewportHeight; + /* GL_ARB_vertex_program */ + GLuint MaxVertexProgramInstructions; + GLuint MaxVertexProgramAttribs; + GLuint MaxVertexProgramTemps; + GLuint MaxVertexProgramLocalParams; + GLuint MaxVertexProgramEnvParams; + GLuint MaxVertexProgramAddressRegs; + /* GL_ARB_fragment_program */ + GLuint MaxFragmentProgramInstructions; + GLuint MaxFragmentProgramAttribs; + GLuint MaxFragmentProgramTemps; + GLuint MaxFragmentProgramLocalParams; + GLuint MaxFragmentProgramEnvParams; + GLuint MaxFragmentProgramAddressRegs; + GLuint MaxFragmentProgramAluInstructions; + GLuint MaxFragmentProgramTexInstructions; + GLuint MaxFragmentProgramTexIndirections; + /* vertex or fragment program */ + GLuint MaxProgramMatrices; + GLuint MaxProgramMatrixStackDepth; + /* vertex array / buffer object bounds checking */ + GLboolean CheckArrayBounds; + /* GL_ARB_draw_buffers */ + GLuint MaxDrawBuffers; + /* GL_OES_read_format */ + GLenum ColorReadFormat; + GLenum ColorReadType; + /* GL_EXT_framebuffer_object */ + GLuint MaxColorAttachments; + GLuint MaxRenderbufferSize; +}; + + +/** + * Enable flag for each OpenGL extension. Different device drivers will + * enable different extensions at runtime. + */ +struct gl_extensions +{ + /** + * \name Flags to quickly test if certain extensions are available. + * + * Not every extension needs to have such a flag, but it's encouraged. + */ + /*@{*/ + GLboolean dummy; /* don't remove this! */ + GLboolean ARB_depth_texture; + GLboolean ARB_draw_buffers; + GLboolean ARB_fragment_program; + GLboolean ARB_fragment_shader; + GLboolean ARB_half_float_pixel; + GLboolean ARB_imaging; + GLboolean ARB_multisample; + GLboolean ARB_multitexture; + GLboolean ARB_occlusion_query; + GLboolean ARB_point_sprite; + GLboolean ARB_shader_objects; + GLboolean ARB_shading_language_100; + GLboolean ARB_shadow; + GLboolean ARB_texture_border_clamp; + GLboolean ARB_texture_compression; + GLboolean ARB_texture_cube_map; + GLboolean ARB_texture_env_combine; + GLboolean ARB_texture_env_crossbar; + GLboolean ARB_texture_env_dot3; + GLboolean ARB_texture_float; + GLboolean ARB_texture_mirrored_repeat; + GLboolean ARB_texture_non_power_of_two; + GLboolean ARB_transpose_matrix; + GLboolean ARB_vertex_buffer_object; + GLboolean ARB_vertex_program; + GLboolean ARB_vertex_shader; + GLboolean ARB_window_pos; + GLboolean EXT_abgr; + GLboolean EXT_bgra; + GLboolean EXT_blend_color; + GLboolean EXT_blend_equation_separate; + GLboolean EXT_blend_func_separate; + GLboolean EXT_blend_logic_op; + GLboolean EXT_blend_minmax; + GLboolean EXT_blend_subtract; + GLboolean EXT_clip_volume_hint; + GLboolean EXT_cull_vertex; + GLboolean EXT_convolution; + GLboolean EXT_compiled_vertex_array; + GLboolean EXT_copy_texture; + GLboolean EXT_depth_bounds_test; + GLboolean EXT_draw_range_elements; + GLboolean EXT_framebuffer_object; + GLboolean EXT_fog_coord; + GLboolean EXT_histogram; + GLboolean EXT_multi_draw_arrays; + GLboolean EXT_paletted_texture; + GLboolean EXT_packed_pixels; + GLboolean EXT_pixel_buffer_object; + GLboolean EXT_point_parameters; + GLboolean EXT_polygon_offset; + GLboolean EXT_rescale_normal; + GLboolean EXT_shadow_funcs; + GLboolean EXT_secondary_color; + GLboolean EXT_separate_specular_color; + GLboolean EXT_shared_texture_palette; + GLboolean EXT_stencil_wrap; + GLboolean EXT_stencil_two_side; + GLboolean EXT_subtexture; + GLboolean EXT_texture; + GLboolean EXT_texture_object; + GLboolean EXT_texture3D; + GLboolean EXT_texture_compression_s3tc; + GLboolean EXT_texture_env_add; + GLboolean EXT_texture_env_combine; + GLboolean EXT_texture_env_dot3; + GLboolean EXT_texture_filter_anisotropic; + GLboolean EXT_texture_lod_bias; + GLboolean EXT_texture_mirror_clamp; + GLboolean EXT_vertex_array; + GLboolean EXT_vertex_array_set; + /* vendor extensions */ + GLboolean APPLE_client_storage; + GLboolean APPLE_packed_pixels; + GLboolean ATI_texture_mirror_once; + GLboolean ATI_texture_env_combine3; + GLboolean ATI_fragment_shader; + GLboolean HP_occlusion_test; + GLboolean IBM_rasterpos_clip; + GLboolean IBM_multimode_draw_arrays; + GLboolean MESA_pack_invert; + GLboolean MESA_packed_depth_stencil; + GLboolean MESA_program_debug; + GLboolean MESA_resize_buffers; + GLboolean MESA_ycbcr_texture; + GLboolean NV_blend_square; + GLboolean NV_fragment_program; + GLboolean NV_light_max_exponent; + GLboolean NV_point_sprite; + GLboolean NV_texgen_reflection; + GLboolean NV_texture_rectangle; + GLboolean NV_vertex_program; + GLboolean NV_vertex_program1_1; + GLboolean OES_read_format; + GLboolean SGI_color_matrix; + GLboolean SGI_color_table; + GLboolean SGI_texture_color_table; + GLboolean SGIS_generate_mipmap; + GLboolean SGIS_pixel_texture; + GLboolean SGIS_texture_edge_clamp; + GLboolean SGIS_texture_lod; + GLboolean SGIX_depth_texture; + GLboolean SGIX_pixel_texture; + GLboolean SGIX_shadow; + GLboolean SGIX_shadow_ambient; /* or GL_ARB_shadow_ambient */ + GLboolean TDFX_texture_compression_FXT1; + GLboolean S3_s3tc; + /*@}*/ + /* The extension string */ + const GLubyte *String; +}; + + +/** + * A stack of matrices (projection, modelview, color, texture, etc). + */ +struct matrix_stack +{ + GLmatrix *Top; /**< points into Stack */ + GLmatrix *Stack; /**< array [MaxDepth] of GLmatrix */ + GLuint Depth; /**< 0 <= Depth < MaxDepth */ + GLuint MaxDepth; /**< size of Stack[] array */ + GLuint DirtyFlag; /**< _NEW_MODELVIEW or _NEW_PROJECTION, for example */ +}; + + +/** + * \name Bits for image transfer operations + * + * \sa __GLcontextRec::ImageTransferState. + */ +/*@{*/ +#define IMAGE_SCALE_BIAS_BIT 0x1 +#define IMAGE_SHIFT_OFFSET_BIT 0x2 +#define IMAGE_MAP_COLOR_BIT 0x4 +#define IMAGE_COLOR_TABLE_BIT 0x8 +#define IMAGE_CONVOLUTION_BIT 0x10 +#define IMAGE_POST_CONVOLUTION_SCALE_BIAS 0x20 +#define IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT 0x40 +#define IMAGE_COLOR_MATRIX_BIT 0x80 +#define IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT 0x100 +#define IMAGE_HISTOGRAM_BIT 0x200 +#define IMAGE_MIN_MAX_BIT 0x400 +#define IMAGE_CLAMP_BIT 0x800 /* extra */ + + +/** Pixel Transfer ops up to convolution */ +#define IMAGE_PRE_CONVOLUTION_BITS (IMAGE_SCALE_BIAS_BIT | \ + IMAGE_SHIFT_OFFSET_BIT | \ + IMAGE_MAP_COLOR_BIT | \ + IMAGE_COLOR_TABLE_BIT) + +/** Pixel transfer ops after convolution */ +#define IMAGE_POST_CONVOLUTION_BITS (IMAGE_POST_CONVOLUTION_SCALE_BIAS | \ + IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT | \ + IMAGE_COLOR_MATRIX_BIT | \ + IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT |\ + IMAGE_HISTOGRAM_BIT | \ + IMAGE_MIN_MAX_BIT) +/*@}*/ + + +/** + * \name Bits to indicate what state has changed. + * + * 4 unused flags. + */ +/*@{*/ +#define _NEW_MODELVIEW 0x1 /**< __GLcontextRec::ModelView */ +#define _NEW_PROJECTION 0x2 /**< __GLcontextRec::Projection */ +#define _NEW_TEXTURE_MATRIX 0x4 /**< __GLcontextRec::TextureMatrix */ +#define _NEW_COLOR_MATRIX 0x8 /**< __GLcontextRec::ColorMatrix */ +#define _NEW_ACCUM 0x10 /**< __GLcontextRec::Accum */ +#define _NEW_COLOR 0x20 /**< __GLcontextRec::Color */ +#define _NEW_DEPTH 0x40 /**< __GLcontextRec::Depth */ +#define _NEW_EVAL 0x80 /**< __GLcontextRec::Eval, __GLcontextRec::EvalMap */ +#define _NEW_FOG 0x100 /**< __GLcontextRec::Fog */ +#define _NEW_HINT 0x200 /**< __GLcontextRec::Hint */ +#define _NEW_LIGHT 0x400 /**< __GLcontextRec::Light */ +#define _NEW_LINE 0x800 /**< __GLcontextRec::Line */ +#define _NEW_PIXEL 0x1000 /**< __GLcontextRec::Pixel */ +#define _NEW_POINT 0x2000 /**< __GLcontextRec::Point */ +#define _NEW_POLYGON 0x4000 /**< __GLcontextRec::Polygon */ +#define _NEW_POLYGONSTIPPLE 0x8000 /**< __GLcontextRec::PolygonStipple */ +#define _NEW_SCISSOR 0x10000 /**< __GLcontextRec::Scissor */ +#define _NEW_STENCIL 0x20000 /**< __GLcontextRec::Stencil */ +#define _NEW_TEXTURE 0x40000 /**< __GLcontextRec::Texture */ +#define _NEW_TRANSFORM 0x80000 /**< __GLcontextRec::Transform */ +#define _NEW_VIEWPORT 0x100000 /**< __GLcontextRec::Viewport */ +#define _NEW_PACKUNPACK 0x200000 /**< __GLcontextRec::Pack, __GLcontextRec::Unpack */ +#define _NEW_ARRAY 0x400000 /**< __GLcontextRec::Array */ +#define _NEW_RENDERMODE 0x800000 /**< __GLcontextRec::RenderMode, __GLcontextRec::Feedback, __GLcontextRec::Select */ +#define _NEW_BUFFERS 0x1000000 /**< __GLcontextRec::Visual, __GLcontextRec::DrawBuffer, */ +#define _NEW_MULTISAMPLE 0x2000000 /**< __GLcontextRec::Multisample */ +#define _NEW_TRACK_MATRIX 0x4000000 /**< __GLcontextRec::VertexProgram */ +#define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */ +#define _NEW_ALL ~0 +/*@}*/ + + +/** + * \name Bits to track array state changes + * + * Also used to summarize array enabled. + */ +/*@{*/ +#define _NEW_ARRAY_VERTEX VERT_BIT_POS +#define _NEW_ARRAY_WEIGHT VERT_BIT_WEIGHT +#define _NEW_ARRAY_NORMAL VERT_BIT_NORMAL +#define _NEW_ARRAY_COLOR0 VERT_BIT_COLOR0 +#define _NEW_ARRAY_COLOR1 VERT_BIT_COLOR1 +#define _NEW_ARRAY_FOGCOORD VERT_BIT_FOG +#define _NEW_ARRAY_INDEX VERT_BIT_SIX +#define _NEW_ARRAY_EDGEFLAG VERT_BIT_SEVEN +#define _NEW_ARRAY_TEXCOORD_0 VERT_BIT_TEX0 +#define _NEW_ARRAY_TEXCOORD_1 VERT_BIT_TEX1 +#define _NEW_ARRAY_TEXCOORD_2 VERT_BIT_TEX2 +#define _NEW_ARRAY_TEXCOORD_3 VERT_BIT_TEX3 +#define _NEW_ARRAY_TEXCOORD_4 VERT_BIT_TEX4 +#define _NEW_ARRAY_TEXCOORD_5 VERT_BIT_TEX5 +#define _NEW_ARRAY_TEXCOORD_6 VERT_BIT_TEX6 +#define _NEW_ARRAY_TEXCOORD_7 VERT_BIT_TEX7 +#define _NEW_ARRAY_ATTRIB_0 0x10000 /* start at bit 16 */ +#define _NEW_ARRAY_ALL 0xffffffff + + +#define _NEW_ARRAY_TEXCOORD(i) (_NEW_ARRAY_TEXCOORD_0 << (i)) +#define _NEW_ARRAY_ATTRIB(i) (_NEW_ARRAY_ATTRIB_0 << (i)) +/*@}*/ + + +/** + * \name A bunch of flags that we think might be useful to drivers. + * + * Set in the __GLcontextRec::_TriangleCaps bitfield. + */ +/*@{*/ +#define DD_FLATSHADE 0x1 +#define DD_SEPARATE_SPECULAR 0x2 +#define DD_TRI_CULL_FRONT_BACK 0x4 /* special case on some hw */ +#define DD_TRI_LIGHT_TWOSIDE 0x8 +#define DD_TRI_UNFILLED 0x10 +#define DD_TRI_SMOOTH 0x20 +#define DD_TRI_STIPPLE 0x40 +#define DD_TRI_OFFSET 0x80 +#define DD_LINE_SMOOTH 0x100 +#define DD_LINE_STIPPLE 0x200 +#define DD_LINE_WIDTH 0x400 +#define DD_POINT_SMOOTH 0x800 +#define DD_POINT_SIZE 0x1000 +#define DD_POINT_ATTEN 0x2000 +#define DD_TRI_TWOSTENCIL 0x4000 +/*@}*/ + + +/** + * \name Define the state changes under which each of these bits might change + */ +/*@{*/ +#define _DD_NEW_FLATSHADE _NEW_LIGHT +#define _DD_NEW_SEPARATE_SPECULAR (_NEW_LIGHT | _NEW_FOG | _NEW_PROGRAM) +#define _DD_NEW_TRI_CULL_FRONT_BACK _NEW_POLYGON +#define _DD_NEW_TRI_LIGHT_TWOSIDE _NEW_LIGHT +#define _DD_NEW_TRI_UNFILLED _NEW_POLYGON +#define _DD_NEW_TRI_SMOOTH _NEW_POLYGON +#define _DD_NEW_TRI_STIPPLE _NEW_POLYGON +#define _DD_NEW_TRI_OFFSET _NEW_POLYGON +#define _DD_NEW_LINE_SMOOTH _NEW_LINE +#define _DD_NEW_LINE_STIPPLE _NEW_LINE +#define _DD_NEW_LINE_WIDTH _NEW_LINE +#define _DD_NEW_POINT_SMOOTH _NEW_POINT +#define _DD_NEW_POINT_SIZE _NEW_POINT +#define _DD_NEW_POINT_ATTEN _NEW_POINT +/*@}*/ + + +#define _MESA_NEW_NEED_EYE_COORDS (_NEW_LIGHT | \ + _NEW_TEXTURE | \ + _NEW_POINT | \ + _NEW_MODELVIEW) + +#define _MESA_NEW_NEED_NORMALS (_NEW_LIGHT | \ + _NEW_TEXTURE) + +#define _IMAGE_NEW_TRANSFER_STATE (_NEW_PIXEL | _NEW_COLOR_MATRIX) + + + + +/* + * Forward declaration of display list data types: + */ +union node; +typedef union node Node; + + +/* This has to be included here. */ +#include "dd.h" + + +#define NUM_VERTEX_FORMAT_ENTRIES (sizeof(GLvertexformat) / sizeof(void *)) + +/** + * Core Mesa's support for tnl modules: + */ +struct gl_tnl_module +{ + /** + * Vertex format to be lazily swapped into current dispatch. + */ + const GLvertexformat *Current; + + /** + * \name Record of functions swapped out. + * On restore, only need to swap these functions back in. + */ + /*@{*/ + struct { + _glapi_proc * location; + _glapi_proc function; + } Swapped[NUM_VERTEX_FORMAT_ENTRIES]; + GLuint SwapCount; + /*@}*/ +}; + +/* Strictly this is a tnl/ private concept, but it doesn't seem + * worthwhile adding a tnl private structure just to hold this one bit + * of information: + */ +#define MESA_DLIST_DANGLING_REFS 0x1 + +/* Provide a location where information about a display list can be + * collected. Could be extended with driverPrivate structures, + * etc. in the future. + */ +struct mesa_display_list +{ + Node *node; + GLuint id; + GLuint flags; +}; + + +/** + * State used during display list compilation and execution. + */ +struct mesa_list_state +{ + struct mesa_display_list *CallStack[MAX_LIST_NESTING]; + GLuint CallDepth; /**< Current recursion calling depth */ + + struct mesa_display_list *CurrentList; + Node *CurrentListPtr; /**< Head of list being compiled */ + GLuint CurrentListNum; /**< Number of the list being compiled */ + Node *CurrentBlock; /**< Pointer to current block of nodes */ + GLuint CurrentPos; /**< Index into current block of nodes */ + + GLvertexformat ListVtxfmt; + + GLubyte ActiveAttribSize[VERT_ATTRIB_MAX]; + GLfloat CurrentAttrib[VERT_ATTRIB_MAX][4]; + + GLubyte ActiveMaterialSize[MAT_ATTRIB_MAX]; + GLfloat CurrentMaterial[MAT_ATTRIB_MAX][4]; + + GLubyte ActiveIndex; + GLfloat CurrentIndex; + + GLubyte ActiveEdgeFlag; + GLboolean CurrentEdgeFlag; +}; + + +/** + * Mesa rendering context. + * + * This is the central context data structure for Mesa. Almost all + * OpenGL state is contained in this structure. + * Think of this as a base class from which device drivers will derive + * sub classes. + * + * The GLcontext typedef names this structure. + */ +struct __GLcontextRec +{ + /** + * \name OS related interfaces. + * + * These \b must be the first members of this structure, because they are + * exposed to the outside world (i.e. GLX extension). + */ + /*@{*/ + __GLimports imports; + __GLexports exports; + /*@}*/ + + /** State possibly shared with other contexts in the address space */ + struct gl_shared_state *Shared; + + /** \name API function pointer tables */ + /*@{*/ + struct _glapi_table *Save; /**< Display list save functions */ + struct _glapi_table *Exec; /**< Execute functions */ + struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */ + /*@}*/ + + GLvisual Visual; + GLframebuffer *DrawBuffer; /**< buffer for writing */ + GLframebuffer *ReadBuffer; /**< buffer for reading */ + GLframebuffer *WinSysDrawBuffer; /**< set with MakeCurrent */ + GLframebuffer *WinSysReadBuffer; /**< set with MakeCurrent */ + + /** + * Device driver function pointer table + */ + struct dd_function_table Driver; + + void *DriverCtx; /**< Points to device driver context/state */ + void *DriverMgrCtx; /**< Points to device driver manager (optional)*/ + + /** Core/Driver constants */ + struct gl_constants Const; + + /** \name The various 4x4 matrix stacks */ + /*@{*/ + struct matrix_stack ModelviewMatrixStack; + struct matrix_stack ProjectionMatrixStack; + struct matrix_stack ColorMatrixStack; + struct matrix_stack TextureMatrixStack[MAX_TEXTURE_COORD_UNITS]; + struct matrix_stack ProgramMatrixStack[MAX_PROGRAM_MATRICES]; + struct matrix_stack *CurrentStack; /**< Points to one of the above stacks */ + /*@}*/ + + /** Combined modelview and projection matrix */ + GLmatrix _ModelProjectMatrix; + + /** \name Display lists */ + struct mesa_list_state ListState; + + GLboolean ExecuteFlag; /**< Execute GL commands? */ + GLboolean CompileFlag; /**< Compile GL commands into display list? */ + + /** Extensions */ + struct gl_extensions Extensions; + + /** \name Renderer attribute stack */ + /*@{*/ + GLuint AttribStackDepth; + struct gl_attrib_node *AttribStack[MAX_ATTRIB_STACK_DEPTH]; + /*@}*/ + + /** \name Renderer attribute groups + * + * We define a struct for each attribute group to make pushing and popping + * attributes easy. Also it's a good organization. + */ + /*@{*/ + struct gl_accum_attrib Accum; /**< Accumulation buffer attributes */ + struct gl_colorbuffer_attrib Color; /**< Color buffers attributes */ + struct gl_current_attrib Current; /**< Current attributes */ + struct gl_depthbuffer_attrib Depth; /**< Depth buffer attributes */ + struct gl_eval_attrib Eval; /**< Eval attributes */ + struct gl_fog_attrib Fog; /**< Fog attributes */ + struct gl_hint_attrib Hint; /**< Hint attributes */ + struct gl_light_attrib Light; /**< Light attributes */ + struct gl_line_attrib Line; /**< Line attributes */ + struct gl_list_attrib List; /**< List attributes */ + struct gl_multisample_attrib Multisample; + struct gl_pixel_attrib Pixel; /**< Pixel attributes */ + struct gl_point_attrib Point; /**< Point attributes */ + struct gl_polygon_attrib Polygon; /**< Polygon attributes */ + GLuint PolygonStipple[32]; /**< Polygon stipple */ + struct gl_scissor_attrib Scissor; /**< Scissor attributes */ + struct gl_stencil_attrib Stencil; /**< Stencil buffer attributes */ + struct gl_texture_attrib Texture; /**< Texture attributes */ + struct gl_transform_attrib Transform; /**< Transformation attributes */ + struct gl_viewport_attrib Viewport; /**< Viewport attributes */ + /*@}*/ + + /** \name Client attribute stack */ + /*@{*/ + GLuint ClientAttribStackDepth; + struct gl_attrib_node *ClientAttribStack[MAX_CLIENT_ATTRIB_STACK_DEPTH]; + /*@}*/ + + /** \name Client attribute groups */ + /*@{*/ + struct gl_array_attrib Array; /**< Vertex arrays */ + struct gl_pixelstore_attrib Pack; /**< Pixel packing */ + struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */ + struct gl_pixelstore_attrib DefaultPacking; /**< Default params */ + /*@}*/ + + /** \name Other assorted state (not pushed/popped on attribute stack) */ + /*@{*/ + struct gl_histogram_attrib Histogram; + struct gl_minmax_attrib MinMax; + struct gl_convolution_attrib Convolution1D; + struct gl_convolution_attrib Convolution2D; + struct gl_convolution_attrib Separable2D; + + struct gl_evaluators EvalMap; /**< All evaluators */ + struct gl_feedback Feedback; /**< Feedback */ + struct gl_selection Select; /**< Selection */ + + struct gl_color_table ColorTable; /**< Pre-convolution */ + struct gl_color_table ProxyColorTable; /**< Pre-convolution */ + struct gl_color_table PostConvolutionColorTable; + struct gl_color_table ProxyPostConvolutionColorTable; + struct gl_color_table PostColorMatrixColorTable; + struct gl_color_table ProxyPostColorMatrixColorTable; + + struct gl_program_state Program; /**< for vertex or fragment progs */ + struct gl_vertex_program_state VertexProgram; /**< GL_NV_vertex_program */ + struct gl_fragment_program_state FragmentProgram; /**< GL_NV_fragment_program */ + struct gl_ati_fragment_shader_state ATIFragmentShader; /**< GL_ATI_fragment_shader */ + + struct fragment_program *_TexEnvProgram; /**< Texture state as fragment program */ + struct vertex_program *_TnlProgram; /**< Fixed func TNL state as vertex program */ + + GLboolean _MaintainTexEnvProgram; + GLboolean _MaintainTnlProgram; + + struct gl_occlusion_state Occlusion; /**< GL_ARB_occlusion_query */ + + struct gl_shader_objects_state ShaderObjects; /* GL_ARB_shader_objects */ + /*@}*/ + +#if FEATURE_EXT_framebuffer_object + /*struct gl_framebuffer *CurrentFramebuffer;*/ + struct gl_renderbuffer *CurrentRenderbuffer; +#endif + + GLenum ErrorValue; /**< Last error code */ + GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */ + GLuint NewState; /**< bitwise-or of _NEW_* flags */ + + /** \name Derived state */ + /*@{*/ + GLuint _TriangleCaps; /**< bitwise-or of DD_* flags */ + GLuint _ImageTransferState;/**< bitwise-or of IMAGE_*_BIT flags */ + GLfloat _EyeZDir[3]; + GLfloat _ModelViewInvScale; + GLuint _NeedEyeCoords; + GLuint _ForceEyeCoords; + GLboolean _RotateMode; + GLenum _CurrentProgram; /* currently executing program */ + + struct gl_shine_tab *_ShineTable[2]; /**< Active shine tables */ + struct gl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */ + /**@}*/ + + struct gl_list_extensions ListExt; /**< driver dlist extensions */ + + + GLboolean OcclusionResult; /**< for GL_HP_occlusion_test */ + GLboolean OcclusionResultSaved; /**< for GL_HP_occlusion_test */ + GLuint _Facing; /**< This is a hack for 2-sided stencil test. + * + * We don't have a better way to communicate this value from + * swrast_setup to swrast. */ + + /** \name Color clamping (tentative part of GL_ARB_color_clamp_control) */ + /*@{*/ + GLboolean ClampFragmentColors; + GLboolean ClampVertexColors; + /*@}*/ + + /** \name For debugging/development only */ + /*@{*/ + GLboolean FirstTimeCurrent; + /*@}*/ + + /** Dither disable via MESA_NO_DITHER env var */ + GLboolean NoDither; + + /** software compression/decompression supported or not */ + GLboolean Mesa_DXTn; + + /** Core tnl module support */ + struct gl_tnl_module TnlModule; + + /** + * \name Hooks for module contexts. + * + * These will eventually live in the driver or elsewhere. + */ + /*@{*/ + void *swrast_context; + void *swsetup_context; + void *swtnl_context; + void *swtnl_im; + void *acache_context; + void *aelt_context; + /*@}*/ +}; + + +/** The string names for GL_POINT, GL_LINE_LOOP, etc */ +extern const char *_mesa_prim_name[GL_POLYGON+4]; + + +#ifdef MESA_DEBUG +extern int MESA_VERBOSE; +extern int MESA_DEBUG_FLAGS; +# define MESA_FUNCTION __FUNCTION__ +#else +# define MESA_VERBOSE 0 +# define MESA_DEBUG_FLAGS 0 +# define MESA_FUNCTION "a function" +# ifndef NDEBUG +# define NDEBUG +# endif +#endif + + +enum _verbose +{ + VERBOSE_VARRAY = 0x0001, + VERBOSE_TEXTURE = 0x0002, + VERBOSE_IMMEDIATE = 0x0004, + VERBOSE_PIPELINE = 0x0008, + VERBOSE_DRIVER = 0x0010, + VERBOSE_STATE = 0x0020, + VERBOSE_API = 0x0040, + VERBOSE_DISPLAY_LIST = 0x0100, + VERBOSE_LIGHTING = 0x0200, + VERBOSE_PRIMS = 0x0400, + VERBOSE_VERTS = 0x0800, + VERBOSE_DISASSEM = 0x1000 +}; + + +enum _debug +{ + DEBUG_ALWAYS_FLUSH = 0x1 +}; + + + +#define Elements(x) sizeof(x)/sizeof(*(x)) + + +#endif /* TYPES_H */ diff --git a/src/mesa/main/occlude.c b/src/mesa/main/occlude.c new file mode 100644 index 00000000000..bc61a475d66 --- /dev/null +++ b/src/mesa/main/occlude.c @@ -0,0 +1,353 @@ +/* + * Mesa 3-D graphics library + * Version: 6.0.2 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Functions to implement the GL_ARB_occlusion_query extension. + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "occlude.h" +#include "mtypes.h" + + +struct occlusion_query +{ + GLenum Target; + GLuint Id; + GLuint PassedCounter; + GLboolean Active; +}; + + +/** + * Allocate a new occlusion query object. + * \param target - must be GL_SAMPLES_PASSED_ARB at this time + * \param id - the object's ID + * \return pointer to new occlusion_query object or NULL if out of memory. + */ +static struct occlusion_query * +new_query_object(GLenum target, GLuint id) +{ + struct occlusion_query *q = MALLOC_STRUCT(occlusion_query); + if (q) { + q->Target = target; + q->Id = id; + q->PassedCounter = 0; + q->Active = GL_FALSE; + } + return q; +} + + +/** + * Delete an occlusion query object. + */ +static void +delete_query_object(struct occlusion_query *q) +{ + FREE(q); +} + + +void GLAPIENTRY +_mesa_GenQueriesARB(GLsizei n, GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenQueriesARB(n < 0)"); + return; + } + + if (ctx->Occlusion.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGenQueriesARB"); + return; + } + + first = _mesa_HashFindFreeKeyBlock(ctx->Occlusion.QueryObjects, n); + if (first) { + GLsizei i; + for (i = 0; i < n; i++) { + struct occlusion_query *q = new_query_object(GL_SAMPLES_PASSED_ARB, + first + i); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenQueriesARB"); + return; + } + ids[i] = first + i; + _mesa_HashInsert(ctx->Occlusion.QueryObjects, first + i, q); + } + } +} + + +void GLAPIENTRY +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteQueriesARB(n < 0)"); + return; + } + + if (ctx->Occlusion.Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteQueriesARB"); + return; + } + + for (i = 0; i < n; i++) { + if (ids[i] > 0) { + struct occlusion_query *q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, ids[i]); + if (q) { + _mesa_HashRemove(ctx->Occlusion.QueryObjects, ids[i]); + delete_query_object(q); + } + } + } +} + + +GLboolean GLAPIENTRY +_mesa_IsQueryARB(GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (id && _mesa_HashLookup(ctx->Occlusion.QueryObjects, id)) + return GL_TRUE; + else + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_BeginQueryARB(GLenum target, GLuint id) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + if (target != GL_SAMPLES_PASSED_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBeginQueryARB(target)"); + return; + } + + if (id == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(id==0)"); + return; + } + + if (ctx->Occlusion.CurrentQueryObject) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB(target)"); + return; + } + + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, id); + if (q && q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginQueryARB"); + return; + } + else if (!q) { + q = new_query_object(target, id); + if (!q) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBeginQueryARB"); + return; + } + _mesa_HashInsert(ctx->Occlusion.QueryObjects, id, q); + } + + q->Active = GL_TRUE; + q->PassedCounter = 0; + ctx->Occlusion.Active = GL_TRUE; + ctx->Occlusion.CurrentQueryObject = id; + ctx->Occlusion.PassedCounter = 0; +} + + +void GLAPIENTRY +_mesa_EndQueryARB(GLenum target) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + FLUSH_VERTICES(ctx, _NEW_DEPTH); + + if (target != GL_SAMPLES_PASSED_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glEndQueryARB(target)"); + return; + } + + if (ctx->Occlusion.CurrentQueryObject) + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, + ctx->Occlusion.CurrentQueryObject); + if (!q || !q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glEndQuery with no glBeginQuery"); + return; + } + + q->PassedCounter = ctx->Occlusion.PassedCounter; + q->Active = GL_FALSE; + ctx->Occlusion.Active = GL_FALSE; + ctx->Occlusion.CurrentQueryObject = 0; +} + + +void GLAPIENTRY +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_SAMPLES_PASSED_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(target)"); + return; + } + + switch (pname) { + case GL_QUERY_COUNTER_BITS_ARB: + *params = 8 * sizeof(GLuint); + break; + case GL_CURRENT_QUERY_ARB: + *params = ctx->Occlusion.CurrentQueryObject; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryivARB(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id) + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, id); + + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectivARB(id=%d)", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + *params = q->PassedCounter; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = GL_TRUE; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectivARB(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct occlusion_query *q = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (id) + q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, id); + if (!q || q->Active) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetQueryObjectuivARB(id=%d", id); + return; + } + + switch (pname) { + case GL_QUERY_RESULT_ARB: + *params = q->PassedCounter; + break; + case GL_QUERY_RESULT_AVAILABLE_ARB: + /* XXX revisit when we have a hardware implementation! */ + *params = GL_TRUE; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetQueryObjectuivARB(pname)"); + return; + } +} + + + +/** + * Allocate/init the context state related to occlusion query objects. + */ +void +_mesa_init_occlude(GLcontext *ctx) +{ +#if FEATURE_ARB_occlusion_query + ctx->Occlusion.QueryObjects = _mesa_NewHashTable(); +#endif + ctx->OcclusionResult = GL_FALSE; + ctx->OcclusionResultSaved = GL_FALSE; +} + + +/** + * Free the context state related to occlusion query objects. + */ +void +_mesa_free_occlude_data(GLcontext *ctx) +{ + while (1) { + GLuint query = _mesa_HashFirstEntry(ctx->Occlusion.QueryObjects); + if (query) { + struct occlusion_query *q = (struct occlusion_query *) + _mesa_HashLookup(ctx->Occlusion.QueryObjects, query); + ASSERT(q); + delete_query_object(q); + _mesa_HashRemove(ctx->Occlusion.QueryObjects, query); + } + else { + break; + } + } + _mesa_DeleteHashTable(ctx->Occlusion.QueryObjects); +} diff --git a/src/mesa/main/occlude.h b/src/mesa/main/occlude.h new file mode 100644 index 00000000000..acf19101f14 --- /dev/null +++ b/src/mesa/main/occlude.h @@ -0,0 +1,61 @@ +/* + * Mesa 3-D graphics library + * Version: 6.0.2 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef OCCLUDE_H +#define OCCLUDE_H + + +extern void +_mesa_init_occlude(GLcontext *ctx); + +extern void +_mesa_free_occlude_data(GLcontext *ctx); + +extern void GLAPIENTRY +_mesa_GenQueriesARB(GLsizei n, GLuint *ids); + +extern void GLAPIENTRY +_mesa_DeleteQueriesARB(GLsizei n, const GLuint *ids); + +extern GLboolean GLAPIENTRY +_mesa_IsQueryARB(GLuint id); + +extern void GLAPIENTRY +_mesa_BeginQueryARB(GLenum target, GLuint id); + +extern void GLAPIENTRY +_mesa_EndQueryARB(GLenum target); + +extern void GLAPIENTRY +_mesa_GetQueryivARB(GLenum target, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params); + +extern void GLAPIENTRY +_mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params); + + +#endif /* OCCLUDE_H */ diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c new file mode 100644 index 00000000000..e8912c70029 --- /dev/null +++ b/src/mesa/main/pixel.c @@ -0,0 +1,2119 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "glheader.h" +#include "bufferobj.h" +#include "colormac.h" +#include "context.h" +#include "image.h" +#include "macros.h" +#include "pixel.h" +#include "mtypes.h" + + +/**********************************************************************/ +/***** glPixelZoom *****/ +/**********************************************************************/ + + + +void GLAPIENTRY +_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor ) +{ + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Pixel.ZoomX == xfactor && + ctx->Pixel.ZoomY == yfactor) + return; + + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.ZoomX = xfactor; + ctx->Pixel.ZoomY = yfactor; +} + + + +/**********************************************************************/ +/***** glPixelStore *****/ +/**********************************************************************/ + + +void GLAPIENTRY +_mesa_PixelStorei( GLenum pname, GLint param ) +{ + /* NOTE: this call can't be compiled into the display list */ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (pname) { + case GL_PACK_SWAP_BYTES: + if (param == (GLint)ctx->Pack.SwapBytes) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE; + break; + case GL_PACK_LSB_FIRST: + if (param == (GLint)ctx->Pack.LsbFirst) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE; + break; + case GL_PACK_ROW_LENGTH: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Pack.RowLength == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.RowLength = param; + break; + case GL_PACK_IMAGE_HEIGHT: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Pack.ImageHeight == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.ImageHeight = param; + break; + case GL_PACK_SKIP_PIXELS: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Pack.SkipPixels == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.SkipPixels = param; + break; + case GL_PACK_SKIP_ROWS: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Pack.SkipRows == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.SkipRows = param; + break; + case GL_PACK_SKIP_IMAGES: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Pack.SkipImages == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.SkipImages = param; + break; + case GL_PACK_ALIGNMENT: + if (param!=1 && param!=2 && param!=4 && param!=8) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Pack.Alignment == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.Alignment = param; + break; + case GL_PACK_INVERT_MESA: + if (!ctx->Extensions.MESA_pack_invert) { + _mesa_error( ctx, GL_INVALID_ENUM, "glPixelstore(pname)" ); + return; + } + if (ctx->Pack.Invert == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Pack.Invert = param; + break; + + case GL_UNPACK_SWAP_BYTES: + if (param == (GLint)ctx->Unpack.SwapBytes) + return; + if ((GLint)ctx->Unpack.SwapBytes == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE; + break; + case GL_UNPACK_LSB_FIRST: + if (param == (GLint)ctx->Unpack.LsbFirst) + return; + if ((GLint)ctx->Unpack.LsbFirst == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE; + break; + case GL_UNPACK_ROW_LENGTH: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Unpack.RowLength == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.RowLength = param; + break; + case GL_UNPACK_IMAGE_HEIGHT: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Unpack.ImageHeight == param) + return; + + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.ImageHeight = param; + break; + case GL_UNPACK_SKIP_PIXELS: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Unpack.SkipPixels == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.SkipPixels = param; + break; + case GL_UNPACK_SKIP_ROWS: + if (param<0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Unpack.SkipRows == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.SkipRows = param; + break; + case GL_UNPACK_SKIP_IMAGES: + if (param < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" ); + return; + } + if (ctx->Unpack.SkipImages == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.SkipImages = param; + break; + case GL_UNPACK_ALIGNMENT: + if (param!=1 && param!=2 && param!=4 && param!=8) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelStore" ); + return; + } + if (ctx->Unpack.Alignment == param) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.Alignment = param; + break; + case GL_UNPACK_CLIENT_STORAGE_APPLE: + if (param == (GLint)ctx->Unpack.ClientStorage) + return; + FLUSH_VERTICES(ctx, _NEW_PACKUNPACK); + ctx->Unpack.ClientStorage = param ? GL_TRUE : GL_FALSE; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glPixelStore" ); + return; + } +} + + +void GLAPIENTRY +_mesa_PixelStoref( GLenum pname, GLfloat param ) +{ + _mesa_PixelStorei( pname, (GLint) param ); +} + + + +/**********************************************************************/ +/***** glPixelMap *****/ +/**********************************************************************/ + + +/** + * Helper routine used by the other _mesa_PixelMap() functions. + */ +static void +pixelmap(GLcontext *ctx, GLenum map, GLsizei mapsize, const GLfloat *values) +{ + GLint i; + switch (map) { + case GL_PIXEL_MAP_S_TO_S: + ctx->Pixel.MapStoSsize = mapsize; + for (i = 0; i < mapsize; i++) { + ctx->Pixel.MapStoS[i] = IROUND(values[i]); + } + break; + case GL_PIXEL_MAP_I_TO_I: + ctx->Pixel.MapItoIsize = mapsize; + for (i = 0; i < mapsize; i++) { + ctx->Pixel.MapItoI[i] = values[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + ctx->Pixel.MapItoRsize = mapsize; + for (i = 0; i < mapsize; i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + ctx->Pixel.MapItoR[i] = val; + ctx->Pixel.MapItoR8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_I_TO_G: + ctx->Pixel.MapItoGsize = mapsize; + for (i = 0; i < mapsize; i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + ctx->Pixel.MapItoG[i] = val; + ctx->Pixel.MapItoG8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_I_TO_B: + ctx->Pixel.MapItoBsize = mapsize; + for (i = 0; i < mapsize; i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + ctx->Pixel.MapItoB[i] = val; + ctx->Pixel.MapItoB8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_I_TO_A: + ctx->Pixel.MapItoAsize = mapsize; + for (i = 0; i < mapsize; i++) { + GLfloat val = CLAMP( values[i], 0.0F, 1.0F ); + ctx->Pixel.MapItoA[i] = val; + ctx->Pixel.MapItoA8[i] = (GLint) (val * 255.0F); + } + break; + case GL_PIXEL_MAP_R_TO_R: + ctx->Pixel.MapRtoRsize = mapsize; + for (i = 0; i < mapsize; i++) { + ctx->Pixel.MapRtoR[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + ctx->Pixel.MapGtoGsize = mapsize; + for (i = 0; i < mapsize; i++) { + ctx->Pixel.MapGtoG[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + ctx->Pixel.MapBtoBsize = mapsize; + for (i = 0; i < mapsize; i++) { + ctx->Pixel.MapBtoB[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + ctx->Pixel.MapAtoAsize = mapsize; + for (i = 0; i < mapsize; i++) { + ctx->Pixel.MapAtoA[i] = CLAMP( values[i], 0.0F, 1.0F ); + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glPixelMap(map)" ); + } +} + + +void GLAPIENTRY +_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* XXX someday, test against ctx->Const.MaxPixelMapTableSize */ + if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); + return; + } + + if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) { + /* test that mapsize is a power of two */ + if (_mesa_bitcount((GLuint) mapsize) != 1) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" ); + return; + } + } + + FLUSH_VERTICES(ctx, _NEW_PIXEL); + + if (ctx->Unpack.BufferObj->Name) { + /* unpack pixelmap from PBO */ + GLubyte *buf; + /* Note, need to use DefaultPacking and Unpack's buffer object */ + ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj; + if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, + GL_INTENSITY, GL_FLOAT, values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPixelMapfv(invalid PBO access)"); + return; + } + /* restore */ + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPixelMapfv(PBO is mapped)"); + return; + } + values = (const GLfloat *) ADD_POINTERS(buf, values); + } + else if (!values) { + return; + } + + pixelmap(ctx, map, mapsize, values); + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } +} + + + +void GLAPIENTRY +_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values ) +{ + GLfloat fvalues[MAX_PIXEL_MAP_TABLE]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" ); + return; + } + + if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) { + /* test that mapsize is a power of two */ + if (_mesa_bitcount((GLuint) mapsize) != 1) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" ); + return; + } + } + + FLUSH_VERTICES(ctx, _NEW_PIXEL); + + if (ctx->Unpack.BufferObj->Name) { + /* unpack pixelmap from PBO */ + GLubyte *buf; + /* Note, need to use DefaultPacking and Unpack's buffer object */ + ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj; + if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, + GL_INTENSITY, GL_UNSIGNED_INT, values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPixelMapuiv(invalid PBO access)"); + return; + } + /* restore */ + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPixelMapuiv(PBO is mapped)"); + return; + } + values = (const GLuint *) ADD_POINTERS(buf, values); + } + else if (!values) { + return; + } + + /* convert to floats */ + if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) { + GLint i; + for (i = 0; i < mapsize; i++) { + fvalues[i] = (GLfloat) values[i]; + } + } + else { + GLint i; + for (i = 0; i < mapsize; i++) { + fvalues[i] = UINT_TO_FLOAT( values[i] ); + } + } + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } + + pixelmap(ctx, map, mapsize, fvalues); +} + + + +void GLAPIENTRY +_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values ) +{ + GLfloat fvalues[MAX_PIXEL_MAP_TABLE]; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (mapsize < 1 || mapsize > MAX_PIXEL_MAP_TABLE) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapusv(mapsize)" ); + return; + } + + if (map >= GL_PIXEL_MAP_S_TO_S && map <= GL_PIXEL_MAP_I_TO_A) { + /* test that mapsize is a power of two */ + if (_mesa_bitcount((GLuint) mapsize) != 1) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPixelMapuiv(mapsize)" ); + return; + } + } + + FLUSH_VERTICES(ctx, _NEW_PIXEL); + + if (ctx->Unpack.BufferObj->Name) { + /* unpack pixelmap from PBO */ + GLubyte *buf; + /* Note, need to use DefaultPacking and Unpack's buffer object */ + ctx->DefaultPacking.BufferObj = ctx->Unpack.BufferObj; + if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, + GL_INTENSITY, GL_UNSIGNED_SHORT, + values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPixelMapusv(invalid PBO access)"); + return; + } + /* restore */ + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPixelMapusv(PBO is mapped)"); + return; + } + values = (const GLushort *) ADD_POINTERS(buf, values); + } + else if (!values) { + return; + } + + /* convert to floats */ + if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) { + GLint i; + for (i = 0; i < mapsize; i++) { + fvalues[i] = (GLfloat) values[i]; + } + } + else { + GLint i; + for (i = 0; i < mapsize; i++) { + fvalues[i] = USHORT_TO_FLOAT( values[i] ); + } + } + + if (ctx->Unpack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } + + pixelmap(ctx, map, mapsize, fvalues); +} + + +/** + * Return size of the named map. + */ +static GLuint +get_map_size(GLcontext *ctx, GLenum map) +{ + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + return ctx->Pixel.MapItoIsize; + case GL_PIXEL_MAP_S_TO_S: + return ctx->Pixel.MapStoSsize; + case GL_PIXEL_MAP_I_TO_R: + return ctx->Pixel.MapItoRsize; + case GL_PIXEL_MAP_I_TO_G: + return ctx->Pixel.MapItoGsize; + case GL_PIXEL_MAP_I_TO_B: + return ctx->Pixel.MapItoBsize; + case GL_PIXEL_MAP_I_TO_A: + return ctx->Pixel.MapItoAsize; + case GL_PIXEL_MAP_R_TO_R: + return ctx->Pixel.MapRtoRsize; + case GL_PIXEL_MAP_G_TO_G: + return ctx->Pixel.MapGtoGsize; + case GL_PIXEL_MAP_B_TO_B: + return ctx->Pixel.MapBtoBsize; + case GL_PIXEL_MAP_A_TO_A: + return ctx->Pixel.MapAtoAsize; + default: + return 0; + } +} + + +void GLAPIENTRY +_mesa_GetPixelMapfv( GLenum map, GLfloat *values ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint mapsize, i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + mapsize = get_map_size(ctx, map); + + if (ctx->Pack.BufferObj->Name) { + /* pack pixelmap into PBO */ + GLubyte *buf; + /* Note, need to use DefaultPacking and Pack's buffer object */ + ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj; + if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, + GL_INTENSITY, GL_FLOAT, values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPixelMapfv(invalid PBO access)"); + return; + } + /* restore */ + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPixelMapfv(PBO is mapped)"); + return; + } + values = (GLfloat *) ADD_POINTERS(buf, values); + } + else if (!values) { + return; + } + + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + MEMCPY(values, ctx->Pixel.MapItoI, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_S_TO_S: + for (i = 0; i < mapsize; i++) { + values[i] = (GLfloat) ctx->Pixel.MapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + MEMCPY(values, ctx->Pixel.MapItoR, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_G: + MEMCPY(values, ctx->Pixel.MapItoG, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_B: + MEMCPY(values, ctx->Pixel.MapItoB, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_I_TO_A: + MEMCPY(values, ctx->Pixel.MapItoA, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_R_TO_R: + MEMCPY(values, ctx->Pixel.MapRtoR, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_G_TO_G: + MEMCPY(values, ctx->Pixel.MapGtoG, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_B_TO_B: + MEMCPY(values, ctx->Pixel.MapBtoB, mapsize * sizeof(GLfloat)); + break; + case GL_PIXEL_MAP_A_TO_A: + MEMCPY(values, ctx->Pixel.MapAtoA, mapsize * sizeof(GLfloat)); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + +void GLAPIENTRY +_mesa_GetPixelMapuiv( GLenum map, GLuint *values ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint mapsize, i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + mapsize = get_map_size(ctx, map); + + if (ctx->Pack.BufferObj->Name) { + /* pack pixelmap into PBO */ + GLubyte *buf; + /* Note, need to use DefaultPacking and Pack's buffer object */ + ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj; + if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, + GL_INTENSITY, GL_UNSIGNED_INT, values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPixelMapuiv(invalid PBO access)"); + return; + } + /* restore */ + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPixelMapuiv(PBO is mapped)"); + return; + } + values = (GLuint *) ADD_POINTERS(buf, values); + } + else if (!values) { + return; + } + + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoI[i] ); + } + break; + case GL_PIXEL_MAP_S_TO_S: + MEMCPY(values, ctx->Pixel.MapStoS, mapsize * sizeof(GLint)); + break; + case GL_PIXEL_MAP_I_TO_R: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoR[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_G: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoG[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_B: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoB[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_A: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoA[i] ); + } + break; + case GL_PIXEL_MAP_R_TO_R: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapRtoR[i] ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapGtoG[i] ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapBtoB[i] ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_UINT( ctx->Pixel.MapAtoA[i] ); + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + +void GLAPIENTRY +_mesa_GetPixelMapusv( GLenum map, GLushort *values ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint mapsize, i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + mapsize = get_map_size(ctx, map); + + if (ctx->Pack.BufferObj->Name) { + /* pack pixelmap into PBO */ + GLubyte *buf; + /* Note, need to use DefaultPacking and Pack's buffer object */ + ctx->DefaultPacking.BufferObj = ctx->Pack.BufferObj; + if (!_mesa_validate_pbo_access(1, &ctx->DefaultPacking, mapsize, 1, 1, + GL_INTENSITY, GL_UNSIGNED_SHORT, + values)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPixelMapusv(invalid PBO access)"); + return; + } + /* restore */ + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPixelMapusv(PBO is mapped)"); + return; + } + values = (GLushort *) ADD_POINTERS(buf, values); + } + else if (!values) { + return; + } + + switch (map) { + case GL_PIXEL_MAP_I_TO_I: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT(ctx->Pixel.MapItoI[i]); + } + break; + case GL_PIXEL_MAP_S_TO_S: + for (i = 0; i < mapsize; i++) { + values[i] = (GLushort) ctx->Pixel.MapStoS[i]; + } + break; + case GL_PIXEL_MAP_I_TO_R: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoR[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_G: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoG[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_B: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoB[i] ); + } + break; + case GL_PIXEL_MAP_I_TO_A: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoA[i] ); + } + break; + case GL_PIXEL_MAP_R_TO_R: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapRtoR[i] ); + } + break; + case GL_PIXEL_MAP_G_TO_G: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapGtoG[i] ); + } + break; + case GL_PIXEL_MAP_B_TO_B: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapBtoB[i] ); + } + break; + case GL_PIXEL_MAP_A_TO_A: + for (i = 0; i < mapsize; i++) { + values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapAtoA[i] ); + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" ); + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + + +/**********************************************************************/ +/***** glPixelTransfer *****/ +/**********************************************************************/ + + +/* + * Implements glPixelTransfer[fi] whether called immediately or from a + * display list. + */ +void GLAPIENTRY +_mesa_PixelTransferf( GLenum pname, GLfloat param ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (pname) { + case GL_MAP_COLOR: + if (ctx->Pixel.MapColorFlag == (param ? GL_TRUE : GL_FALSE)) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE; + break; + case GL_MAP_STENCIL: + if (ctx->Pixel.MapStencilFlag == (param ? GL_TRUE : GL_FALSE)) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE; + break; + case GL_INDEX_SHIFT: + if (ctx->Pixel.IndexShift == (GLint) param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.IndexShift = (GLint) param; + break; + case GL_INDEX_OFFSET: + if (ctx->Pixel.IndexOffset == (GLint) param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.IndexOffset = (GLint) param; + break; + case GL_RED_SCALE: + if (ctx->Pixel.RedScale == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.RedScale = param; + break; + case GL_RED_BIAS: + if (ctx->Pixel.RedBias == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.RedBias = param; + break; + case GL_GREEN_SCALE: + if (ctx->Pixel.GreenScale == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.GreenScale = param; + break; + case GL_GREEN_BIAS: + if (ctx->Pixel.GreenBias == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.GreenBias = param; + break; + case GL_BLUE_SCALE: + if (ctx->Pixel.BlueScale == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.BlueScale = param; + break; + case GL_BLUE_BIAS: + if (ctx->Pixel.BlueBias == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.BlueBias = param; + break; + case GL_ALPHA_SCALE: + if (ctx->Pixel.AlphaScale == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.AlphaScale = param; + break; + case GL_ALPHA_BIAS: + if (ctx->Pixel.AlphaBias == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.AlphaBias = param; + break; + case GL_DEPTH_SCALE: + if (ctx->Pixel.DepthScale == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.DepthScale = param; + break; + case GL_DEPTH_BIAS: + if (ctx->Pixel.DepthBias == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.DepthBias = param; + break; + case GL_POST_COLOR_MATRIX_RED_SCALE: + if (ctx->Pixel.PostColorMatrixScale[0] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixScale[0] = param; + break; + case GL_POST_COLOR_MATRIX_RED_BIAS: + if (ctx->Pixel.PostColorMatrixBias[0] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixBias[0] = param; + break; + case GL_POST_COLOR_MATRIX_GREEN_SCALE: + if (ctx->Pixel.PostColorMatrixScale[1] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixScale[1] = param; + break; + case GL_POST_COLOR_MATRIX_GREEN_BIAS: + if (ctx->Pixel.PostColorMatrixBias[1] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixBias[1] = param; + break; + case GL_POST_COLOR_MATRIX_BLUE_SCALE: + if (ctx->Pixel.PostColorMatrixScale[2] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixScale[2] = param; + break; + case GL_POST_COLOR_MATRIX_BLUE_BIAS: + if (ctx->Pixel.PostColorMatrixBias[2] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixBias[2] = param; + break; + case GL_POST_COLOR_MATRIX_ALPHA_SCALE: + if (ctx->Pixel.PostColorMatrixScale[3] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixScale[3] = param; + break; + case GL_POST_COLOR_MATRIX_ALPHA_BIAS: + if (ctx->Pixel.PostColorMatrixBias[3] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostColorMatrixBias[3] = param; + break; + case GL_POST_CONVOLUTION_RED_SCALE: + if (ctx->Pixel.PostConvolutionScale[0] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionScale[0] = param; + break; + case GL_POST_CONVOLUTION_RED_BIAS: + if (ctx->Pixel.PostConvolutionBias[0] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionBias[0] = param; + break; + case GL_POST_CONVOLUTION_GREEN_SCALE: + if (ctx->Pixel.PostConvolutionScale[1] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionScale[1] = param; + break; + case GL_POST_CONVOLUTION_GREEN_BIAS: + if (ctx->Pixel.PostConvolutionBias[1] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionBias[1] = param; + break; + case GL_POST_CONVOLUTION_BLUE_SCALE: + if (ctx->Pixel.PostConvolutionScale[2] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionScale[2] = param; + break; + case GL_POST_CONVOLUTION_BLUE_BIAS: + if (ctx->Pixel.PostConvolutionBias[2] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionBias[2] = param; + break; + case GL_POST_CONVOLUTION_ALPHA_SCALE: + if (ctx->Pixel.PostConvolutionScale[2] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionScale[2] = param; + break; + case GL_POST_CONVOLUTION_ALPHA_BIAS: + if (ctx->Pixel.PostConvolutionBias[2] == param) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.PostConvolutionBias[2] = param; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" ); + return; + } +} + + +void GLAPIENTRY +_mesa_PixelTransferi( GLenum pname, GLint param ) +{ + _mesa_PixelTransferf( pname, (GLfloat) param ); +} + + + +/**********************************************************************/ +/***** Pixel processing functions ******/ +/**********************************************************************/ + +/* + * Apply scale and bias factors to an array of RGBA pixels. + */ +void +_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4], + GLfloat rScale, GLfloat gScale, + GLfloat bScale, GLfloat aScale, + GLfloat rBias, GLfloat gBias, + GLfloat bBias, GLfloat aBias) +{ + if (rScale != 1.0 || rBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = rgba[i][RCOMP] * rScale + rBias; + } + } + if (gScale != 1.0 || gBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][GCOMP] = rgba[i][GCOMP] * gScale + gBias; + } + } + if (bScale != 1.0 || bBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][BCOMP] = rgba[i][BCOMP] * bScale + bBias; + } + } + if (aScale != 1.0 || aBias != 0.0) { + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][ACOMP] = rgba[i][ACOMP] * aScale + aBias; + } + } +} + + +/* + * Apply pixel mapping to an array of floating point RGBA pixels. + */ +void +_mesa_map_rgba( const GLcontext *ctx, GLuint n, GLfloat rgba[][4] ) +{ + const GLfloat rscale = (GLfloat) (ctx->Pixel.MapRtoRsize - 1); + const GLfloat gscale = (GLfloat) (ctx->Pixel.MapGtoGsize - 1); + const GLfloat bscale = (GLfloat) (ctx->Pixel.MapBtoBsize - 1); + const GLfloat ascale = (GLfloat) (ctx->Pixel.MapAtoAsize - 1); + const GLfloat *rMap = ctx->Pixel.MapRtoR; + const GLfloat *gMap = ctx->Pixel.MapGtoG; + const GLfloat *bMap = ctx->Pixel.MapBtoB; + const GLfloat *aMap = ctx->Pixel.MapAtoA; + GLuint i; + for (i=0;i<n;i++) { + GLfloat r = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); + GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); + GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); + GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); + rgba[i][RCOMP] = rMap[IROUND(r * rscale)]; + rgba[i][GCOMP] = gMap[IROUND(g * gscale)]; + rgba[i][BCOMP] = bMap[IROUND(b * bscale)]; + rgba[i][ACOMP] = aMap[IROUND(a * ascale)]; + } +} + + +/* + * Apply the color matrix and post color matrix scaling and biasing. + */ +void +_mesa_transform_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4]) +{ + const GLfloat rs = ctx->Pixel.PostColorMatrixScale[0]; + const GLfloat rb = ctx->Pixel.PostColorMatrixBias[0]; + const GLfloat gs = ctx->Pixel.PostColorMatrixScale[1]; + const GLfloat gb = ctx->Pixel.PostColorMatrixBias[1]; + const GLfloat bs = ctx->Pixel.PostColorMatrixScale[2]; + const GLfloat bb = ctx->Pixel.PostColorMatrixBias[2]; + const GLfloat as = ctx->Pixel.PostColorMatrixScale[3]; + const GLfloat ab = ctx->Pixel.PostColorMatrixBias[3]; + const GLfloat *m = ctx->ColorMatrixStack.Top->m; + GLuint i; + for (i = 0; i < n; i++) { + const GLfloat r = rgba[i][RCOMP]; + const GLfloat g = rgba[i][GCOMP]; + const GLfloat b = rgba[i][BCOMP]; + const GLfloat a = rgba[i][ACOMP]; + rgba[i][RCOMP] = (m[0] * r + m[4] * g + m[ 8] * b + m[12] * a) * rs + rb; + rgba[i][GCOMP] = (m[1] * r + m[5] * g + m[ 9] * b + m[13] * a) * gs + gb; + rgba[i][BCOMP] = (m[2] * r + m[6] * g + m[10] * b + m[14] * a) * bs + bb; + rgba[i][ACOMP] = (m[3] * r + m[7] * g + m[11] * b + m[15] * a) * as + ab; + } +} + + +/** + * Apply a color table lookup to an array of floating point RGBA colors. + */ +void +_mesa_lookup_rgba_float(const struct gl_color_table *table, + GLuint n, GLfloat rgba[][4]) +{ + if (!table->Table || table->Size == 0) + return; + + switch (table->Format) { + case GL_INTENSITY: + /* replace RGBA with I */ + if (table->Type == GL_FLOAT) { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND(rgba[i][RCOMP] * scale); + GLfloat c = lut[CLAMP(j, 0, max)]; + rgba[i][RCOMP] = rgba[i][GCOMP] = + rgba[i][BCOMP] = rgba[i][ACOMP] = c; + } + } + else { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND(rgba[i][RCOMP] * scale); + GLfloat c = CHAN_TO_FLOAT(lut[CLAMP(j, 0, max)]); + rgba[i][RCOMP] = rgba[i][GCOMP] = + rgba[i][BCOMP] = rgba[i][ACOMP] = c; + } + } + break; + case GL_LUMINANCE: + /* replace RGB with L */ + if (table->Type == GL_FLOAT) { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND(rgba[i][RCOMP] * scale); + GLfloat c = lut[CLAMP(j, 0, max)]; + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = c; + } + } + else { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND(rgba[i][RCOMP] * scale); + GLfloat c = CHAN_TO_FLOAT(lut[CLAMP(j, 0, max)]); + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = c; + } + } + break; + case GL_ALPHA: + /* replace A with A */ + if (table->Type == GL_FLOAT) { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND(rgba[i][ACOMP] * scale); + rgba[i][ACOMP] = lut[CLAMP(j, 0, max)]; + } + } + else { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND(rgba[i][ACOMP] * scale); + rgba[i][ACOMP] = CHAN_TO_FLOAT(lut[CLAMP(j, 0, max)]); + } + } + break; + case GL_LUMINANCE_ALPHA: + /* replace RGBA with LLLA */ + if (table->Type == GL_FLOAT) { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jL = IROUND(rgba[i][RCOMP] * scale); + GLint jA = IROUND(rgba[i][ACOMP] * scale); + GLfloat luminance, alpha; + jL = CLAMP(jL, 0, max); + jA = CLAMP(jA, 0, max); + luminance = lut[jL * 2 + 0]; + alpha = lut[jA * 2 + 1]; + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = luminance; + rgba[i][ACOMP] = alpha;; + } + } + else { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jL = IROUND(rgba[i][RCOMP] * scale); + GLint jA = IROUND(rgba[i][ACOMP] * scale); + GLfloat luminance, alpha; + jL = CLAMP(jL, 0, max); + jA = CLAMP(jA, 0, max); + luminance = CHAN_TO_FLOAT(lut[jL * 2 + 0]); + alpha = CHAN_TO_FLOAT(lut[jA * 2 + 1]); + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = luminance; + rgba[i][ACOMP] = alpha;; + } + } + break; + case GL_RGB: + /* replace RGB with RGB */ + if (table->Type == GL_FLOAT) { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND(rgba[i][RCOMP] * scale); + GLint jG = IROUND(rgba[i][GCOMP] * scale); + GLint jB = IROUND(rgba[i][BCOMP] * scale); + jR = CLAMP(jR, 0, max); + jG = CLAMP(jG, 0, max); + jB = CLAMP(jB, 0, max); + rgba[i][RCOMP] = lut[jR * 3 + 0]; + rgba[i][GCOMP] = lut[jG * 3 + 1]; + rgba[i][BCOMP] = lut[jB * 3 + 2]; + } + } + else { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND(rgba[i][RCOMP] * scale); + GLint jG = IROUND(rgba[i][GCOMP] * scale); + GLint jB = IROUND(rgba[i][BCOMP] * scale); + jR = CLAMP(jR, 0, max); + jG = CLAMP(jG, 0, max); + jB = CLAMP(jB, 0, max); + rgba[i][RCOMP] = CHAN_TO_FLOAT(lut[jR * 3 + 0]); + rgba[i][GCOMP] = CHAN_TO_FLOAT(lut[jG * 3 + 1]); + rgba[i][BCOMP] = CHAN_TO_FLOAT(lut[jB * 3 + 2]); + } + } + break; + case GL_RGBA: + /* replace RGBA with RGBA */ + if (table->Type == GL_FLOAT) { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND(rgba[i][RCOMP] * scale); + GLint jG = IROUND(rgba[i][GCOMP] * scale); + GLint jB = IROUND(rgba[i][BCOMP] * scale); + GLint jA = IROUND(rgba[i][ACOMP] * scale); + jR = CLAMP(jR, 0, max); + jG = CLAMP(jG, 0, max); + jB = CLAMP(jB, 0, max); + jA = CLAMP(jA, 0, max); + rgba[i][RCOMP] = lut[jR * 4 + 0]; + rgba[i][GCOMP] = lut[jG * 4 + 1]; + rgba[i][BCOMP] = lut[jB * 4 + 2]; + rgba[i][ACOMP] = lut[jA * 4 + 3]; + } + } + else { + const GLint max = table->Size - 1; + const GLfloat scale = (GLfloat) max; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND(rgba[i][RCOMP] * scale); + GLint jG = IROUND(rgba[i][GCOMP] * scale); + GLint jB = IROUND(rgba[i][BCOMP] * scale); + GLint jA = IROUND(rgba[i][ACOMP] * scale); + jR = CLAMP(jR, 0, max); + jG = CLAMP(jG, 0, max); + jB = CLAMP(jB, 0, max); + jA = CLAMP(jA, 0, max); + rgba[i][RCOMP] = CHAN_TO_FLOAT(lut[jR * 4 + 0]); + rgba[i][GCOMP] = CHAN_TO_FLOAT(lut[jG * 4 + 1]); + rgba[i][BCOMP] = CHAN_TO_FLOAT(lut[jB * 4 + 2]); + rgba[i][ACOMP] = CHAN_TO_FLOAT(lut[jA * 4 + 3]); + } + } + break; + default: + _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_float"); + return; + } +} + + + +/** + * Apply a color table lookup to an array of GLchan RGBA colors. + */ +void +_mesa_lookup_rgba_chan(const struct gl_color_table *table, + GLuint n, GLchan rgba[][4]) +{ + if (!table->Table || table->Size == 0) + return; + + switch (table->Format) { + case GL_INTENSITY: + /* replace RGBA with I */ + if (table->Type == GL_FLOAT) { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLchan c; + CLAMPED_FLOAT_TO_CHAN(c, lut[j]); + rgba[i][RCOMP] = rgba[i][GCOMP] = + rgba[i][BCOMP] = rgba[i][ACOMP] = c; + } + } + else { +#if CHAN_TYPE == GL_UNSIGNED_BYTE + if (table->Size == 256) { + /* common case */ + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + const GLchan c = lut[rgba[i][RCOMP]]; + rgba[i][RCOMP] = rgba[i][GCOMP] = + rgba[i][BCOMP] = rgba[i][ACOMP] = c; + } + } + else +#endif + { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale); + rgba[i][RCOMP] = rgba[i][GCOMP] = + rgba[i][BCOMP] = rgba[i][ACOMP] = lut[j]; + } + } + } + break; + case GL_LUMINANCE: + /* replace RGB with L */ + if (table->Type == GL_FLOAT) { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLchan c; + CLAMPED_FLOAT_TO_CHAN(c, lut[j]); + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = c; + } + } + else { +#if CHAN_TYPE == GL_UNSIGNED_BYTE + if (table->Size == 256) { + /* common case */ + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + const GLchan c = lut[rgba[i][RCOMP]]; + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = c; + } + } + else +#endif + { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND((GLfloat) rgba[i][RCOMP] * scale); + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = lut[j]; + } + } + } + break; + case GL_ALPHA: + /* replace A with A */ + if (table->Type == GL_FLOAT) { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale); + GLchan c; + CLAMPED_FLOAT_TO_CHAN(c, lut[j]); + rgba[i][ACOMP] = c; + } + } + else { +#if CHAN_TYPE == GL_UNSIGNED_BYTE + if (table->Size == 256) { + /* common case */ + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][ACOMP] = lut[rgba[i][ACOMP]]; + } + } + else +#endif + { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint j = IROUND((GLfloat) rgba[i][ACOMP] * scale); + rgba[i][ACOMP] = lut[j]; + } + } + } + break; + case GL_LUMINANCE_ALPHA: + /* replace RGBA with LLLA */ + if (table->Type == GL_FLOAT) { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale); + GLchan luminance, alpha; + CLAMPED_FLOAT_TO_CHAN(luminance, lut[jL * 2 + 0]); + CLAMPED_FLOAT_TO_CHAN(alpha, lut[jA * 2 + 1]); + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = luminance; + rgba[i][ACOMP] = alpha;; + } + } + else { +#if CHAN_TYPE == GL_UNSIGNED_BYTE + if (table->Size == 256) { + /* common case */ + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLchan l = lut[rgba[i][RCOMP] * 2 + 0]; + GLchan a = lut[rgba[i][ACOMP] * 2 + 1];; + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = l; + rgba[i][ACOMP] = a; + } + } + else +#endif + { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jL = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale); + GLchan luminance = lut[jL * 2 + 0]; + GLchan alpha = lut[jA * 2 + 1]; + rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = luminance; + rgba[i][ACOMP] = alpha; + } + } + } + break; + case GL_RGB: + /* replace RGB with RGB */ + if (table->Type == GL_FLOAT) { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale); + GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale); + CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 3 + 0]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 3 + 1]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 3 + 2]); + } + } + else { +#if CHAN_TYPE == GL_UNSIGNED_BYTE + if (table->Size == 256) { + /* common case */ + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 3 + 0]; + rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 3 + 1]; + rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 3 + 2]; + } + } + else +#endif + { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale); + GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale); + rgba[i][RCOMP] = lut[jR * 3 + 0]; + rgba[i][GCOMP] = lut[jG * 3 + 1]; + rgba[i][BCOMP] = lut[jB * 3 + 2]; + } + } + } + break; + case GL_RGBA: + /* replace RGBA with RGBA */ + if (table->Type == GL_FLOAT) { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale); + GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale); + GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale); + CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]); + } + } + else { +#if CHAN_TYPE == GL_UNSIGNED_BYTE + if (table->Size == 256) { + /* common case */ + const GLchan *lut = (const GLchan *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + rgba[i][RCOMP] = lut[rgba[i][RCOMP] * 4 + 0]; + rgba[i][GCOMP] = lut[rgba[i][GCOMP] * 4 + 1]; + rgba[i][BCOMP] = lut[rgba[i][BCOMP] * 4 + 2]; + rgba[i][ACOMP] = lut[rgba[i][ACOMP] * 4 + 3]; + } + } + else +#endif + { + const GLfloat scale = (GLfloat) (table->Size - 1) / CHAN_MAXF; + const GLfloat *lut = (const GLfloat *) table->Table; + GLuint i; + for (i = 0; i < n; i++) { + GLint jR = IROUND((GLfloat) rgba[i][RCOMP] * scale); + GLint jG = IROUND((GLfloat) rgba[i][GCOMP] * scale); + GLint jB = IROUND((GLfloat) rgba[i][BCOMP] * scale); + GLint jA = IROUND((GLfloat) rgba[i][ACOMP] * scale); + CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], lut[jR * 4 + 0]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], lut[jG * 4 + 1]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], lut[jB * 4 + 2]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], lut[jA * 4 + 3]); + } + } + } + break; + default: + _mesa_problem(NULL, "Bad format in _mesa_lookup_rgba_chan"); + return; + } +} + + + +/* + * Apply color index shift and offset to an array of pixels. + */ +void +_mesa_shift_and_offset_ci( const GLcontext *ctx, GLuint n, GLuint indexes[] ) +{ + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + GLuint i; + if (shift > 0) { + for (i=0;i<n;i++) { + indexes[i] = (indexes[i] << shift) + offset; + } + } + else if (shift < 0) { + shift = -shift; + for (i=0;i<n;i++) { + indexes[i] = (indexes[i] >> shift) + offset; + } + } + else { + for (i=0;i<n;i++) { + indexes[i] = indexes[i] + offset; + } + } +} + + +/* + * Apply color index mapping to color indexes. + */ +void +_mesa_map_ci( const GLcontext *ctx, GLuint n, GLuint index[] ) +{ + const GLuint mask = ctx->Pixel.MapItoIsize - 1; + GLuint i; + for (i = 0; i < n; i++) { + const GLuint j = index[i] & mask; + index[i] = IROUND(ctx->Pixel.MapItoI[j]); + } +} + + +/* + * Map color indexes to rgba values. + */ +void +_mesa_map_ci_to_rgba_chan( const GLcontext *ctx, GLuint n, + const GLuint index[], GLchan rgba[][4] ) +{ +#if CHAN_BITS == 8 + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLubyte *rMap = ctx->Pixel.MapItoR8; + const GLubyte *gMap = ctx->Pixel.MapItoG8; + const GLubyte *bMap = ctx->Pixel.MapItoB8; + const GLubyte *aMap = ctx->Pixel.MapItoA8; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +#else + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLfloat *rMap = ctx->Pixel.MapItoR; + const GLfloat *gMap = ctx->Pixel.MapItoG; + const GLfloat *bMap = ctx->Pixel.MapItoB; + const GLfloat *aMap = ctx->Pixel.MapItoA; + GLuint i; + for (i=0;i<n;i++) { + CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], rMap[index[i] & rmask]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], gMap[index[i] & gmask]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], bMap[index[i] & bmask]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], aMap[index[i] & amask]); + } +#endif +} + + +/* + * Map color indexes to float rgba values. + */ +void +_mesa_map_ci_to_rgba( const GLcontext *ctx, GLuint n, + const GLuint index[], GLfloat rgba[][4] ) +{ + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLfloat *rMap = ctx->Pixel.MapItoR; + const GLfloat *gMap = ctx->Pixel.MapItoG; + const GLfloat *bMap = ctx->Pixel.MapItoB; + const GLfloat *aMap = ctx->Pixel.MapItoA; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +} + + +/* + * Map 8-bit color indexes to rgb values. + */ +void +_mesa_map_ci8_to_rgba( const GLcontext *ctx, GLuint n, const GLubyte index[], + GLchan rgba[][4] ) +{ +#if CHAN_BITS == 8 + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLubyte *rMap = ctx->Pixel.MapItoR8; + const GLubyte *gMap = ctx->Pixel.MapItoG8; + const GLubyte *bMap = ctx->Pixel.MapItoB8; + const GLubyte *aMap = ctx->Pixel.MapItoA8; + GLuint i; + for (i=0;i<n;i++) { + rgba[i][RCOMP] = rMap[index[i] & rmask]; + rgba[i][GCOMP] = gMap[index[i] & gmask]; + rgba[i][BCOMP] = bMap[index[i] & bmask]; + rgba[i][ACOMP] = aMap[index[i] & amask]; + } +#else + GLuint rmask = ctx->Pixel.MapItoRsize - 1; + GLuint gmask = ctx->Pixel.MapItoGsize - 1; + GLuint bmask = ctx->Pixel.MapItoBsize - 1; + GLuint amask = ctx->Pixel.MapItoAsize - 1; + const GLfloat *rMap = ctx->Pixel.MapItoR; + const GLfloat *gMap = ctx->Pixel.MapItoG; + const GLfloat *bMap = ctx->Pixel.MapItoB; + const GLfloat *aMap = ctx->Pixel.MapItoA; + GLuint i; + for (i=0;i<n;i++) { + CLAMPED_FLOAT_TO_CHAN(rgba[i][RCOMP], rMap[index[i] & rmask]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][GCOMP], gMap[index[i] & gmask]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][BCOMP], bMap[index[i] & bmask]); + CLAMPED_FLOAT_TO_CHAN(rgba[i][ACOMP], aMap[index[i] & amask]); + } +#endif +} + + +void +_mesa_shift_and_offset_stencil( const GLcontext *ctx, GLuint n, + GLstencil stencil[] ) +{ + GLuint i; + GLint shift = ctx->Pixel.IndexShift; + GLint offset = ctx->Pixel.IndexOffset; + if (shift > 0) { + for (i=0;i<n;i++) { + stencil[i] = (stencil[i] << shift) + offset; + } + } + else if (shift < 0) { + shift = -shift; + for (i=0;i<n;i++) { + stencil[i] = (stencil[i] >> shift) + offset; + } + } + else { + for (i=0;i<n;i++) { + stencil[i] = stencil[i] + offset; + } + } + +} + + +void +_mesa_map_stencil( const GLcontext *ctx, GLuint n, GLstencil stencil[] ) +{ + GLuint mask = ctx->Pixel.MapStoSsize - 1; + GLuint i; + for (i=0;i<n;i++) { + stencil[i] = ctx->Pixel.MapStoS[ stencil[i] & mask ]; + } +} + + + +/* + * This function converts an array of GLchan colors to GLfloat colors. + * Most importantly, it undoes the non-uniform quantization of pixel + * values introduced when we convert shallow (< 8 bit) pixel values + * to GLubytes in the ctx->Driver.ReadRGBASpan() functions. + * This fixes a number of OpenGL conformance failures when running on + * 16bpp displays, for example. + */ +void +_mesa_chan_to_float_span(const GLcontext *ctx, GLuint n, + CONST GLchan rgba[][4], GLfloat rgbaf[][4]) +{ +#if CHAN_TYPE == GL_FLOAT + MEMCPY(rgbaf, rgba, n * 4 * sizeof(GLfloat)); +#else + const GLuint rShift = CHAN_BITS - ctx->Visual.redBits; + const GLuint gShift = CHAN_BITS - ctx->Visual.greenBits; + const GLuint bShift = CHAN_BITS - ctx->Visual.blueBits; + GLuint aShift; + const GLfloat rScale = 1.0F / (GLfloat) ((1 << ctx->Visual.redBits ) - 1); + const GLfloat gScale = 1.0F / (GLfloat) ((1 << ctx->Visual.greenBits) - 1); + const GLfloat bScale = 1.0F / (GLfloat) ((1 << ctx->Visual.blueBits ) - 1); + GLfloat aScale; + GLuint i; + + if (ctx->Visual.alphaBits > 0) { + aShift = CHAN_BITS - ctx->Visual.alphaBits; + aScale = 1.0F / (GLfloat) ((1 << ctx->Visual.alphaBits) - 1); + } + else { + aShift = 0; + aScale = 1.0F / CHAN_MAXF; + } + + for (i = 0; i < n; i++) { + const GLint r = rgba[i][RCOMP] >> rShift; + const GLint g = rgba[i][GCOMP] >> gShift; + const GLint b = rgba[i][BCOMP] >> bShift; + const GLint a = rgba[i][ACOMP] >> aShift; + rgbaf[i][RCOMP] = (GLfloat) r * rScale; + rgbaf[i][GCOMP] = (GLfloat) g * gScale; + rgbaf[i][BCOMP] = (GLfloat) b * bScale; + rgbaf[i][ACOMP] = (GLfloat) a * aScale; + } +#endif +} + +/**********************************************************************/ +/***** State Management *****/ +/**********************************************************************/ + +/* + * Return a bitmask of IMAGE_*_BIT flags which to indicate which + * pixel transfer operations are enabled. + */ +static void +update_image_transfer_state(GLcontext *ctx) +{ + GLuint mask = 0; + + if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F || + ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F || + ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F || + ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F) + mask |= IMAGE_SCALE_BIAS_BIT; + + if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) + mask |= IMAGE_SHIFT_OFFSET_BIT; + + if (ctx->Pixel.MapColorFlag) + mask |= IMAGE_MAP_COLOR_BIT; + + if (ctx->Pixel.ColorTableEnabled) + mask |= IMAGE_COLOR_TABLE_BIT; + + if (ctx->Pixel.Convolution1DEnabled || + ctx->Pixel.Convolution2DEnabled || + ctx->Pixel.Separable2DEnabled) { + mask |= IMAGE_CONVOLUTION_BIT; + if (ctx->Pixel.PostConvolutionScale[0] != 1.0F || + ctx->Pixel.PostConvolutionScale[1] != 1.0F || + ctx->Pixel.PostConvolutionScale[2] != 1.0F || + ctx->Pixel.PostConvolutionScale[3] != 1.0F || + ctx->Pixel.PostConvolutionBias[0] != 0.0F || + ctx->Pixel.PostConvolutionBias[1] != 0.0F || + ctx->Pixel.PostConvolutionBias[2] != 0.0F || + ctx->Pixel.PostConvolutionBias[3] != 0.0F) { + mask |= IMAGE_POST_CONVOLUTION_SCALE_BIAS; + } + } + + if (ctx->Pixel.PostConvolutionColorTableEnabled) + mask |= IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT; + + if (ctx->ColorMatrixStack.Top->type != MATRIX_IDENTITY || + ctx->Pixel.PostColorMatrixScale[0] != 1.0F || + ctx->Pixel.PostColorMatrixBias[0] != 0.0F || + ctx->Pixel.PostColorMatrixScale[1] != 1.0F || + ctx->Pixel.PostColorMatrixBias[1] != 0.0F || + ctx->Pixel.PostColorMatrixScale[2] != 1.0F || + ctx->Pixel.PostColorMatrixBias[2] != 0.0F || + ctx->Pixel.PostColorMatrixScale[3] != 1.0F || + ctx->Pixel.PostColorMatrixBias[3] != 0.0F) + mask |= IMAGE_COLOR_MATRIX_BIT; + + if (ctx->Pixel.PostColorMatrixColorTableEnabled) + mask |= IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT; + + if (ctx->Pixel.HistogramEnabled) + mask |= IMAGE_HISTOGRAM_BIT; + + if (ctx->Pixel.MinMaxEnabled) + mask |= IMAGE_MIN_MAX_BIT; + + ctx->_ImageTransferState = mask; +} + + +void _mesa_update_pixel( GLcontext *ctx, GLuint new_state ) +{ + if (new_state & _NEW_COLOR_MATRIX) + _math_matrix_analyse( ctx->ColorMatrixStack.Top ); + + /* References ColorMatrix.type (derived above). + */ + if (new_state & _IMAGE_NEW_TRANSFER_STATE) + update_image_transfer_state(ctx); +} + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + + +/** + * Initialize the context's PIXEL attribute group. + */ +void +_mesa_init_pixel( GLcontext *ctx ) +{ + int i; + + /* Pixel group */ + ctx->Pixel.RedBias = 0.0; + ctx->Pixel.RedScale = 1.0; + ctx->Pixel.GreenBias = 0.0; + ctx->Pixel.GreenScale = 1.0; + ctx->Pixel.BlueBias = 0.0; + ctx->Pixel.BlueScale = 1.0; + ctx->Pixel.AlphaBias = 0.0; + ctx->Pixel.AlphaScale = 1.0; + ctx->Pixel.DepthBias = 0.0; + ctx->Pixel.DepthScale = 1.0; + ctx->Pixel.IndexOffset = 0; + ctx->Pixel.IndexShift = 0; + ctx->Pixel.ZoomX = 1.0; + ctx->Pixel.ZoomY = 1.0; + ctx->Pixel.MapColorFlag = GL_FALSE; + ctx->Pixel.MapStencilFlag = GL_FALSE; + ctx->Pixel.MapStoSsize = 1; + ctx->Pixel.MapItoIsize = 1; + ctx->Pixel.MapItoRsize = 1; + ctx->Pixel.MapItoGsize = 1; + ctx->Pixel.MapItoBsize = 1; + ctx->Pixel.MapItoAsize = 1; + ctx->Pixel.MapRtoRsize = 1; + ctx->Pixel.MapGtoGsize = 1; + ctx->Pixel.MapBtoBsize = 1; + ctx->Pixel.MapAtoAsize = 1; + ctx->Pixel.MapStoS[0] = 0; + ctx->Pixel.MapItoI[0] = 0.0; + ctx->Pixel.MapItoR[0] = 0.0; + ctx->Pixel.MapItoG[0] = 0.0; + ctx->Pixel.MapItoB[0] = 0.0; + ctx->Pixel.MapItoA[0] = 0.0; + ctx->Pixel.MapItoR8[0] = 0; + ctx->Pixel.MapItoG8[0] = 0; + ctx->Pixel.MapItoB8[0] = 0; + ctx->Pixel.MapItoA8[0] = 0; + ctx->Pixel.MapRtoR[0] = 0.0; + ctx->Pixel.MapGtoG[0] = 0.0; + ctx->Pixel.MapBtoB[0] = 0.0; + ctx->Pixel.MapAtoA[0] = 0.0; + ctx->Pixel.HistogramEnabled = GL_FALSE; + ctx->Pixel.MinMaxEnabled = GL_FALSE; + ctx->Pixel.PixelTextureEnabled = GL_FALSE; + ctx->Pixel.FragmentRgbSource = GL_PIXEL_GROUP_COLOR_SGIS; + ctx->Pixel.FragmentAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS; + ASSIGN_4V(ctx->Pixel.PostColorMatrixScale, 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.PostColorMatrixBias, 0.0, 0.0, 0.0, 0.0); + ASSIGN_4V(ctx->Pixel.ColorTableScale, 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.ColorTableBias, 0.0, 0.0, 0.0, 0.0); + ASSIGN_4V(ctx->Pixel.PCCTscale, 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.PCCTbias, 0.0, 0.0, 0.0, 0.0); + ASSIGN_4V(ctx->Pixel.PCMCTscale, 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.PCMCTbias, 0.0, 0.0, 0.0, 0.0); + ctx->Pixel.ColorTableEnabled = GL_FALSE; + ctx->Pixel.PostConvolutionColorTableEnabled = GL_FALSE; + ctx->Pixel.PostColorMatrixColorTableEnabled = GL_FALSE; + ctx->Pixel.Convolution1DEnabled = GL_FALSE; + ctx->Pixel.Convolution2DEnabled = GL_FALSE; + ctx->Pixel.Separable2DEnabled = GL_FALSE; + for (i = 0; i < 3; i++) { + ASSIGN_4V(ctx->Pixel.ConvolutionBorderColor[i], 0.0, 0.0, 0.0, 0.0); + ctx->Pixel.ConvolutionBorderMode[i] = GL_REDUCE; + ASSIGN_4V(ctx->Pixel.ConvolutionFilterScale[i], 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.ConvolutionFilterBias[i], 0.0, 0.0, 0.0, 0.0); + } + for (i = 0; i < MAX_CONVOLUTION_WIDTH * MAX_CONVOLUTION_WIDTH * 4; i++) { + ctx->Convolution1D.Filter[i] = 0.0; + ctx->Convolution2D.Filter[i] = 0.0; + ctx->Separable2D.Filter[i] = 0.0; + } + ASSIGN_4V(ctx->Pixel.PostConvolutionScale, 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.PostConvolutionBias, 0.0, 0.0, 0.0, 0.0); + /* GL_SGI_texture_color_table */ + ASSIGN_4V(ctx->Pixel.TextureColorTableScale, 1.0, 1.0, 1.0, 1.0); + ASSIGN_4V(ctx->Pixel.TextureColorTableBias, 0.0, 0.0, 0.0, 0.0); + + /* Pixel transfer */ + ctx->Pack.Alignment = 4; + ctx->Pack.RowLength = 0; + ctx->Pack.ImageHeight = 0; + ctx->Pack.SkipPixels = 0; + ctx->Pack.SkipRows = 0; + ctx->Pack.SkipImages = 0; + ctx->Pack.SwapBytes = GL_FALSE; + ctx->Pack.LsbFirst = GL_FALSE; + ctx->Pack.ClientStorage = GL_FALSE; + ctx->Pack.Invert = GL_FALSE; +#if FEATURE_EXT_pixel_buffer_object + ctx->Pack.BufferObj = ctx->Array.NullBufferObj; +#endif + ctx->Unpack.Alignment = 4; + ctx->Unpack.RowLength = 0; + ctx->Unpack.ImageHeight = 0; + ctx->Unpack.SkipPixels = 0; + ctx->Unpack.SkipRows = 0; + ctx->Unpack.SkipImages = 0; + ctx->Unpack.SwapBytes = GL_FALSE; + ctx->Unpack.LsbFirst = GL_FALSE; + ctx->Unpack.ClientStorage = GL_FALSE; + ctx->Unpack.Invert = GL_FALSE; +#if FEATURE_EXT_pixel_buffer_object + ctx->Unpack.BufferObj = ctx->Array.NullBufferObj; +#endif + + /* + * _mesa_unpack_image() returns image data in this format. When we + * execute image commands (glDrawPixels(), glTexImage(), etc) from + * within display lists we have to be sure to set the current + * unpacking parameters to these values! + */ + ctx->DefaultPacking.Alignment = 1; + ctx->DefaultPacking.RowLength = 0; + ctx->DefaultPacking.SkipPixels = 0; + ctx->DefaultPacking.SkipRows = 0; + ctx->DefaultPacking.ImageHeight = 0; + ctx->DefaultPacking.SkipImages = 0; + ctx->DefaultPacking.SwapBytes = GL_FALSE; + ctx->DefaultPacking.LsbFirst = GL_FALSE; + ctx->DefaultPacking.ClientStorage = GL_FALSE; + ctx->DefaultPacking.Invert = GL_FALSE; +#if FEATURE_EXT_pixel_buffer_object + ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj; +#endif + + if (ctx->Visual.doubleBufferMode) { + ctx->Pixel.ReadBuffer = GL_BACK; + } + else { + ctx->Pixel.ReadBuffer = GL_FRONT; + } + + /* Miscellaneous */ + ctx->_ImageTransferState = 0; +} diff --git a/src/mesa/main/pixel.h b/src/mesa/main/pixel.h new file mode 100644 index 00000000000..9eef0cff5af --- /dev/null +++ b/src/mesa/main/pixel.h @@ -0,0 +1,153 @@ +/** + * \file pixel.h + * Pixel operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef PIXEL_H +#define PIXEL_H + + +#include "mtypes.h" + + +/** \name API functions */ +/*@{*/ + +extern void GLAPIENTRY +_mesa_GetPixelMapfv( GLenum map, GLfloat *values ); + +extern void GLAPIENTRY +_mesa_GetPixelMapuiv( GLenum map, GLuint *values ); + +extern void GLAPIENTRY +_mesa_GetPixelMapusv( GLenum map, GLushort *values ); + +extern void GLAPIENTRY +_mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values ); + +extern void GLAPIENTRY +_mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values ); + +extern void GLAPIENTRY +_mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values ); + +extern void GLAPIENTRY +_mesa_PixelStoref( GLenum pname, GLfloat param ); + + +extern void GLAPIENTRY +_mesa_PixelStorei( GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_PixelTransferf( GLenum pname, GLfloat param ); + +extern void GLAPIENTRY +_mesa_PixelTransferi( GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_PixelZoom( GLfloat xfactor, GLfloat yfactor ); + +/*@}*/ + + +/** \name Pixel processing functions */ +/*@{*/ + +extern void +_mesa_scale_and_bias_rgba(GLuint n, GLfloat rgba[][4], + GLfloat rScale, GLfloat gScale, + GLfloat bScale, GLfloat aScale, + GLfloat rBias, GLfloat gBias, + GLfloat bBias, GLfloat aBias); + +extern void +_mesa_map_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4]); + + +extern void +_mesa_transform_rgba(const GLcontext *ctx, GLuint n, GLfloat rgba[][4]); + + +extern void +_mesa_lookup_rgba_float(const struct gl_color_table *table, + GLuint n, GLfloat rgba[][4]); + +extern void +_mesa_lookup_rgba_chan(const struct gl_color_table *table, + GLuint n, GLchan rgba[][4]); + + +extern void +_mesa_shift_and_offset_ci(const GLcontext *ctx, GLuint n, + GLuint indexes[]); + + +extern void +_mesa_map_ci(const GLcontext *ctx, GLuint n, GLuint index[]); + + +extern void +_mesa_map_ci_to_rgba_chan(const GLcontext *ctx, + GLuint n, const GLuint index[], + GLchan rgba[][4]); + + +extern void +_mesa_map_ci_to_rgba(const GLcontext *ctx, + GLuint n, const GLuint index[], GLfloat rgba[][4]); + + +extern void +_mesa_map_ci8_to_rgba(const GLcontext *ctx, + GLuint n, const GLubyte index[], + GLchan rgba[][4]); + + +extern void +_mesa_shift_and_offset_stencil(const GLcontext *ctx, GLuint n, + GLstencil indexes[]); + + +extern void +_mesa_map_stencil(const GLcontext *ctx, GLuint n, GLstencil index[]); + + +extern void +_mesa_chan_to_float_span(const GLcontext *ctx, GLuint n, + CONST GLchan rgba[][4], GLfloat rgbaf[][4]); + + +extern void +_mesa_update_pixel( GLcontext *ctx, GLuint newstate ); + +extern void +_mesa_init_pixel( GLcontext * ctx ); + +/*@}*/ + +#endif diff --git a/src/mesa/main/points.c b/src/mesa/main/points.c new file mode 100644 index 00000000000..aa36fb62877 --- /dev/null +++ b/src/mesa/main/points.c @@ -0,0 +1,294 @@ +/** + * \file points.c + * Point operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "points.h" +#include "texstate.h" +#include "mtypes.h" + + +/** + * Set current point size. + * \param size point diameter in pixels + * \sa glPointSize(). + */ +void GLAPIENTRY +_mesa_PointSize( GLfloat size ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (size <= 0.0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPointSize" ); + return; + } + + if (ctx->Point.Size == size) + return; + + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.Size = size; + + if (ctx->Driver.PointSize) + ctx->Driver.PointSize(ctx, size); +} + + +#if _HAVE_FULL_GL + +/* + * Added by GL_NV_point_sprite + */ +void GLAPIENTRY +_mesa_PointParameteriNV( GLenum pname, GLint param ) +{ + const GLfloat value = (GLfloat) param; + _mesa_PointParameterfvEXT(pname, &value); +} + + +/* + * Added by GL_NV_point_sprite + */ +void GLAPIENTRY +_mesa_PointParameterivNV( GLenum pname, const GLint *params ) +{ + const GLfloat value = (GLfloat) params[0]; + _mesa_PointParameterfvEXT(pname, &value); +} + + + +/* + * Same for both GL_EXT_point_parameters and GL_ARB_point_parameters. + */ +void GLAPIENTRY +_mesa_PointParameterfEXT( GLenum pname, GLfloat param) +{ + _mesa_PointParameterfvEXT(pname, ¶m); +} + + + +/* + * Same for both GL_EXT_point_parameters and GL_ARB_point_parameters. + */ +void GLAPIENTRY +_mesa_PointParameterfvEXT( GLenum pname, const GLfloat *params) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (pname) { + case GL_DISTANCE_ATTENUATION_EXT: + if (ctx->Extensions.EXT_point_parameters) { + if (TEST_EQ_3V(ctx->Point.Params, params)) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + COPY_3V(ctx->Point.Params, params); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)"); + return; + } + break; + case GL_POINT_SIZE_MIN_EXT: + if (ctx->Extensions.EXT_point_parameters) { + if (params[0] < 0.0F) { + _mesa_error( ctx, GL_INVALID_VALUE, + "glPointParameterf[v]{EXT,ARB}(param)" ); + return; + } + if (ctx->Point.MinSize == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.MinSize = params[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)"); + return; + } + break; + case GL_POINT_SIZE_MAX_EXT: + if (ctx->Extensions.EXT_point_parameters) { + if (params[0] < 0.0F) { + _mesa_error( ctx, GL_INVALID_VALUE, + "glPointParameterf[v]{EXT,ARB}(param)" ); + return; + } + if (ctx->Point.MaxSize == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.MaxSize = params[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)"); + return; + } + break; + case GL_POINT_FADE_THRESHOLD_SIZE_EXT: + if (ctx->Extensions.EXT_point_parameters) { + if (params[0] < 0.0F) { + _mesa_error( ctx, GL_INVALID_VALUE, + "glPointParameterf[v]{EXT,ARB}(param)" ); + return; + } + if (ctx->Point.Threshold == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.Threshold = params[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)"); + return; + } + break; + case GL_POINT_SPRITE_R_MODE_NV: + /* This is one area where ARB_point_sprite and NV_point_sprite + * differ. In ARB_point_sprite the POINT_SPRITE_R_MODE is + * always ZERO. NV_point_sprite adds the S and R modes. + */ + if (ctx->Extensions.NV_point_sprite) { + GLenum value = (GLenum) params[0]; + if (value != GL_ZERO && value != GL_S && value != GL_R) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glPointParameterf[v]{EXT,ARB}(param)"); + return; + } + if (ctx->Point.SpriteRMode == value) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.SpriteRMode = value; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)"); + return; + } + break; + case GL_POINT_SPRITE_COORD_ORIGIN: + if (ctx->Extensions.ARB_point_sprite) { + GLenum value = (GLenum) params[0]; + if (value != GL_LOWER_LEFT && value != GL_UPPER_LEFT) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glPointParameterf[v]{EXT,ARB}(param)"); + return; + } + if (ctx->Point.SpriteOrigin == value) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.SpriteOrigin = value; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)"); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, + "glPointParameterf[v]{EXT,ARB}(pname)" ); + return; + } + + if (ctx->Driver.PointParameterfv) + (*ctx->Driver.PointParameterfv)(ctx, pname, params); +} +#endif + + + +/** + * Update derived point-related state. + */ +void +_mesa_update_point(GLcontext *ctx) +{ + /* clamp to user-specified limits now, clamp to ctx->Const.Min/Max + * limits during rasterization. + */ + ctx->Point._Size = CLAMP(ctx->Point.Size, + ctx->Point.MinSize, + ctx->Point.MaxSize); + + if (ctx->Point._Size == 1.0F) + ctx->_TriangleCaps &= ~DD_POINT_SIZE; + else + ctx->_TriangleCaps |= DD_POINT_SIZE; + + ctx->Point._Attenuated = (ctx->Point.Params[0] != 1.0 || + ctx->Point.Params[1] != 0.0 || + ctx->Point.Params[2] != 0.0); + + if (ctx->Point._Attenuated) + ctx->_TriangleCaps |= DD_POINT_ATTEN; + else + ctx->_TriangleCaps &= ~DD_POINT_ATTEN; +} + + + +/** + * Initialize the context point state. + * + * \param ctx GL context. + * + * Initializes __GLcontextRec::Point and point related constants in + * __GLcontextRec::Const. + */ +void +_mesa_init_point(GLcontext *ctx) +{ + GLuint i; + + ctx->Point.SmoothFlag = GL_FALSE; + ctx->Point.Size = 1.0; + ctx->Point._Size = 1.0; + ctx->Point.Params[0] = 1.0; + ctx->Point.Params[1] = 0.0; + ctx->Point.Params[2] = 0.0; + ctx->Point._Attenuated = GL_FALSE; + ctx->Point.MinSize = 0.0; + ctx->Point.MaxSize + = MAX2(ctx->Const.MaxPointSize, ctx->Const.MaxPointSizeAA); + ctx->Point.Threshold = 1.0; + ctx->Point.PointSprite = GL_FALSE; /* GL_ARB/NV_point_sprite */ + ctx->Point.SpriteRMode = GL_ZERO; /* GL_NV_point_sprite (only!) */ + ctx->Point.SpriteOrigin = GL_UPPER_LEFT; /* GL_ARB_point_sprite */ + for (i = 0; i < MAX_TEXTURE_UNITS; i++) { + ctx->Point.CoordReplace[i] = GL_FALSE; /* GL_ARB/NV_point_sprite */ + } +} diff --git a/src/mesa/main/points.h b/src/mesa/main/points.h new file mode 100644 index 00000000000..56acd9ee574 --- /dev/null +++ b/src/mesa/main/points.h @@ -0,0 +1,60 @@ +/** + * \file points.h + * Point operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef POINTS_H +#define POINTS_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_PointSize( GLfloat size ); + +extern void GLAPIENTRY +_mesa_PointParameteriNV( GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_PointParameterivNV( GLenum pname, const GLint *params ); + +extern void GLAPIENTRY +_mesa_PointParameterfEXT( GLenum pname, GLfloat param ); + +extern void GLAPIENTRY +_mesa_PointParameterfvEXT( GLenum pname, const GLfloat *params ); + +extern void +_mesa_update_point(GLcontext *ctx); + +extern void +_mesa_init_point( GLcontext * ctx ); + + +#endif diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c new file mode 100644 index 00000000000..b771408cf36 --- /dev/null +++ b/src/mesa/main/polygon.c @@ -0,0 +1,383 @@ +/** + * \file polygon.c + * Polygon operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "bufferobj.h" +#include "context.h" +#include "image.h" +#include "enums.h" +#include "macros.h" +#include "polygon.h" +#include "mtypes.h" + + +/** + * Specify whether to cull front- or back-facing facets. + * + * \param mode culling mode. + * + * \sa glCullFace(). + * + * Verifies the parameter and updates gl_polygon_attrib::CullFaceMode. On + * change, flushes the vertices and notifies the driver via + * the dd_function_table::CullFace callback. + */ +void GLAPIENTRY +_mesa_CullFace( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glCullFace %s\n", _mesa_lookup_enum_by_nr(mode)); + + if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCullFace" ); + return; + } + + if (ctx->Polygon.CullFaceMode == mode) + return; + + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.CullFaceMode = mode; + + if (ctx->Driver.CullFace) + ctx->Driver.CullFace( ctx, mode ); +} + + +/** + * Define front- and back-facing + * + * \param mode orientation of front-facing polygons. + * + * \sa glFrontFace(). + * + * Verifies the parameter and updates gl_polygon_attrib::FrontFace. On change + * flushes the vertices and notifies the driver via + * the dd_function_table::FrontFace callback. + */ +void GLAPIENTRY +_mesa_FrontFace( GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glFrontFace %s\n", _mesa_lookup_enum_by_nr(mode)); + + if (mode!=GL_CW && mode!=GL_CCW) { + _mesa_error( ctx, GL_INVALID_ENUM, "glFrontFace" ); + return; + } + + if (ctx->Polygon.FrontFace == mode) + return; + + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.FrontFace = mode; + + ctx->Polygon._FrontBit = (GLboolean) (mode == GL_CW); + + if (ctx->Driver.FrontFace) + ctx->Driver.FrontFace( ctx, mode ); +} + + +/** + * Set the polygon rasterization mode. + * + * \param face the polygons which \p mode applies to. + * \param mode how polygons should be rasterized. + * + * \sa glPolygonMode(). + * + * Verifies the parameters and updates gl_polygon_attrib::FrontMode and + * gl_polygon_attrib::BackMode. On change flushes the vertices and notifies the + * driver via the dd_function_table::PolygonMode callback. + */ +void GLAPIENTRY +_mesa_PolygonMode( GLenum face, GLenum mode ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glPolygonMode %s %s\n", + _mesa_lookup_enum_by_nr(face), + _mesa_lookup_enum_by_nr(mode)); + + if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) { + _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" ); + return; + } + + switch (face) { + case GL_FRONT: + if (ctx->Polygon.FrontMode == mode) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.FrontMode = mode; + break; + case GL_FRONT_AND_BACK: + if (ctx->Polygon.FrontMode == mode && + ctx->Polygon.BackMode == mode) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.FrontMode = mode; + ctx->Polygon.BackMode = mode; + break; + case GL_BACK: + if (ctx->Polygon.BackMode == mode) + return; + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.BackMode = mode; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" ); + return; + } + + ctx->_TriangleCaps &= ~DD_TRI_UNFILLED; + if (ctx->Polygon.FrontMode!=GL_FILL || ctx->Polygon.BackMode!=GL_FILL) + ctx->_TriangleCaps |= DD_TRI_UNFILLED; + + if (ctx->Driver.PolygonMode) { + (*ctx->Driver.PolygonMode)( ctx, face, mode ); + } +} + +#if _HAVE_FULL_GL + + +/** + * This routine updates the ctx->Polygon.Stipple state. + * If we're getting the stipple data from a PBO, we map the buffer + * in order to access the data. + * In any case, we obey the current pixel unpacking parameters when fetching + * the stipple data. + * + * In the future, this routine should be used as a fallback, called via + * ctx->Driver.PolygonStipple(). We'll have to update all the DRI drivers + * too. + */ +void +_mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern) +{ + if (ctx->Unpack.BufferObj->Name) { + /* Get/unpack the stipple pattern from a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(2, &ctx->Unpack, 32, 32, 1, + GL_COLOR_INDEX, GL_BITMAP, pattern)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPolygonStipple(bad PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, + ctx->Unpack.BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glPolygonStipple(PBO mapped)"); + return; + } + buf = ADD_POINTERS(buf, pattern); + _mesa_unpack_polygon_stipple(buf, ctx->PolygonStipple, &ctx->Unpack); + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + ctx->Unpack.BufferObj); + } + else { + /* Get/unpack the stipple pattern from user memory */ + _mesa_unpack_polygon_stipple(pattern, ctx->PolygonStipple, &ctx->Unpack); + } +} + + +/** + * Called by glPolygonStipple. + */ +void GLAPIENTRY +_mesa_PolygonStipple( const GLubyte *pattern ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glPolygonStipple\n"); + + FLUSH_VERTICES(ctx, _NEW_POLYGONSTIPPLE); + + _mesa_polygon_stipple(ctx, pattern); + + if (ctx->Driver.PolygonStipple) + ctx->Driver.PolygonStipple(ctx, pattern); +} + + +/** + * Called by glPolygonStipple. + */ +void GLAPIENTRY +_mesa_GetPolygonStipple( GLubyte *dest ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glGetPolygonStipple\n"); + + /* XXX someday we may put this code into a separate function and call + * it with ctx->Driver.GetPolygonStipple(). + */ + if (ctx->Pack.BufferObj->Name) { + /* Put/pack the stipple pattern into a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(2, &ctx->Pack, 32, 32, 1, + GL_COLOR_INDEX, GL_BITMAP, dest)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPolygonStipple(bad PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetPolygonStipple(PBO mapped)"); + return; + } + buf = ADD_POINTERS(buf, dest); + _mesa_pack_polygon_stipple(ctx->PolygonStipple, buf, &ctx->Pack); + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } + else { + /* Put/pack the stipple pattern into user memory */ + _mesa_pack_polygon_stipple(ctx->PolygonStipple, dest, &ctx->Pack); + } +} + + +void GLAPIENTRY +_mesa_PolygonOffset( GLfloat factor, GLfloat units ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&VERBOSE_API) + _mesa_debug(ctx, "glPolygonOffset %f %f\n", factor, units); + + if (ctx->Polygon.OffsetFactor == factor && + ctx->Polygon.OffsetUnits == units) + return; + + FLUSH_VERTICES(ctx, _NEW_POLYGON); + ctx->Polygon.OffsetFactor = factor; + ctx->Polygon.OffsetUnits = units; + + if (ctx->Driver.PolygonOffset) + ctx->Driver.PolygonOffset( ctx, factor, units ); +} + + +void GLAPIENTRY +_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias ) +{ + GET_CURRENT_CONTEXT(ctx); + /* XXX mult by DepthMaxF here??? */ + _mesa_PolygonOffset(factor, bias * ctx->DrawBuffer->_DepthMaxF ); +} + +#endif + + +/**********************************************************************/ +/** \name State Management */ +/*@{*/ + +/* + * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET + * in ctx->_TriangleCaps if needed. + */ +void _mesa_update_polygon( GLcontext *ctx ) +{ + ctx->_TriangleCaps &= ~(DD_TRI_CULL_FRONT_BACK | DD_TRI_OFFSET); + + if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) + ctx->_TriangleCaps |= DD_TRI_CULL_FRONT_BACK; + + /* Any Polygon offsets enabled? */ + if (ctx->Polygon.OffsetPoint || + ctx->Polygon.OffsetLine || + ctx->Polygon.OffsetFill) { + ctx->_TriangleCaps |= DD_TRI_OFFSET; + } +} + +/*@}*/ + + +/**********************************************************************/ +/** \name Initialization */ +/*@{*/ + +/** + * Initialize the context polygon state. + * + * \param ctx GL context. + * + * Initializes __GLcontextRec::Polygon and __GLcontextRec::PolygonStipple + * attribute groups. + */ +void _mesa_init_polygon( GLcontext * ctx ) +{ + /* Polygon group */ + ctx->Polygon.CullFlag = GL_FALSE; + ctx->Polygon.CullFaceMode = GL_BACK; + ctx->Polygon.FrontFace = GL_CCW; + ctx->Polygon._FrontBit = 0; + ctx->Polygon.FrontMode = GL_FILL; + ctx->Polygon.BackMode = GL_FILL; + ctx->Polygon.SmoothFlag = GL_FALSE; + ctx->Polygon.StippleFlag = GL_FALSE; + ctx->Polygon.OffsetFactor = 0.0F; + ctx->Polygon.OffsetUnits = 0.0F; + ctx->Polygon.OffsetPoint = GL_FALSE; + ctx->Polygon.OffsetLine = GL_FALSE; + ctx->Polygon.OffsetFill = GL_FALSE; + + + /* Polygon Stipple group */ + MEMSET( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) ); +} + +/*@}*/ diff --git a/src/mesa/main/polygon.h b/src/mesa/main/polygon.h new file mode 100644 index 00000000000..2550ed16877 --- /dev/null +++ b/src/mesa/main/polygon.h @@ -0,0 +1,69 @@ +/** + * \file polygon.h + * Polygon operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef POLYGON_H +#define POLYGON_H + + +#include "mtypes.h" + + +extern void +_mesa_polygon_stipple(GLcontext *ctx, const GLubyte *pattern); + + +extern void GLAPIENTRY +_mesa_CullFace( GLenum mode ); + +extern void GLAPIENTRY +_mesa_FrontFace( GLenum mode ); + +extern void GLAPIENTRY +_mesa_PolygonMode( GLenum face, GLenum mode ); + +extern void GLAPIENTRY +_mesa_PolygonOffset( GLfloat factor, GLfloat units ); + +extern void GLAPIENTRY +_mesa_PolygonOffsetEXT( GLfloat factor, GLfloat bias ); + +extern void GLAPIENTRY +_mesa_PolygonStipple( const GLubyte *mask ); + +extern void GLAPIENTRY +_mesa_GetPolygonStipple( GLubyte *mask ); + +extern void +_mesa_update_polygon( GLcontext *ctx ); + +extern void +_mesa_init_polygon( GLcontext * ctx ); + +#endif diff --git a/src/mesa/main/rastpos.c b/src/mesa/main/rastpos.c new file mode 100644 index 00000000000..507eb9f9843 --- /dev/null +++ b/src/mesa/main/rastpos.c @@ -0,0 +1,1001 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file rastpos.c + * Raster position operations. + */ + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "feedback.h" +#include "light.h" +#include "macros.h" +#include "rastpos.h" +#include "state.h" +#include "simple_list.h" +#include "mtypes.h" + +#include "math/m_matrix.h" + + +/** + * Clip a point against the view volume. + * + * \param v vertex vector describing the point to clip. + * + * \return zero if outside view volume, or one if inside. + */ +static GLuint +viewclip_point( const GLfloat v[] ) +{ + if ( v[0] > v[3] || v[0] < -v[3] + || v[1] > v[3] || v[1] < -v[3] + || v[2] > v[3] || v[2] < -v[3] ) { + return 0; + } + else { + return 1; + } +} + + +/** + * Clip a point against the far/near Z clipping planes. + * + * \param v vertex vector describing the point to clip. + * + * \return zero if outside view volume, or one if inside. + */ +static GLuint +viewclip_point_z( const GLfloat v[] ) +{ + if (v[2] > v[3] || v[2] < -v[3] ) { + return 0; + } + else { + return 1; + } +} + + +/** + * Clip a point against the user clipping planes. + * + * \param ctx GL context. + * \param v vertex vector describing the point to clip. + * + * \return zero if the point was clipped, or one otherwise. + */ +static GLuint +userclip_point( GLcontext *ctx, const GLfloat v[] ) +{ + GLuint p; + + for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { + if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { + GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0] + + v[1] * ctx->Transform._ClipUserPlane[p][1] + + v[2] * ctx->Transform._ClipUserPlane[p][2] + + v[3] * ctx->Transform._ClipUserPlane[p][3]; + if (dot < 0.0F) { + return 0; + } + } + } + + return 1; +} + + +/** + * This has been split off to allow the normal shade routines to + * get a little closer to the vertex buffer, and to use the + * GLvector objects directly. + * \param ctx the context + * \param vertex vertex location + * \param normal normal vector + * \param Rcolor returned color + * \param Rspec returned specular color (if separate specular enabled) + * \param Rindex returned color index + */ +static void +shade_rastpos(GLcontext *ctx, + const GLfloat vertex[4], + const GLfloat normal[3], + GLfloat Rcolor[4], + GLfloat Rspec[4], + GLfloat *Rindex) +{ + GLfloat (*base)[3] = ctx->Light._BaseColor; + struct gl_light *light; + GLfloat diffuseColor[4], specularColor[4]; + GLfloat diffuse = 0, specular = 0; + + if (!ctx->_ShineTable[0] || !ctx->_ShineTable[1]) + _mesa_validate_all_lighting_tables( ctx ); + + COPY_3V(diffuseColor, base[0]); + diffuseColor[3] = CLAMP( + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F ); + ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 0.0); + + foreach (light, &ctx->Light.EnabledList) { + GLfloat n_dot_h; + GLfloat attenuation = 1.0; + GLfloat VP[3]; + GLfloat n_dot_VP; + GLfloat *h; + GLfloat diffuseContrib[3], specularContrib[3]; + GLboolean normalized; + + if (!(light->_Flags & LIGHT_POSITIONAL)) { + COPY_3V(VP, light->_VP_inf_norm); + attenuation = light->_VP_inf_spot_attenuation; + } + else { + GLfloat d; + + SUB_3V(VP, light->_Position, vertex); + d = (GLfloat) LEN_3FV( VP ); + + if ( d > 1e-6) { + GLfloat invd = 1.0F / d; + SELF_SCALE_SCALAR_3V(VP, invd); + } + attenuation = 1.0F / (light->ConstantAttenuation + d * + (light->LinearAttenuation + d * + light->QuadraticAttenuation)); + + if (light->_Flags & LIGHT_SPOT) { + GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); + + if (PV_dot_dir<light->_CosCutoff) { + continue; + } + else { + double x = PV_dot_dir * (EXP_TABLE_SIZE-1); + int k = (int) x; + GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] + + (x-k)*light->_SpotExpTable[k][1]); + attenuation *= spot; + } + } + } + + if (attenuation < 1e-3) + continue; + + n_dot_VP = DOT3( normal, VP ); + + if (n_dot_VP < 0.0F) { + ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]); + continue; + } + + COPY_3V(diffuseContrib, light->_MatAmbient[0]); + ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]); + diffuse += n_dot_VP * light->_dli * attenuation; + ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0); + + { + if (ctx->Light.Model.LocalViewer) { + GLfloat v[3]; + COPY_3V(v, vertex); + NORMALIZE_3FV(v); + SUB_3V(VP, VP, v); + h = VP; + normalized = 0; + } + else if (light->_Flags & LIGHT_POSITIONAL) { + h = VP; + ACC_3V(h, ctx->_EyeZDir); + normalized = 0; + } + else { + h = light->_h_inf_norm; + normalized = 1; + } + + n_dot_h = DOT3(normal, h); + + if (n_dot_h > 0.0F) { + GLfloat (*mat)[4] = ctx->Light.Material.Attrib; + GLfloat spec_coef; + GLfloat shininess = mat[MAT_ATTRIB_FRONT_SHININESS][0]; + + if (!normalized) { + n_dot_h *= n_dot_h; + n_dot_h /= LEN_SQUARED_3FV( h ); + shininess *= .5; + } + + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec_coef ); + + if (spec_coef > 1.0e-10) { + if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) { + ACC_SCALE_SCALAR_3V( specularContrib, spec_coef, + light->_MatSpecular[0]); + } + else { + ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef, + light->_MatSpecular[0]); + } + specular += spec_coef * light->_sli * attenuation; + } + } + } + + ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib ); + ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib ); + } + + if (ctx->Visual.rgbMode) { + Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F); + Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F); + Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F); + Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F); + Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F); + Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F); + Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F); + Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F); + } + else { + GLfloat *ind = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_INDEXES]; + GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT]; + GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT]; + GLfloat i = (ind[MAT_INDEX_AMBIENT] + + diffuse * (1.0F-specular) * d_a + + specular * s_a); + if (i > ind[MAT_INDEX_SPECULAR]) { + i = ind[MAT_INDEX_SPECULAR]; + } + *Rindex = i; + } +} + + +/** + * Do texgen needed for glRasterPos. + * \param ctx rendering context + * \param vObj object-space vertex coordinate + * \param vEye eye-space vertex coordinate + * \param normal vertex normal + * \param unit texture unit number + * \param texcoord incoming texcoord and resulting texcoord + */ +static void +compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4], + const GLfloat normal[3], GLuint unit, GLfloat texcoord[4]) +{ + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + /* always compute sphere map terms, just in case */ + GLfloat u[3], two_nu, rx, ry, rz, m, mInv; + COPY_3V(u, vEye); + NORMALIZE_3FV(u); + two_nu = 2.0F * DOT3(normal, u); + rx = u[0] - normal[0] * two_nu; + ry = u[1] - normal[1] * two_nu; + rz = u[2] - normal[2] * two_nu; + m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F); + if (m > 0.0F) + mInv = 0.5F * _mesa_inv_sqrtf(m); + else + mInv = 0.0F; + + if (texUnit->TexGenEnabled & S_BIT) { + switch (texUnit->GenModeS) { + case GL_OBJECT_LINEAR: + texcoord[0] = DOT4(vObj, texUnit->ObjectPlaneS); + break; + case GL_EYE_LINEAR: + texcoord[0] = DOT4(vEye, texUnit->EyePlaneS); + break; + case GL_SPHERE_MAP: + texcoord[0] = rx * mInv + 0.5F; + break; + case GL_REFLECTION_MAP: + texcoord[0] = rx; + break; + case GL_NORMAL_MAP: + texcoord[0] = normal[0]; + break; + default: + _mesa_problem(ctx, "Bad S texgen in compute_texgen()"); + return; + } + } + + if (texUnit->TexGenEnabled & T_BIT) { + switch (texUnit->GenModeT) { + case GL_OBJECT_LINEAR: + texcoord[1] = DOT4(vObj, texUnit->ObjectPlaneT); + break; + case GL_EYE_LINEAR: + texcoord[1] = DOT4(vEye, texUnit->EyePlaneT); + break; + case GL_SPHERE_MAP: + texcoord[1] = ry * mInv + 0.5F; + break; + case GL_REFLECTION_MAP: + texcoord[1] = ry; + break; + case GL_NORMAL_MAP: + texcoord[1] = normal[1]; + break; + default: + _mesa_problem(ctx, "Bad T texgen in compute_texgen()"); + return; + } + } + + if (texUnit->TexGenEnabled & R_BIT) { + switch (texUnit->GenModeR) { + case GL_OBJECT_LINEAR: + texcoord[2] = DOT4(vObj, texUnit->ObjectPlaneR); + break; + case GL_EYE_LINEAR: + texcoord[2] = DOT4(vEye, texUnit->EyePlaneR); + break; + case GL_REFLECTION_MAP: + texcoord[2] = rz; + break; + case GL_NORMAL_MAP: + texcoord[2] = normal[2]; + break; + default: + _mesa_problem(ctx, "Bad R texgen in compute_texgen()"); + return; + } + } + + if (texUnit->TexGenEnabled & Q_BIT) { + switch (texUnit->GenModeQ) { + case GL_OBJECT_LINEAR: + texcoord[3] = DOT4(vObj, texUnit->ObjectPlaneQ); + break; + case GL_EYE_LINEAR: + texcoord[3] = DOT4(vEye, texUnit->EyePlaneQ); + break; + default: + _mesa_problem(ctx, "Bad Q texgen in compute_texgen()"); + return; + } + } +} + + + +/** + * Set the raster position for pixel operations. + * + * All glRasterPos command call this function to update the current + * raster position. + * + * \param ctx GL context. + * \param x x coordinate for the raster position. + * \param y y coordinate for the raster position. + * \param z z coordinate for the raster position. + * \param w w coordinate for the raster position. + * + * \sa Called by _mesa_RasterPos4f(). + * + * Flushes the vertices, transforms and clips the vertex coordinates, and + * finally sets the current raster position and associated data in + * __GLcontextRec::Current. When in selection mode calls + * _mesa_update_hitflag() with the current raster position. + */ +static void +raster_pos4f(GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + FLUSH_CURRENT(ctx, 0); + + if (ctx->NewState) + _mesa_update_state( ctx ); + + if (ctx->VertexProgram._Enabled) { + /* XXX implement this */ + _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos"); + return; + } + else { + GLfloat obj[4], eye[4], clip[4], ndc[3], d; + GLfloat *norm, eyenorm[3]; + GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; + + ASSIGN_4V( obj, x, y, z, w ); + /* apply modelview matrix: eye = MV * obj */ + TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, obj ); + /* apply projection matrix: clip = Proj * eye */ + TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye ); + + /* clip to view volume */ + if (ctx->Transform.RasterPositionUnclipped) { + /* GL_IBM_rasterpos_clip: only clip against Z */ + if (viewclip_point_z(clip) == 0) { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + } + else if (viewclip_point(clip) == 0) { + /* Normal OpenGL behaviour */ + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + + /* clip to user clipping planes */ + if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + + /* ndc = clip / W */ + d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3]; + ndc[0] = clip[0] * d; + ndc[1] = clip[1] * d; + ndc[2] = clip[2] * d; + /* wincoord = viewport_mapping(ndc) */ + ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX] + + ctx->Viewport._WindowMap.m[MAT_TX]); + ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY] + + ctx->Viewport._WindowMap.m[MAT_TY]); + ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ] + + ctx->Viewport._WindowMap.m[MAT_TZ]) + / ctx->DrawBuffer->_DepthMaxF; + ctx->Current.RasterPos[3] = clip[3]; + + /* compute raster distance */ + if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) + ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; + else + ctx->Current.RasterDistance = + SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] ); + + /* compute transformed normal vector (for lighting or texgen) */ + if (ctx->_NeedEyeCoords) { + const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv; + TRANSFORM_NORMAL( eyenorm, objnorm, inv ); + norm = eyenorm; + } + else { + norm = objnorm; + } + + /* update raster color */ + if (ctx->Light.Enabled) { + /* lighting */ + shade_rastpos( ctx, obj, norm, + ctx->Current.RasterColor, + ctx->Current.RasterSecondaryColor, + &ctx->Current.RasterIndex ); + } + else { + /* use current color or index */ + if (ctx->Visual.rgbMode) { + COPY_4FV(ctx->Current.RasterColor, + ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); + COPY_4FV(ctx->Current.RasterSecondaryColor, + ctx->Current.Attrib[VERT_ATTRIB_COLOR1]); + } + else { + ctx->Current.RasterIndex = ctx->Current.Index; + } + } + + /* texture coords */ + { + GLuint u; + for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) { + GLfloat tc[4]; + COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]); + if (ctx->Texture.Unit[u].TexGenEnabled) { + compute_texgen(ctx, obj, eye, norm, u, tc); + } + TRANSFORM_POINT(ctx->Current.RasterTexCoords[u], + ctx->TextureMatrixStack[u].Top->m, tc); + } + } + + ctx->Current.RasterPosValid = GL_TRUE; + } + + if (ctx->RenderMode == GL_SELECT) { + _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + } +} + + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2d(GLdouble x, GLdouble y) +{ + _mesa_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2f(GLfloat x, GLfloat y) +{ + _mesa_RasterPos4f(x, y, 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2i(GLint x, GLint y) +{ + _mesa_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2s(GLshort x, GLshort y) +{ + _mesa_RasterPos4f(x, y, 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3d(GLdouble x, GLdouble y, GLdouble z) +{ + _mesa_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3f(GLfloat x, GLfloat y, GLfloat z) +{ + _mesa_RasterPos4f(x, y, z, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3i(GLint x, GLint y, GLint z) +{ + _mesa_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3s(GLshort x, GLshort y, GLshort z) +{ + _mesa_RasterPos4f(x, y, z, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + _mesa_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +/** Calls raster_pos4f() */ +void GLAPIENTRY +_mesa_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + raster_pos4f(ctx, x, y, z, w); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4i(GLint x, GLint y, GLint z, GLint w) +{ + _mesa_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) +{ + _mesa_RasterPos4f(x, y, z, w); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2dv(const GLdouble *v) +{ + _mesa_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2fv(const GLfloat *v) +{ + _mesa_RasterPos4f(v[0], v[1], 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2iv(const GLint *v) +{ + _mesa_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos2sv(const GLshort *v) +{ + _mesa_RasterPos4f(v[0], v[1], 0.0F, 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3dv(const GLdouble *v) +{ + _mesa_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3fv(const GLfloat *v) +{ + _mesa_RasterPos4f(v[0], v[1], v[2], 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3iv(const GLint *v) +{ + _mesa_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos3sv(const GLshort *v) +{ + _mesa_RasterPos4f(v[0], v[1], v[2], 1.0F); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4dv(const GLdouble *v) +{ + _mesa_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4fv(const GLfloat *v) +{ + _mesa_RasterPos4f(v[0], v[1], v[2], v[3]); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4iv(const GLint *v) +{ + _mesa_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +/** Calls _mesa_RasterPos4f() */ +void GLAPIENTRY +_mesa_RasterPos4sv(const GLshort *v) +{ + _mesa_RasterPos4f(v[0], v[1], v[2], v[3]); +} + + +/**********************************************************************/ +/*** GL_ARB_window_pos / GL_MESA_window_pos ***/ +/**********************************************************************/ + +#if FEATURE_windowpos +/** + * All glWindowPosMESA and glWindowPosARB commands call this function to + * update the current raster position. + */ +static void +window_pos3f(GLfloat x, GLfloat y, GLfloat z) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat z2; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + FLUSH_CURRENT(ctx, 0); + + z2 = CLAMP(z, 0.0F, 1.0F) * (ctx->Viewport.Far - ctx->Viewport.Near) + + ctx->Viewport.Near; + + /* set raster position */ + ctx->Current.RasterPos[0] = x; + ctx->Current.RasterPos[1] = y; + ctx->Current.RasterPos[2] = z2; + ctx->Current.RasterPos[3] = 1.0F; + + ctx->Current.RasterPosValid = GL_TRUE; + + if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) + ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; + else + ctx->Current.RasterDistance = 0.0; + + /* raster color = current color or index */ + if (ctx->Visual.rgbMode) { + ctx->Current.RasterColor[0] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0], 0.0F, 1.0F); + ctx->Current.RasterColor[1] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1], 0.0F, 1.0F); + ctx->Current.RasterColor[2] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2], 0.0F, 1.0F); + ctx->Current.RasterColor[3] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3], 0.0F, 1.0F); + ctx->Current.RasterSecondaryColor[0] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0], 0.0F, 1.0F); + ctx->Current.RasterSecondaryColor[1] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1], 0.0F, 1.0F); + ctx->Current.RasterSecondaryColor[2] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2], 0.0F, 1.0F); + ctx->Current.RasterSecondaryColor[3] + = CLAMP(ctx->Current.Attrib[VERT_ATTRIB_COLOR1][3], 0.0F, 1.0F); + } + else { + ctx->Current.RasterIndex = ctx->Current.Index; + } + + /* raster texcoord = current texcoord */ + { + GLuint texSet; + for (texSet = 0; texSet < ctx->Const.MaxTextureCoordUnits; texSet++) { + COPY_4FV( ctx->Current.RasterTexCoords[texSet], + ctx->Current.Attrib[VERT_ATTRIB_TEX0 + texSet] ); + } + } + + if (ctx->RenderMode==GL_SELECT) { + _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); + } +} + + +/* This is just to support the GL_MESA_window_pos version */ +static void +window_pos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GET_CURRENT_CONTEXT(ctx); + window_pos3f(x, y, z); + ctx->Current.RasterPos[3] = w; +} + + +void GLAPIENTRY +_mesa_WindowPos2dMESA(GLdouble x, GLdouble y) +{ + window_pos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos2fMESA(GLfloat x, GLfloat y) +{ + window_pos4f(x, y, 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos2iMESA(GLint x, GLint y) +{ + window_pos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos2sMESA(GLshort x, GLshort y) +{ + window_pos4f(x, y, 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z) +{ + window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z) +{ + window_pos4f(x, y, z, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3iMESA(GLint x, GLint y, GLint z) +{ + window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3sMESA(GLshort x, GLshort y, GLshort z) +{ + window_pos4f(x, y, z, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w) +{ + window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void GLAPIENTRY +_mesa_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + window_pos4f(x, y, z, w); +} + +void GLAPIENTRY +_mesa_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w) +{ + window_pos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w); +} + +void GLAPIENTRY +_mesa_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w) +{ + window_pos4f(x, y, z, w); +} + +void GLAPIENTRY +_mesa_WindowPos2dvMESA(const GLdouble *v) +{ + window_pos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos2fvMESA(const GLfloat *v) +{ + window_pos4f(v[0], v[1], 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos2ivMESA(const GLint *v) +{ + window_pos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos2svMESA(const GLshort *v) +{ + window_pos4f(v[0], v[1], 0.0F, 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3dvMESA(const GLdouble *v) +{ + window_pos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3fvMESA(const GLfloat *v) +{ + window_pos4f(v[0], v[1], v[2], 1.0); +} + +void GLAPIENTRY +_mesa_WindowPos3ivMESA(const GLint *v) +{ + window_pos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos3svMESA(const GLshort *v) +{ + window_pos4f(v[0], v[1], v[2], 1.0F); +} + +void GLAPIENTRY +_mesa_WindowPos4dvMESA(const GLdouble *v) +{ + window_pos4f((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +void GLAPIENTRY +_mesa_WindowPos4fvMESA(const GLfloat *v) +{ + window_pos4f(v[0], v[1], v[2], v[3]); +} + +void GLAPIENTRY +_mesa_WindowPos4ivMESA(const GLint *v) +{ + window_pos4f((GLfloat) v[0], (GLfloat) v[1], + (GLfloat) v[2], (GLfloat) v[3]); +} + +void GLAPIENTRY +_mesa_WindowPos4svMESA(const GLshort *v) +{ + window_pos4f(v[0], v[1], v[2], v[3]); +} + +#endif + +#if 0 + +/* + * OpenGL implementation of glWindowPos*MESA() + */ +void glWindowPos4fMESA( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + GLfloat fx, fy; + + /* Push current matrix mode and viewport attributes */ + glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT ); + + /* Setup projection parameters */ + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + + glDepthRange( z, z ); + glViewport( (int) x - 1, (int) y - 1, 2, 2 ); + + /* set the raster (window) position */ + fx = x - (int) x; + fy = y - (int) y; + glRasterPos4f( fx, fy, 0.0, w ); + + /* restore matrices, viewport and matrix mode */ + glPopMatrix(); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + + glPopAttrib(); +} + +#endif + + +/**********************************************************************/ +/** \name Initialization */ +/**********************************************************************/ +/*@{*/ + +/** + * Initialize the context current raster position information. + * + * \param ctx GL context. + * + * Initialize the current raster position information in + * __GLcontextRec::Current, and adds the extension entry points to the + * dispatcher. + */ +void _mesa_init_rastpos( GLcontext * ctx ) +{ + int i; + + ASSIGN_4V( ctx->Current.RasterPos, 0.0, 0.0, 0.0, 1.0 ); + ctx->Current.RasterDistance = 0.0; + ASSIGN_4V( ctx->Current.RasterColor, 1.0, 1.0, 1.0, 1.0 ); + ctx->Current.RasterIndex = 1.0; + for (i=0; i<MAX_TEXTURE_UNITS; i++) + ASSIGN_4V( ctx->Current.RasterTexCoords[i], 0.0, 0.0, 0.0, 1.0 ); + ctx->Current.RasterPosValid = GL_TRUE; +} + +/*@}*/ diff --git a/src/mesa/main/rastpos.h b/src/mesa/main/rastpos.h new file mode 100644 index 00000000000..363f86ad87b --- /dev/null +++ b/src/mesa/main/rastpos.h @@ -0,0 +1,193 @@ +/** + * \file rastpos.h + * Raster position operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef RASTPOS_H +#define RASTPOS_H + + +#include "glheader.h" + + +extern void GLAPIENTRY +_mesa_RasterPos2d(GLdouble x, GLdouble y); + +extern void GLAPIENTRY +_mesa_RasterPos2f(GLfloat x, GLfloat y); + +extern void GLAPIENTRY +_mesa_RasterPos2i(GLint x, GLint y); + +extern void GLAPIENTRY +_mesa_RasterPos2s(GLshort x, GLshort y); + +extern void GLAPIENTRY +_mesa_RasterPos3d(GLdouble x, GLdouble y, GLdouble z); + +extern void GLAPIENTRY +_mesa_RasterPos3f(GLfloat x, GLfloat y, GLfloat z); + +extern void GLAPIENTRY +_mesa_RasterPos3i(GLint x, GLint y, GLint z); + +extern void GLAPIENTRY +_mesa_RasterPos3s(GLshort x, GLshort y, GLshort z); + +extern void GLAPIENTRY +_mesa_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w); + +extern void GLAPIENTRY +_mesa_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w); + +extern void GLAPIENTRY +_mesa_RasterPos4i(GLint x, GLint y, GLint z, GLint w); + +extern void GLAPIENTRY +_mesa_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w); + +extern void GLAPIENTRY +_mesa_RasterPos2dv(const GLdouble *v); + +extern void GLAPIENTRY +_mesa_RasterPos2fv(const GLfloat *v); + +extern void GLAPIENTRY +_mesa_RasterPos2iv(const GLint *v); + +extern void GLAPIENTRY +_mesa_RasterPos2sv(const GLshort *v); + +extern void GLAPIENTRY +_mesa_RasterPos3dv(const GLdouble *v); + +extern void GLAPIENTRY +_mesa_RasterPos3fv(const GLfloat *v); + +extern void GLAPIENTRY +_mesa_RasterPos3iv(const GLint *v); + +extern void GLAPIENTRY +_mesa_RasterPos3sv(const GLshort *v); + +extern void GLAPIENTRY +_mesa_RasterPos4dv(const GLdouble *v); + +extern void GLAPIENTRY +_mesa_RasterPos4fv(const GLfloat *v); + +extern void GLAPIENTRY +_mesa_RasterPos4iv(const GLint *v); + +extern void GLAPIENTRY +_mesa_RasterPos4sv(const GLshort *v); + + +/**********************************************************************/ +/** \name GL_MESA_window_pos */ +/**********************************************************************/ +/*@{*/ + +extern void GLAPIENTRY +_mesa_WindowPos2dMESA(GLdouble x, GLdouble y); + +extern void GLAPIENTRY +_mesa_WindowPos2fMESA(GLfloat x, GLfloat y); + +extern void GLAPIENTRY +_mesa_WindowPos2iMESA(GLint x, GLint y); + +extern void GLAPIENTRY +_mesa_WindowPos2sMESA(GLshort x, GLshort y); + +extern void GLAPIENTRY +_mesa_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z); + +extern void GLAPIENTRY +_mesa_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z); + +extern void GLAPIENTRY +_mesa_WindowPos3iMESA(GLint x, GLint y, GLint z); + +extern void GLAPIENTRY +_mesa_WindowPos3sMESA(GLshort x, GLshort y, GLshort z); + +extern void GLAPIENTRY +_mesa_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w); + +extern void GLAPIENTRY +_mesa_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w); + +extern void GLAPIENTRY +_mesa_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w); + +extern void GLAPIENTRY +_mesa_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w); + +extern void GLAPIENTRY +_mesa_WindowPos2dvMESA(const GLdouble *v); + +extern void GLAPIENTRY +_mesa_WindowPos2fvMESA(const GLfloat *v); + +extern void GLAPIENTRY +_mesa_WindowPos2ivMESA(const GLint *v); + +extern void GLAPIENTRY +_mesa_WindowPos2svMESA(const GLshort *v); + +extern void GLAPIENTRY +_mesa_WindowPos3dvMESA(const GLdouble *v); + +extern void GLAPIENTRY +_mesa_WindowPos3fvMESA(const GLfloat *v); + +extern void GLAPIENTRY +_mesa_WindowPos3ivMESA(const GLint *v); + +extern void GLAPIENTRY +_mesa_WindowPos3svMESA(const GLshort *v); + +extern void GLAPIENTRY +_mesa_WindowPos4dvMESA(const GLdouble *v); + +extern void GLAPIENTRY +_mesa_WindowPos4fvMESA(const GLfloat *v); + +extern void GLAPIENTRY +_mesa_WindowPos4ivMESA(const GLint *v); + +extern void GLAPIENTRY +_mesa_WindowPos4svMESA(const GLshort *v); + +extern void +_mesa_init_rastpos( GLcontext * ctx ); + +/*@}*/ + +#endif diff --git a/src/mesa/main/renderbuffer.c b/src/mesa/main/renderbuffer.c new file mode 100644 index 00000000000..42e94a31fe5 --- /dev/null +++ b/src/mesa/main/renderbuffer.c @@ -0,0 +1,1869 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * Functions for allocating/managing renderbuffers. + * Also, routines for reading/writing software-based renderbuffer data as + * ubytes, ushorts, uints, etc. + * + * The 'alpha8' renderbuffer is interesting. It's used to add a software-based + * alpha channel to RGB renderbuffers. This is done by wrapping the RGB + * renderbuffer with the alpha renderbuffer. We can do this because of the + * OO-nature of renderbuffers. + * + * Down the road we'll use this for run-time support of 8, 16 and 32-bit + * color channels. For example, Mesa may use 32-bit/float color channels + * internally (swrast) and use wrapper renderbuffers to convert 32-bit + * values down to 16 or 8-bit values for whatever kind of framebuffer we have. + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "mtypes.h" +#include "fbobject.h" +#include "renderbuffer.h" + + +#define COLOR_INDEX32 0x424243 + + +/* + * Routines for get/put values in common buffer formats follow. + * Someday add support for arbitrary row stride to make them more + * flexible. + */ + +/********************************************************************** + * Functions for buffers of 1 X GLushort values. + * Typically stencil. + */ + +static void * +get_pointer_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + if (!rb->Data) + return NULL; + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + return (GLubyte *) rb->Data + y * rb->Width + x; +} + + +static void +get_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const GLubyte *src = (const GLubyte *) rb->Data + y * rb->Width + x; + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + _mesa_memcpy(values, src, count * sizeof(GLubyte)); +} + + +static void +get_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + GLubyte *dst = (GLubyte *) values; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + const GLubyte *src = (GLubyte *) rb->Data + y[i] * rb->Width + x[i]; + dst[i] = *src; + } +} + + +static void +put_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const GLubyte *src = (const GLubyte *) values; + GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x; + assert(rb->DataType == GL_UNSIGNED_BYTE); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = src[i]; + } + } + } + else { + _mesa_memcpy(dst, values, count * sizeof(GLubyte)); + } +} + + +static void +put_mono_row_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const GLubyte val = *((const GLubyte *) value); + GLubyte *dst = (GLubyte *) rb->Data + y * rb->Width + x; + assert(rb->DataType == GL_UNSIGNED_BYTE); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = val; + } + } + } + else { + GLuint i; + for (i = 0; i < count; i++) { + dst[i] = val; + } + } +} + + +static void +put_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + const GLubyte *src = (const GLubyte *) values; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i]; + *dst = src[i]; + } + } +} + + +static void +put_mono_values_ubyte(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + const GLubyte val = *((const GLubyte *) value); + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLubyte *dst = (GLubyte *) rb->Data + y[i] * rb->Width + x[i]; + *dst = val; + } + } +} + + +/********************************************************************** + * Functions for buffers of 1 X GLushort values. + * Typically depth/Z. + */ + +static void * +get_pointer_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + if (!rb->Data) + return NULL; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + ASSERT(rb->Width > 0); + return (GLushort *) rb->Data + y * rb->Width + x; +} + + +static void +get_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const void *src = rb->GetPointer(ctx, rb, x, y); + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + _mesa_memcpy(values, src, count * sizeof(GLushort)); +} + + +static void +get_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + GLushort *dst = (GLushort *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + for (i = 0; i < count; i++) { + const GLushort *src = (GLushort *) rb->Data + y[i] * rb->Width + x[i]; + dst[i] = *src; + } +} + + +static void +put_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const GLushort *src = (const GLushort *) values; + GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = src[i]; + } + } + } + else { + _mesa_memcpy(dst, src, count * sizeof(GLushort)); + } +} + + +static void +put_mono_row_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const GLushort val = *((const GLushort *) value); + GLushort *dst = (GLushort *) rb->Data + y * rb->Width + x; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = val; + } + } + } + else { + GLuint i; + for (i = 0; i < count; i++) { + dst[i] = val; + } + } +} + + +static void +put_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + const GLushort *src = (const GLushort *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i]; + *dst = src[i]; + } + } +} + + +static void +put_mono_values_ushort(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + const GLushort val = *((const GLushort *) value); + ASSERT(rb->DataType == GL_UNSIGNED_SHORT); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i]; + *dst = val; + } + } + } + else { + GLuint i; + for (i = 0; i < count; i++) { + GLushort *dst = (GLushort *) rb->Data + y[i] * rb->Width + x[i]; + *dst = val; + } + } +} + + +/********************************************************************** + * Functions for buffers of 1 X GLuint values. + * Typically depth/Z or color index. + */ + +static void * +get_pointer_uint(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + if (!rb->Data) + return NULL; + ASSERT(rb->DataType == GL_UNSIGNED_INT); + return (GLuint *) rb->Data + y * rb->Width + x; +} + + +static void +get_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const void *src = rb->GetPointer(ctx, rb, x, y); + ASSERT(rb->DataType == GL_UNSIGNED_INT); + _mesa_memcpy(values, src, count * sizeof(GLuint)); +} + + +static void +get_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + GLuint *dst = (GLuint *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_INT); + for (i = 0; i < count; i++) { + const GLuint *src = (GLuint *) rb->Data + y[i] * rb->Width + x[i]; + dst[i] = *src; + } +} + + +static void +put_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const GLuint *src = (const GLuint *) values; + GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x; + ASSERT(rb->DataType == GL_UNSIGNED_INT); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = src[i]; + } + } + } + else { + _mesa_memcpy(dst, src, count * sizeof(GLuint)); + } +} + + +static void +put_mono_row_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const GLuint val = *((const GLuint *) value); + GLuint *dst = (GLuint *) rb->Data + y * rb->Width + x; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_INT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = val; + } + } +} + + +static void +put_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + const GLuint *src = (const GLuint *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_INT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i]; + *dst = src[i]; + } + } +} + + +static void +put_mono_values_uint(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *value, + const GLubyte *mask) +{ + const GLuint val = *((const GLuint *) value); + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_INT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) rb->Data + y[i] * rb->Width + x[i]; + *dst = val; + } + } +} + + +/********************************************************************** + * Functions for buffers of 3 X GLubyte (or GLbyte) values. + * Typically color buffers. + * NOTE: the incoming and outgoing colors are RGBA! We ignore incoming + * alpha values and return 255 for outgoing alpha values. + */ + +static void * +get_pointer_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + /* No direct access since this buffer is RGB but caller will be + * treating it as if it were RGBA. + */ + return NULL; +} + + +static void +get_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const GLubyte *src = (const GLubyte *) rb->Data + 3 * (y * rb->Width + x); + GLubyte *dst = (GLubyte *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + dst[i * 4 + 0] = src[i * 3 + 0]; + dst[i * 4 + 1] = src[i * 3 + 1]; + dst[i * 4 + 2] = src[i * 3 + 2]; + dst[i * 4 + 3] = 255; + } +} + + +static void +get_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + GLubyte *dst = (GLubyte *) values; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + const GLubyte *src + = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]); + dst[i * 4 + 0] = src[0]; + dst[i * 4 + 1] = src[1]; + dst[i * 4 + 2] = src[2]; + dst[i * 4 + 3] = 255; + } +} + + +static void +put_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + /* note: incoming values are RGB+A! */ + const GLubyte *src = (const GLubyte *) values; + GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x); + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i * 3 + 0] = src[i * 4 + 0]; + dst[i * 3 + 1] = src[i * 4 + 1]; + dst[i * 3 + 2] = src[i * 4 + 2]; + } + } +} + + +static void +put_row_rgb_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + /* note: incoming values are RGB+A! */ + const GLubyte *src = (const GLubyte *) values; + GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x); + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i * 3 + 0] = src[i * 3 + 0]; + dst[i * 3 + 1] = src[i * 3 + 1]; + dst[i * 3 + 2] = src[i * 3 + 2]; + } + } +} + + +static void +put_mono_row_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + /* note: incoming value is RGB+A! */ + const GLubyte val0 = ((const GLubyte *) value)[0]; + const GLubyte val1 = ((const GLubyte *) value)[1]; + const GLubyte val2 = ((const GLubyte *) value)[2]; + GLubyte *dst = (GLubyte *) rb->Data + 3 * (y * rb->Width + x); + assert(rb->DataType == GL_UNSIGNED_BYTE); + if (!mask && val0 == val1 && val1 == val2) { + /* optimized case */ + _mesa_memset(dst, val0, 3 * count); + } + else { + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i * 3 + 0] = val0; + dst[i * 3 + 1] = val1; + dst[i * 3 + 2] = val2; + } + } + } +} + + +static void +put_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + /* note: incoming values are RGB+A! */ + const GLubyte *src = (const GLubyte *) values; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]); + dst[0] = src[i * 4 + 0]; + dst[1] = src[i * 4 + 1]; + dst[2] = src[i * 4 + 2]; + } + } +} + + +static void +put_mono_values_ubyte3(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + /* note: incoming value is RGB+A! */ + const GLubyte val0 = ((const GLubyte *) value)[0]; + const GLubyte val1 = ((const GLubyte *) value)[1]; + const GLubyte val2 = ((const GLubyte *) value)[2]; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLubyte *dst = (GLubyte *) rb->Data + 3 * (y[i] * rb->Width + x[i]); + dst[0] = val0; + dst[1] = val1; + dst[2] = val2; + } + } +} + + +/********************************************************************** + * Functions for buffers of 4 X GLubyte (or GLbyte) values. + * Typically color buffers. + */ + +static void * +get_pointer_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + if (!rb->Data) + return NULL; + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + return (GLubyte *) rb->Data + 4 * (y * rb->Width + x); +} + + +static void +get_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const GLbyte *src = (const GLbyte *) rb->Data + 4 * (y * rb->Width + x); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + _mesa_memcpy(values, src, 4 * count * sizeof(GLbyte)); +} + + +static void +get_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + /* treat 4*GLubyte as 1*GLuint */ + GLuint *dst = (GLuint *) values; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + const GLuint *src = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]); + dst[i] = *src; + } +} + + +static void +put_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + /* treat 4*GLubyte as 1*GLuint */ + const GLuint *src = (const GLuint *) values; + GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x); + assert(rb->DataType == GL_UNSIGNED_BYTE); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = src[i]; + } + } + } + else { + _mesa_memcpy(dst, src, 4 * count * sizeof(GLubyte)); + } +} + + +static void +put_row_rgb_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + /* Store RGB values in RGBA buffer */ + const GLubyte *src = (const GLubyte *) values; + GLubyte *dst = (GLubyte *) rb->Data + 4 * (y * rb->Width + x); + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i * 4 + 0] = src[i * 3 + 0]; + dst[i * 4 + 1] = src[i * 3 + 1]; + dst[i * 4 + 2] = src[i * 3 + 2]; + dst[i * 4 + 3] = 0xff; + } + } +} + + +static void +put_mono_row_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + /* treat 4*GLubyte as 1*GLuint */ + const GLuint val = *((const GLuint *) value); + GLuint *dst = (GLuint *) rb->Data + (y * rb->Width + x); + assert(rb->DataType == GL_UNSIGNED_BYTE); + if (!mask && val == 0) { + /* common case */ + _mesa_bzero(dst, count * 4 * sizeof(GLubyte)); + } + else { + /* general case */ + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = val; + } + } + } + else { + GLuint i; + for (i = 0; i < count; i++) { + dst[i] = val; + } + } + } +} + + +static void +put_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + /* treat 4*GLubyte as 1*GLuint */ + const GLuint *src = (const GLuint *) values; + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]); + *dst = src[i]; + } + } +} + + +static void +put_mono_values_ubyte4(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + /* treat 4*GLubyte as 1*GLuint */ + const GLuint val = *((const GLuint *) value); + GLuint i; + assert(rb->DataType == GL_UNSIGNED_BYTE); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) rb->Data + (y[i] * rb->Width + x[i]); + *dst = val; + } + } +} + + +/********************************************************************** + * Functions for buffers of 4 X GLushort (or GLshort) values. + * Typically accum buffer. + */ + +static void * +get_pointer_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + if (!rb->Data) + return NULL; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + return (GLushort *) rb->Data + 4 * (y * rb->Width + x); +} + + +static void +get_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const GLshort *src = (const GLshort *) rb->Data + 4 * (y * rb->Width + x); + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + _mesa_memcpy(values, src, 4 * count * sizeof(GLshort)); +} + + +static void +get_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + GLushort *dst = (GLushort *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + for (i = 0; i < count; i++) { + const GLushort *src + = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]); + dst[i] = *src; + } +} + + +static void +put_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const GLushort *src = (const GLushort *) values; + GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x); + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i * 4 + 0] = src[i * 4 + 0]; + dst[i * 4 + 1] = src[i * 4 + 1]; + dst[i * 4 + 2] = src[i * 4 + 2]; + dst[i * 4 + 3] = src[i * 4 + 3]; + } + } + } + else { + _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort)); + } +} + + +static void +put_row_rgb_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + /* Put RGB values in RGBA buffer */ + const GLushort *src = (const GLushort *) values; + GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x); + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i * 4 + 0] = src[i * 3 + 0]; + dst[i * 4 + 1] = src[i * 3 + 1]; + dst[i * 4 + 2] = src[i * 3 + 2]; + dst[i * 4 + 3] = 0xffff; + } + } + } + else { + _mesa_memcpy(dst, src, 4 * count * sizeof(GLushort)); + } +} + + +static void +put_mono_row_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const GLushort val0 = ((const GLushort *) value)[0]; + const GLushort val1 = ((const GLushort *) value)[1]; + const GLushort val2 = ((const GLushort *) value)[2]; + const GLushort val3 = ((const GLushort *) value)[3]; + GLushort *dst = (GLushort *) rb->Data + 4 * (y * rb->Width + x); + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + if (!mask && val0 == 0 && val1 == 0 && val2 == 0 && val3 == 0) { + /* common case for clearing accum buffer */ + _mesa_bzero(dst, count * 4 * sizeof(GLushort)); + } + else { + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i * 4 + 0] = val0; + dst[i * 4 + 1] = val1; + dst[i * 4 + 2] = val2; + dst[i * 4 + 3] = val3; + } + } + } +} + + +static void +put_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + const GLushort *src = (const GLushort *) values; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]); + dst[0] = src[i * 4 + 0]; + dst[1] = src[i * 4 + 1]; + dst[2] = src[i * 4 + 2]; + dst[3] = src[i * 4 + 3]; + } + } +} + + +static void +put_mono_values_ushort4(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + const GLushort val0 = ((const GLushort *) value)[0]; + const GLushort val1 = ((const GLushort *) value)[1]; + const GLushort val2 = ((const GLushort *) value)[2]; + const GLushort val3 = ((const GLushort *) value)[3]; + GLuint i; + ASSERT(rb->DataType == GL_UNSIGNED_SHORT || rb->DataType == GL_SHORT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLushort *dst = (GLushort *) rb->Data + 4 * (y[i] * rb->Width + x[i]); + dst[0] = val0; + dst[1] = val1; + dst[2] = val2; + dst[3] = val3; + } + } +} + + + +/** + * This is a software fallback for the gl_renderbuffer->AllocStorage + * function. + * Device drivers will typically override this function for the buffers + * which it manages (typically color buffers, Z and stencil). + * Other buffers (like software accumulation and aux buffers) which the driver + * doesn't manage can be handled with this function. + * + * This one multi-purpose function can allocate stencil, depth, accum, color + * or color-index buffers! + * + * This function also plugs in the appropriate GetPointer, Get/PutRow and + * Get/PutValues functions. + */ +static GLboolean +soft_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + GLuint pixelSize; + + switch (internalFormat) { + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + rb->_BaseFormat = GL_RGB; + rb->DataType = GL_UNSIGNED_BYTE; + rb->GetPointer = get_pointer_ubyte3; + rb->GetRow = get_row_ubyte3; + rb->GetValues = get_values_ubyte3; + rb->PutRow = put_row_ubyte3; + rb->PutRowRGB = put_row_rgb_ubyte3; + rb->PutMonoRow = put_mono_row_ubyte3; + rb->PutValues = put_values_ubyte3; + rb->PutMonoValues = put_mono_values_ubyte3; + rb->ComponentSizes[0] = 8 * sizeof(GLubyte); + rb->ComponentSizes[1] = 8 * sizeof(GLubyte); + rb->ComponentSizes[2] = 8 * sizeof(GLubyte); + rb->ComponentSizes[3] = 0; + pixelSize = 3 * sizeof(GLchan); + break; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + rb->_BaseFormat = GL_RGBA; + rb->DataType = GL_UNSIGNED_BYTE; + rb->GetPointer = get_pointer_ubyte4; + rb->GetRow = get_row_ubyte4; + rb->GetValues = get_values_ubyte4; + rb->PutRow = put_row_ubyte4; + rb->PutRowRGB = put_row_rgb_ubyte4; + rb->PutMonoRow = put_mono_row_ubyte4; + rb->PutValues = put_values_ubyte4; + rb->PutMonoValues = put_mono_values_ubyte4; + rb->ComponentSizes[0] = 8 * sizeof(GLubyte); + rb->ComponentSizes[1] = 8 * sizeof(GLubyte); + rb->ComponentSizes[2] = 8 * sizeof(GLubyte); + rb->ComponentSizes[3] = 8 * sizeof(GLubyte); + pixelSize = 4 * sizeof(GLubyte); + break; + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + rb->_BaseFormat = GL_RGBA; + rb->DataType = GL_UNSIGNED_SHORT; + rb->GetPointer = get_pointer_ushort4; + rb->GetRow = get_row_ushort4; + rb->GetValues = get_values_ushort4; + rb->PutRow = put_row_ushort4; + rb->PutRowRGB = put_row_rgb_ushort4; + rb->PutMonoRow = put_mono_row_ushort4; + rb->PutValues = put_values_ushort4; + rb->PutMonoValues = put_mono_values_ushort4; + rb->ComponentSizes[0] = 8 * sizeof(GLushort); + rb->ComponentSizes[1] = 8 * sizeof(GLushort); + rb->ComponentSizes[2] = 8 * sizeof(GLushort); + rb->ComponentSizes[3] = 8 * sizeof(GLushort); + pixelSize = 4 * sizeof(GLushort); + break; +#if 00 + case ALPHA8: + rb->_BaseFormat = GL_RGBA; /* Yes, not GL_ALPHA! */ + rb->DataType = GL_UNSIGNED_BYTE; + rb->GetPointer = get_pointer_alpha8; + rb->GetRow = get_row_alpha8; + rb->GetValues = get_values_alpha8; + rb->PutRow = put_row_alpha8; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_alpha8; + rb->PutValues = put_values_alpha8; + rb->PutMonoValues = put_mono_values_alpha8; + rb->ComponentSizes[0] = 0; /*red*/ + rb->ComponentSizes[1] = 0; /*green*/ + rb->ComponentSizes[2] = 0; /*blue*/ + rb->ComponentSizes[3] = 8 * sizeof(GLubyte); + pixelSize = sizeof(GLubyte); + break; +#endif + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1_EXT: + case GL_STENCIL_INDEX4_EXT: + case GL_STENCIL_INDEX8_EXT: + rb->_BaseFormat = GL_STENCIL_INDEX; + rb->DataType = GL_UNSIGNED_BYTE; + rb->GetPointer = get_pointer_ubyte; + rb->GetRow = get_row_ubyte; + rb->GetValues = get_values_ubyte; + rb->PutRow = put_row_ubyte; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_ubyte; + rb->PutValues = put_values_ubyte; + rb->PutMonoValues = put_mono_values_ubyte; + rb->ComponentSizes[0] = 8 * sizeof(GLubyte); + pixelSize = sizeof(GLubyte); + break; + case GL_STENCIL_INDEX16_EXT: + rb->_BaseFormat = GL_STENCIL_INDEX; + rb->DataType = GL_UNSIGNED_SHORT; + rb->GetPointer = get_pointer_ushort; + rb->GetRow = get_row_ushort; + rb->GetValues = get_values_ushort; + rb->PutRow = put_row_ushort; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_ushort; + rb->PutValues = put_values_ushort; + rb->PutMonoValues = put_mono_values_ushort; + rb->ComponentSizes[0] = 8 * sizeof(GLushort); + pixelSize = sizeof(GLushort); + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + rb->_BaseFormat = GL_DEPTH_COMPONENT; + rb->DataType = GL_UNSIGNED_SHORT; + rb->GetPointer = get_pointer_ushort; + rb->GetRow = get_row_ushort; + rb->GetValues = get_values_ushort; + rb->PutRow = put_row_ushort; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_ushort; + rb->PutValues = put_values_ushort; + rb->PutMonoValues = put_mono_values_ushort; + rb->ComponentSizes[0] = 8 * sizeof(GLushort); + pixelSize = sizeof(GLushort); + break; + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + rb->_BaseFormat = GL_DEPTH_COMPONENT; + rb->DataType = GL_UNSIGNED_INT; + rb->GetPointer = get_pointer_uint; + rb->GetRow = get_row_uint; + rb->GetValues = get_values_uint; + rb->PutRow = put_row_uint; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_uint; + rb->PutValues = put_values_uint; + rb->PutMonoValues = put_mono_values_uint; + rb->ComponentSizes[0] = 8 * sizeof(GLuint); + pixelSize = sizeof(GLuint); + break; + case GL_COLOR_INDEX8_EXT: + rb->_BaseFormat = GL_COLOR_INDEX; + rb->DataType = GL_UNSIGNED_BYTE; + rb->GetPointer = get_pointer_ubyte; + rb->GetRow = get_row_ubyte; + rb->GetValues = get_values_ubyte; + rb->PutRow = put_row_ubyte; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_ubyte; + rb->PutValues = put_values_ubyte; + rb->PutMonoValues = put_mono_values_ubyte; + rb->ComponentSizes[0] = 8 * sizeof(GLubyte); + pixelSize = sizeof(GLubyte); + break; + case GL_COLOR_INDEX16_EXT: + rb->_BaseFormat = GL_COLOR_INDEX; + rb->DataType = GL_UNSIGNED_SHORT; + rb->GetPointer = get_pointer_ushort; + rb->GetRow = get_row_ushort; + rb->GetValues = get_values_ushort; + rb->PutRow = put_row_ushort; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_ushort; + rb->PutValues = put_values_ushort; + rb->PutMonoValues = put_mono_values_ushort; + rb->ComponentSizes[0] = 8 * sizeof(GLushort); + pixelSize = sizeof(GLushort); + break; + case COLOR_INDEX32: + rb->_BaseFormat = GL_COLOR_INDEX; + rb->DataType = GL_UNSIGNED_INT; + rb->GetPointer = get_pointer_uint; + rb->GetRow = get_row_uint; + rb->GetValues = get_values_uint; + rb->PutRow = put_row_uint; + rb->PutRowRGB = NULL; + rb->PutMonoRow = put_mono_row_uint; + rb->PutValues = put_values_uint; + rb->PutMonoValues = put_mono_values_uint; + rb->ComponentSizes[0] = 8 * sizeof(GLuint); + pixelSize = sizeof(GLuint); + break; + default: + _mesa_problem(ctx, "Bad internalFormat in soft_renderbuffer_storage"); + return GL_FALSE; + } + + ASSERT(rb->DataType); + ASSERT(rb->GetPointer); + ASSERT(rb->GetRow); + ASSERT(rb->GetValues); + ASSERT(rb->PutRow); + ASSERT(rb->PutMonoRow); + ASSERT(rb->PutValues); + ASSERT(rb->PutMonoValues); + ASSERT(rb->ComponentSizes[0] > 0); + + /* free old buffer storage */ + if (rb->Data) + _mesa_free(rb->Data); + + /* allocate new buffer storage */ + rb->Data = _mesa_malloc(width * height * pixelSize); + if (rb->Data == NULL) { + rb->Width = 0; + rb->Height = 0; + _mesa_error(ctx, GL_OUT_OF_MEMORY, "software renderbuffer allocation"); + return GL_FALSE; + } + + rb->Width = width; + rb->Height = height; + rb->InternalFormat = internalFormat; + + return GL_TRUE; +} + + +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ + + +/** + * Here we utilize the gl_renderbuffer->Wrapper field to put an alpha + * buffer wrapper around an existing RGB renderbuffer (hw or sw). + * + * When PutRow is called (for example), we store the alpha values in + * this buffer, then pass on the PutRow call to the wrapped RGB + * buffer. + */ + + +static GLboolean +alloc_storage_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, + GLenum internalFormat, GLuint width, GLuint height) +{ + ASSERT(arb != arb->Wrapped); + + /* first, pass the call to the wrapped RGB buffer */ + if (!arb->Wrapped->AllocStorage(ctx, arb->Wrapped, internalFormat, + width, height)) { + return GL_FALSE; + } + + /* next, resize my alpha buffer */ + if (arb->Data) { + _mesa_free(arb->Data); + } + + arb->Data = _mesa_malloc(width * height * sizeof(GLubyte)); + if (arb->Data == NULL) { + arb->Width = 0; + arb->Height = 0; + _mesa_error(ctx, GL_OUT_OF_MEMORY, "software alpha buffer allocation"); + return GL_FALSE; + } + + arb->Width = width; + arb->Height = height; + arb->InternalFormat = internalFormat; + + return GL_TRUE; +} + + +/** + * Delete an alpha_renderbuffer object, as well as the wrapped RGB buffer. + */ +static void +delete_renderbuffer_alpha8(struct gl_renderbuffer *arb) +{ + if (arb->Data) { + _mesa_free(arb->Data); + } + ASSERT(arb->Wrapped); + ASSERT(arb != arb->Wrapped); + arb->Wrapped->Delete(arb->Wrapped); + arb->Wrapped = NULL; + _mesa_free(arb); +} + + +static void * +get_pointer_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, + GLint x, GLint y) +{ + return NULL; /* don't allow direct access! */ +} + + +static void +get_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, + GLint x, GLint y, void *values) +{ + /* NOTE: 'values' is RGBA format! */ + const GLubyte *src = (const GLubyte *) arb->Data + y * arb->Width + x; + GLubyte *dst = (GLubyte *) values; + GLuint i; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->GetRow(ctx, arb->Wrapped, count, x, y, values); + /* second, fill in alpha values from this buffer! */ + for (i = 0; i < count; i++) { + dst[i * 4 + 3] = src[i]; + } +} + + +static void +get_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + GLubyte *dst = (GLubyte *) values; + GLuint i; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->GetValues(ctx, arb->Wrapped, count, x, y, values); + /* second, fill in alpha values from this buffer! */ + for (i = 0; i < count; i++) { + const GLubyte *src = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; + dst[i * 4 + 3] = *src; + } +} + + +static void +put_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const GLubyte *src = (const GLubyte *) values; + GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; + GLuint i; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->PutRow(ctx, arb->Wrapped, count, x, y, values, mask); + /* second, store alpha in our buffer */ + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = src[i * 4 + 3]; + } + } +} + + +static void +put_row_rgb_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const GLubyte *src = (const GLubyte *) values; + GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; + GLuint i; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->PutRowRGB(ctx, arb->Wrapped, count, x, y, values, mask); + /* second, store alpha in our buffer */ + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i] = src[i * 4 + 3]; + } + } +} + + +static void +put_mono_row_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const GLubyte val = ((const GLubyte *) value)[3]; + GLubyte *dst = (GLubyte *) arb->Data + y * arb->Width + x; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->PutMonoRow(ctx, arb->Wrapped, count, x, y, value, mask); + /* second, store alpha in our buffer */ + if (mask) { + GLuint i; + for (i = 0; i < count; i++) { + if (mask[i]) { + dst[i] = val; + } + } + } + else { + _mesa_memset(dst, val, count); + } +} + + +static void +put_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, GLuint count, + const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + const GLubyte *src = (const GLubyte *) values; + GLuint i; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, values, mask); + /* second, store alpha in our buffer */ + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; + *dst = src[i * 4 + 3]; + } + } +} + + +static void +put_mono_values_alpha8(GLcontext *ctx, struct gl_renderbuffer *arb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + const GLubyte val = ((const GLubyte *) value)[3]; + GLuint i; + ASSERT(arb != arb->Wrapped); + ASSERT(arb->DataType == GL_UNSIGNED_BYTE); + /* first, pass the call to the wrapped RGB buffer */ + arb->Wrapped->PutValues(ctx, arb->Wrapped, count, x, y, value, mask); + /* second, store alpha in our buffer */ + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLubyte *dst = (GLubyte *) arb->Data + y[i] * arb->Width + x[i]; + *dst = val; + } + } +} + + + +/**********************************************************************/ +/**********************************************************************/ +/**********************************************************************/ + + +/** + * Default GetPointer routine. Always return NULL to indicate that + * direct buffer access is not supported. + */ +static void * +nop_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, GLint x, GLint y) +{ + return NULL; +} + + +/** + * Initialize the fields of a gl_renderbuffer to default values. + */ +void +_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name) +{ + rb->Name = name; + rb->RefCount = 1; + rb->Delete = _mesa_delete_renderbuffer; + + /* The rest of these should be set later by the caller of this function or + * the AllocStorage method: + */ + rb->AllocStorage = NULL; + + rb->Width = 0; + rb->Height = 0; + rb->InternalFormat = GL_NONE; + rb->_BaseFormat = GL_NONE; + rb->DataType = GL_NONE; + rb->ComponentSizes[0] = 0; + rb->ComponentSizes[1] = 0; + rb->ComponentSizes[2] = 0; + rb->ComponentSizes[3] = 0; + rb->Data = NULL; + + /* Point back to ourself so that we don't have to check for Wrapped==NULL + * all over the drivers. + */ + rb->Wrapped = rb; + + rb->GetPointer = nop_get_pointer; + rb->GetRow = NULL; + rb->GetValues = NULL; + rb->PutRow = NULL; + rb->PutRowRGB = NULL; + rb->PutMonoRow = NULL; + rb->PutValues = NULL; + rb->PutMonoValues = NULL; +} + + +/** + * Allocate a new gl_renderbuffer object. This can be used for user-created + * renderbuffers or window-system renderbuffers. + */ +struct gl_renderbuffer * +_mesa_new_renderbuffer(GLcontext *ctx, GLuint name) +{ + struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); + if (rb) { + _mesa_init_renderbuffer(rb, name); + } + return rb; +} + + +/** + * Delete a gl_framebuffer. + * This is the default function for framebuffer->Delete(). + */ +void +_mesa_delete_renderbuffer(struct gl_renderbuffer *rb) +{ + if (rb->Data) { + _mesa_free(rb->Data); + } + _mesa_free(rb); +} + + +/** + * Allocate a software-based renderbuffer. This is called via the + * ctx->Driver.NewRenderbuffer() function when the user creates a new + * renderbuffer. + */ +struct gl_renderbuffer * +_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name) +{ + struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); + if (rb) { + rb->AllocStorage = soft_renderbuffer_storage; + /* Normally, one would setup the PutRow, GetRow, etc functions here. + * But we're doing that in the soft_renderbuffer_storage() function + * instead. + */ + } + return rb; +} + + +/** + * Add software-based color renderbuffers to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + */ +GLboolean +_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint rgbBits, GLuint alphaBits, + GLboolean frontLeft, GLboolean backLeft, + GLboolean frontRight, GLboolean backRight) +{ + GLuint b; + + if (rgbBits > 16 || alphaBits > 16) { + _mesa_problem(ctx, + "Unsupported bit depth in _mesa_add_color_renderbuffers"); + return GL_FALSE; + } + + assert(MAX_COLOR_ATTACHMENTS >= 4); + + for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { + struct gl_renderbuffer *rb; + + if (b == BUFFER_FRONT_LEFT && !frontLeft) + continue; + else if (b == BUFFER_BACK_LEFT && !backLeft) + continue; + else if (b == BUFFER_FRONT_RIGHT && !frontRight) + continue; + else if (b == BUFFER_BACK_RIGHT && !backRight) + continue; + + assert(fb->Attachment[b].Renderbuffer == NULL); + + rb = _mesa_new_renderbuffer(ctx, 0); + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); + return GL_FALSE; + } + + if (rgbBits <= 8) { + if (alphaBits) + rb->InternalFormat = GL_RGBA8; + else + rb->InternalFormat = GL_RGB8; + } + else { + assert(rgbBits <= 16); + if (alphaBits) + rb->InternalFormat = GL_RGBA16; + else + rb->InternalFormat = GL_RGBA16; /* don't really have RGB16 yet */ + } + + rb->AllocStorage = soft_renderbuffer_storage; + _mesa_add_renderbuffer(fb, b, rb); + } + + return GL_TRUE; +} + + +/** + * Add software-based color index renderbuffers to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + */ +GLboolean +_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint indexBits, + GLboolean frontLeft, GLboolean backLeft, + GLboolean frontRight, GLboolean backRight) +{ + GLuint b; + + if (indexBits > 8) { + _mesa_problem(ctx, + "Unsupported bit depth in _mesa_add_color_renderbuffers"); + return GL_FALSE; + } + + assert(MAX_COLOR_ATTACHMENTS >= 4); + + for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { + struct gl_renderbuffer *rb; + + if (b == BUFFER_FRONT_LEFT && !frontLeft) + continue; + else if (b == BUFFER_BACK_LEFT && !backLeft) + continue; + else if (b == BUFFER_FRONT_RIGHT && !frontRight) + continue; + else if (b == BUFFER_BACK_RIGHT && !backRight) + continue; + + assert(fb->Attachment[b].Renderbuffer == NULL); + + rb = _mesa_new_renderbuffer(ctx, 0); + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating color buffer"); + return GL_FALSE; + } + + if (indexBits <= 8) { + /* only support GLuint for now */ + /*rb->InternalFormat = GL_COLOR_INDEX8_EXT;*/ + rb->InternalFormat = COLOR_INDEX32; + } + else { + rb->InternalFormat = COLOR_INDEX32; + } + rb->AllocStorage = soft_renderbuffer_storage; + _mesa_add_renderbuffer(fb, b, rb); + } + + return GL_TRUE; +} + + +/** + * Add software-based alpha renderbuffers to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + */ +GLboolean +_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint alphaBits, + GLboolean frontLeft, GLboolean backLeft, + GLboolean frontRight, GLboolean backRight) +{ + GLuint b; + + /* for window system framebuffers only! */ + assert(fb->Name == 0); + + if (alphaBits > 8) { + _mesa_problem(ctx, + "Unsupported bit depth in _mesa_add_alpha_renderbuffers"); + return GL_FALSE; + } + + assert(MAX_COLOR_ATTACHMENTS >= 4); + + /* Wrap each of the RGB color buffers with an alpha renderbuffer. + */ + for (b = BUFFER_FRONT_LEFT; b <= BUFFER_BACK_RIGHT; b++) { + struct gl_renderbuffer *arb; + + if (b == BUFFER_FRONT_LEFT && !frontLeft) + continue; + else if (b == BUFFER_BACK_LEFT && !backLeft) + continue; + else if (b == BUFFER_FRONT_RIGHT && !frontRight) + continue; + else if (b == BUFFER_BACK_RIGHT && !backRight) + continue; + + /* the RGB buffer to wrap must already exist!! */ + assert(fb->Attachment[b].Renderbuffer); + + /* only GLubyte supported for now */ + assert(fb->Attachment[b].Renderbuffer->DataType == GL_UNSIGNED_BYTE); + + /* allocate alpha renderbuffer */ + arb = _mesa_new_renderbuffer(ctx, 0); + if (!arb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating alpha buffer"); + return GL_FALSE; + } + + /* wrap the alpha renderbuffer around the RGB renderbuffer */ + arb->Wrapped = fb->Attachment[b].Renderbuffer; + + /* Set up my alphabuffer fields and plug in my functions. + * The functions will put/get the alpha values from/to RGBA arrays + * and then call the wrapped buffer's functions to handle the RGB + * values. + */ + arb->InternalFormat = arb->Wrapped->InternalFormat; + arb->_BaseFormat = arb->Wrapped->_BaseFormat; + arb->DataType = arb->Wrapped->DataType; + arb->AllocStorage = alloc_storage_alpha8; + arb->Delete = delete_renderbuffer_alpha8; + arb->GetPointer = get_pointer_alpha8; + arb->GetRow = get_row_alpha8; + arb->GetValues = get_values_alpha8; + arb->PutRow = put_row_alpha8; + arb->PutRowRGB = put_row_rgb_alpha8; + arb->PutMonoRow = put_mono_row_alpha8; + arb->PutValues = put_values_alpha8; + arb->PutMonoValues = put_mono_values_alpha8; + + /* clear the pointer to avoid assertion/sanity check failure later */ + fb->Attachment[b].Renderbuffer = NULL; + + /* plug the alpha renderbuffer into the colorbuffer attachment */ + _mesa_add_renderbuffer(fb, b, arb); + } + + return GL_TRUE; +} + + +/** + * Add a software-based depth renderbuffer to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + */ +GLboolean +_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint depthBits) +{ + struct gl_renderbuffer *rb; + + if (depthBits > 32) { + _mesa_problem(ctx, + "Unsupported depthBits in _mesa_add_depth_renderbuffer"); + return GL_FALSE; + } + + assert(fb->Attachment[BUFFER_DEPTH].Renderbuffer == NULL); + + rb = _mesa_new_renderbuffer(ctx, 0); + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating depth buffer"); + return GL_FALSE; + } + + if (depthBits <= 16) { + rb->InternalFormat = GL_DEPTH_COMPONENT16; + } + else { + rb->InternalFormat = GL_DEPTH_COMPONENT32; + } + + rb->AllocStorage = soft_renderbuffer_storage; + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); + + return GL_TRUE; +} + + +/** + * Add a software-based stencil renderbuffer to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + */ +GLboolean +_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint stencilBits) +{ + struct gl_renderbuffer *rb; + + if (stencilBits > 16) { + _mesa_problem(ctx, + "Unsupported stencilBits in _mesa_add_stencil_renderbuffer"); + return GL_FALSE; + } + + assert(fb->Attachment[BUFFER_STENCIL].Renderbuffer == NULL); + + rb = _mesa_new_renderbuffer(ctx, 0); + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating stencil buffer"); + return GL_FALSE; + } + + if (stencilBits <= 8) { + rb->InternalFormat = GL_STENCIL_INDEX8_EXT; + } + else { + /* not really supported (see s_stencil.c code) */ + rb->InternalFormat = GL_STENCIL_INDEX16_EXT; + } + + rb->AllocStorage = soft_renderbuffer_storage; + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); + + return GL_TRUE; +} + + +/** + * Add a software-based accumulation renderbuffer to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + */ +GLboolean +_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint redBits, GLuint greenBits, + GLuint blueBits, GLuint alphaBits) +{ + struct gl_renderbuffer *rb; + + if (redBits > 16 || greenBits > 16 || blueBits > 16 || alphaBits > 16) { + _mesa_problem(ctx, + "Unsupported accumBits in _mesa_add_accum_renderbuffer"); + return GL_FALSE; + } + + assert(fb->Attachment[BUFFER_ACCUM].Renderbuffer == NULL); + + rb = _mesa_new_renderbuffer(ctx, 0); + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); + return GL_FALSE; + } + + rb->InternalFormat = GL_RGBA16; + rb->AllocStorage = soft_renderbuffer_storage; + _mesa_add_renderbuffer(fb, BUFFER_ACCUM, rb); + + return GL_TRUE; +} + + + +/** + * Add a software-based accumulation renderbuffer to the given framebuffer. + * This is a helper routine for device drivers when creating a + * window system framebuffer (not a user-created render/framebuffer). + * Once this function is called, you can basically forget about this + * renderbuffer; core Mesa will handle all the buffer management and + * rendering! + * + * NOTE: color-index aux buffers not supported. + */ +GLboolean +_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint colorBits, GLuint numBuffers) +{ + GLuint i; + + if (colorBits > 16) { + _mesa_problem(ctx, + "Unsupported accumBits in _mesa_add_aux_renderbuffers"); + return GL_FALSE; + } + + assert(numBuffers < MAX_AUX_BUFFERS); + + for (i = 0; i < numBuffers; i++) { + struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, 0); + + assert(fb->Attachment[BUFFER_AUX0 + i].Renderbuffer == NULL); + + if (!rb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Allocating accum buffer"); + return GL_FALSE; + } + + if (colorBits <= 8) { + rb->InternalFormat = GL_RGBA8; + } + else { + rb->InternalFormat = GL_RGBA16; + } + + rb->AllocStorage = soft_renderbuffer_storage; + _mesa_add_renderbuffer(fb, BUFFER_AUX0 + i, rb); + } + return GL_TRUE; +} + + + +/** + * Attach a renderbuffer to a framebuffer. + */ +void +_mesa_add_renderbuffer(struct gl_framebuffer *fb, + GLuint bufferName, struct gl_renderbuffer *rb) +{ + assert(fb); + assert(rb); + /* there should be no previous renderbuffer on this attachment point! */ + assert(fb->Attachment[bufferName].Renderbuffer == NULL); + assert(bufferName < BUFFER_COUNT); + + /* winsys vs. user-created buffer cross check */ + if (fb->Name) { + assert(rb->Name); + } + else { + assert(!rb->Name); + } + + fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT; + fb->Attachment[bufferName].Complete = GL_TRUE; + fb->Attachment[bufferName].Renderbuffer = rb; +} diff --git a/src/mesa/main/renderbuffer.h b/src/mesa/main/renderbuffer.h new file mode 100644 index 00000000000..5c11de7c8a3 --- /dev/null +++ b/src/mesa/main/renderbuffer.h @@ -0,0 +1,84 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef RENDERBUFFER_H +#define RENDERBUFFER_H + + +extern void +_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name); + +extern struct gl_renderbuffer * +_mesa_new_renderbuffer(GLcontext *ctx, GLuint name); + +extern void +_mesa_delete_renderbuffer(struct gl_renderbuffer *rb); + + +extern struct gl_renderbuffer * +_mesa_new_soft_renderbuffer(GLcontext *ctx, GLuint name); + + +extern GLboolean +_mesa_add_color_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint rgbBits, GLuint alphaBits, + GLboolean frontLeft, GLboolean backLeft, + GLboolean frontRight, GLboolean backRight); + +extern GLboolean +_mesa_add_color_index_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint indexBits, + GLboolean frontLeft, GLboolean backLeft, + GLboolean frontRight, GLboolean backRight); + +extern GLboolean +_mesa_add_alpha_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint alphaBits, + GLboolean frontLeft, GLboolean backLeft, + GLboolean frontRight, GLboolean backRight); + +extern GLboolean +_mesa_add_depth_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint depthBits); + +extern GLboolean +_mesa_add_stencil_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint stencilBits); + + +extern GLboolean +_mesa_add_accum_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint redBits, GLuint greenBits, + GLuint blueBits, GLuint alphaBits); + +extern GLboolean +_mesa_add_aux_renderbuffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint bits, GLuint numBuffers); + +extern void +_mesa_add_renderbuffer(struct gl_framebuffer *fb, + GLuint bufferName, struct gl_renderbuffer *rb); + +#endif /* RENDERBUFFER_H */ diff --git a/src/mesa/main/simple_list.h b/src/mesa/main/simple_list.h new file mode 100644 index 00000000000..63475f6f740 --- /dev/null +++ b/src/mesa/main/simple_list.h @@ -0,0 +1,197 @@ +/** + * \file simple_list.h + * Simple macros for type-safe, intrusive lists. + * + * Intended to work with a list sentinal which is created as an empty + * list. Insert & delete are O(1). + * + * \author + * (C) 1997, Keith Whitwell + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _SIMPLE_LIST_H +#define _SIMPLE_LIST_H + +/** + * Remove an element from list. + * + * \param elem element to remove. + */ +#define remove_from_list(elem) \ +do { \ + (elem)->next->prev = (elem)->prev; \ + (elem)->prev->next = (elem)->next; \ +} while (0) + +/** + * Insert an element to the list head. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_head(list, elem) \ +do { \ + (elem)->prev = list; \ + (elem)->next = (list)->next; \ + (list)->next->prev = elem; \ + (list)->next = elem; \ +} while(0) + +/** + * Insert an element to the list tail. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_tail(list, elem) \ +do { \ + (elem)->next = list; \ + (elem)->prev = (list)->prev; \ + (list)->prev->next = elem; \ + (list)->prev = elem; \ +} while(0) + +/** + * Move an element to the list head. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_head(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_head(list, elem); \ +} while (0) + +/** + * Move an element to the list tail. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_tail(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_tail(list, elem); \ +} while (0) + +/** + * Make a empty list empty. + * + * \param sentinal list (sentinal element). + */ +#define make_empty_list(sentinal) \ +do { \ + (sentinal)->next = sentinal; \ + (sentinal)->prev = sentinal; \ +} while (0) + +/** + * Get list first element. + * + * \param list list. + * + * \return pointer to first element. + */ +#define first_elem(list) ((list)->next) + +/** + * Get list last element. + * + * \param list list. + * + * \return pointer to last element. + */ +#define last_elem(list) ((list)->prev) + +/** + * Get next element. + * + * \param elem element. + * + * \return pointer to next element. + */ +#define next_elem(elem) ((elem)->next) + +/** + * Get previous element. + * + * \param elem element. + * + * \return pointer to previous element. + */ +#define prev_elem(elem) ((elem)->prev) + +/** + * Test whether element is at end of the list. + * + * \param list list. + * \param elem element. + * + * \return non-zero if element is at end of list, or zero otherwise. + */ +#define at_end(list, elem) ((elem) == (list)) + +/** + * Test if a list is empty. + * + * \param list list. + * + * \return non-zero if list empty, or zero otherwise. + */ +#define is_empty_list(list) ((list)->next == (list)) + +/** + * Walk through the elements of a list. + * + * \param ptr pointer to the current element. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach(ptr, list) \ + for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next ) + +/** + * Walk through the elements of a list. + * + * Same as #foreach but lets you unlink the current value during a list + * traversal. Useful for freeing a list, element by element. + * + * \param ptr pointer to the current element. + * \param t temporary pointer. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach_s(ptr, t, list) \ + for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) + +#endif diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c new file mode 100644 index 00000000000..9ab2c5fb8a9 --- /dev/null +++ b/src/mesa/main/state.c @@ -0,0 +1,1040 @@ +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file state.c + * State management. + * + * This file manages recalculation of derived values in the __GLcontextRec. + * Also, this is where we initialize the API dispatch table. + */ + +#include "glheader.h" +#include "accum.h" +#include "api_loopback.h" +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program +#include "arbprogram.h" +#endif +#if FEATURE_ATI_fragment_shader +#include "atifragshader.h" +#endif +#include "attrib.h" +#include "blend.h" +#if FEATURE_ARB_vertex_buffer_object +#include "bufferobj.h" +#endif +#include "buffers.h" +#include "clip.h" +#include "colortab.h" +#include "context.h" +#include "convolve.h" +#include "depth.h" +#include "dlist.h" +#include "drawpix.h" +#include "enable.h" +#include "eval.h" +#include "get.h" +#include "feedback.h" +#include "fog.h" +#if FEATURE_EXT_framebuffer_object +#include "fbobject.h" +#endif +#include "framebuffer.h" +#include "hint.h" +#include "histogram.h" +#include "imports.h" +#include "light.h" +#include "lines.h" +#include "macros.h" +#include "matrix.h" +#if FEATURE_ARB_occlusion_query +#include "occlude.h" +#endif +#include "pixel.h" +#include "points.h" +#include "polygon.h" +#include "rastpos.h" +#include "state.h" +#include "stencil.h" +#include "teximage.h" +#include "texobj.h" +#include "texstate.h" +#include "mtypes.h" +#include "varray.h" +#if FEATURE_NV_vertex_program +#include "nvprogram.h" +#endif +#if FEATURE_NV_fragment_program +#include "nvfragprog.h" +#include "nvprogram.h" +#include "program.h" +#include "texenvprogram.h" +#endif +#if FEATURE_ARB_shader_objects +#include "shaderobjects.h" +#endif +#include "debug.h" +#include "dispatch.h" + + + +/** + * Initialize a dispatch table with pointers to Mesa's immediate-mode + * commands. + * + * Pointers to glBegin()/glEnd() object commands and a few others + * are provided via the GLvertexformat interface. + * + * \param ctx GL context to which \c exec belongs. + * \param exec dispatch table. + */ +void +_mesa_init_exec_table(struct _glapi_table *exec) +{ +#if _HAVE_FULL_GL + _mesa_loopback_init_api_table( exec ); +#endif + + /* load the dispatch slots we understand */ + SET_AlphaFunc(exec, _mesa_AlphaFunc); + SET_BlendFunc(exec, _mesa_BlendFunc); + SET_Clear(exec, _mesa_Clear); + SET_ClearColor(exec, _mesa_ClearColor); + SET_ClearStencil(exec, _mesa_ClearStencil); + SET_ColorMask(exec, _mesa_ColorMask); + SET_CullFace(exec, _mesa_CullFace); + SET_Disable(exec, _mesa_Disable); + SET_DrawBuffer(exec, _mesa_DrawBuffer); + SET_Enable(exec, _mesa_Enable); + SET_Finish(exec, _mesa_Finish); + SET_Flush(exec, _mesa_Flush); + SET_FrontFace(exec, _mesa_FrontFace); + SET_Frustum(exec, _mesa_Frustum); + SET_GetError(exec, _mesa_GetError); + SET_GetFloatv(exec, _mesa_GetFloatv); + SET_GetString(exec, _mesa_GetString); + SET_InitNames(exec, _mesa_InitNames); + SET_LineStipple(exec, _mesa_LineStipple); + SET_LineWidth(exec, _mesa_LineWidth); + SET_LoadIdentity(exec, _mesa_LoadIdentity); + SET_LoadMatrixf(exec, _mesa_LoadMatrixf); + SET_LoadName(exec, _mesa_LoadName); + SET_LogicOp(exec, _mesa_LogicOp); + SET_MatrixMode(exec, _mesa_MatrixMode); + SET_MultMatrixf(exec, _mesa_MultMatrixf); + SET_Ortho(exec, _mesa_Ortho); + SET_PixelStorei(exec, _mesa_PixelStorei); + SET_PopMatrix(exec, _mesa_PopMatrix); + SET_PopName(exec, _mesa_PopName); + SET_PushMatrix(exec, _mesa_PushMatrix); + SET_PushName(exec, _mesa_PushName); + SET_RasterPos2f(exec, _mesa_RasterPos2f); + SET_RasterPos2fv(exec, _mesa_RasterPos2fv); + SET_RasterPos2i(exec, _mesa_RasterPos2i); + SET_RasterPos2iv(exec, _mesa_RasterPos2iv); + SET_ReadBuffer(exec, _mesa_ReadBuffer); + SET_RenderMode(exec, _mesa_RenderMode); + SET_Rotatef(exec, _mesa_Rotatef); + SET_Scalef(exec, _mesa_Scalef); + SET_Scissor(exec, _mesa_Scissor); + SET_SelectBuffer(exec, _mesa_SelectBuffer); + SET_ShadeModel(exec, _mesa_ShadeModel); + SET_StencilFunc(exec, _mesa_StencilFunc); + SET_StencilMask(exec, _mesa_StencilMask); + SET_StencilOp(exec, _mesa_StencilOp); + SET_TexEnvfv(exec, _mesa_TexEnvfv); + SET_TexEnvi(exec, _mesa_TexEnvi); + SET_TexImage2D(exec, _mesa_TexImage2D); + SET_TexParameteri(exec, _mesa_TexParameteri); + SET_Translatef(exec, _mesa_Translatef); + SET_Viewport(exec, _mesa_Viewport); +#if _HAVE_FULL_GL + SET_Accum(exec, _mesa_Accum); + SET_Bitmap(exec, _mesa_Bitmap); + SET_CallList(exec, _mesa_CallList); + SET_CallLists(exec, _mesa_CallLists); + SET_ClearAccum(exec, _mesa_ClearAccum); + SET_ClearDepth(exec, _mesa_ClearDepth); + SET_ClearIndex(exec, _mesa_ClearIndex); + SET_ClipPlane(exec, _mesa_ClipPlane); + SET_ColorMaterial(exec, _mesa_ColorMaterial); + SET_CopyPixels(exec, _mesa_CopyPixels); + SET_CullParameterfvEXT(exec, _mesa_CullParameterfvEXT); + SET_CullParameterdvEXT(exec, _mesa_CullParameterdvEXT); + SET_DeleteLists(exec, _mesa_DeleteLists); + SET_DepthFunc(exec, _mesa_DepthFunc); + SET_DepthMask(exec, _mesa_DepthMask); + SET_DepthRange(exec, _mesa_DepthRange); + SET_DrawPixels(exec, _mesa_DrawPixels); + SET_EndList(exec, _mesa_EndList); + SET_FeedbackBuffer(exec, _mesa_FeedbackBuffer); + SET_FogCoordPointerEXT(exec, _mesa_FogCoordPointerEXT); + SET_Fogf(exec, _mesa_Fogf); + SET_Fogfv(exec, _mesa_Fogfv); + SET_Fogi(exec, _mesa_Fogi); + SET_Fogiv(exec, _mesa_Fogiv); + SET_GenLists(exec, _mesa_GenLists); + SET_GetClipPlane(exec, _mesa_GetClipPlane); + SET_GetBooleanv(exec, _mesa_GetBooleanv); + SET_GetDoublev(exec, _mesa_GetDoublev); + SET_GetIntegerv(exec, _mesa_GetIntegerv); + SET_GetLightfv(exec, _mesa_GetLightfv); + SET_GetLightiv(exec, _mesa_GetLightiv); + SET_GetMapdv(exec, _mesa_GetMapdv); + SET_GetMapfv(exec, _mesa_GetMapfv); + SET_GetMapiv(exec, _mesa_GetMapiv); + SET_GetMaterialfv(exec, _mesa_GetMaterialfv); + SET_GetMaterialiv(exec, _mesa_GetMaterialiv); + SET_GetPixelMapfv(exec, _mesa_GetPixelMapfv); + SET_GetPixelMapuiv(exec, _mesa_GetPixelMapuiv); + SET_GetPixelMapusv(exec, _mesa_GetPixelMapusv); + SET_GetPolygonStipple(exec, _mesa_GetPolygonStipple); + SET_GetTexEnvfv(exec, _mesa_GetTexEnvfv); + SET_GetTexEnviv(exec, _mesa_GetTexEnviv); + SET_GetTexLevelParameterfv(exec, _mesa_GetTexLevelParameterfv); + SET_GetTexLevelParameteriv(exec, _mesa_GetTexLevelParameteriv); + SET_GetTexParameterfv(exec, _mesa_GetTexParameterfv); + SET_GetTexParameteriv(exec, _mesa_GetTexParameteriv); + SET_GetTexGendv(exec, _mesa_GetTexGendv); + SET_GetTexGenfv(exec, _mesa_GetTexGenfv); + SET_GetTexGeniv(exec, _mesa_GetTexGeniv); + SET_GetTexImage(exec, _mesa_GetTexImage); + SET_Hint(exec, _mesa_Hint); + SET_IndexMask(exec, _mesa_IndexMask); + SET_IsEnabled(exec, _mesa_IsEnabled); + SET_IsList(exec, _mesa_IsList); + SET_LightModelf(exec, _mesa_LightModelf); + SET_LightModelfv(exec, _mesa_LightModelfv); + SET_LightModeli(exec, _mesa_LightModeli); + SET_LightModeliv(exec, _mesa_LightModeliv); + SET_Lightf(exec, _mesa_Lightf); + SET_Lightfv(exec, _mesa_Lightfv); + SET_Lighti(exec, _mesa_Lighti); + SET_Lightiv(exec, _mesa_Lightiv); + SET_ListBase(exec, _mesa_ListBase); + SET_LoadMatrixd(exec, _mesa_LoadMatrixd); + SET_Map1d(exec, _mesa_Map1d); + SET_Map1f(exec, _mesa_Map1f); + SET_Map2d(exec, _mesa_Map2d); + SET_Map2f(exec, _mesa_Map2f); + SET_MapGrid1d(exec, _mesa_MapGrid1d); + SET_MapGrid1f(exec, _mesa_MapGrid1f); + SET_MapGrid2d(exec, _mesa_MapGrid2d); + SET_MapGrid2f(exec, _mesa_MapGrid2f); + SET_MultMatrixd(exec, _mesa_MultMatrixd); + SET_NewList(exec, _mesa_NewList); + SET_PassThrough(exec, _mesa_PassThrough); + SET_PixelMapfv(exec, _mesa_PixelMapfv); + SET_PixelMapuiv(exec, _mesa_PixelMapuiv); + SET_PixelMapusv(exec, _mesa_PixelMapusv); + SET_PixelStoref(exec, _mesa_PixelStoref); + SET_PixelTransferf(exec, _mesa_PixelTransferf); + SET_PixelTransferi(exec, _mesa_PixelTransferi); + SET_PixelZoom(exec, _mesa_PixelZoom); + SET_PointSize(exec, _mesa_PointSize); + SET_PolygonMode(exec, _mesa_PolygonMode); + SET_PolygonOffset(exec, _mesa_PolygonOffset); + SET_PolygonStipple(exec, _mesa_PolygonStipple); + SET_PopAttrib(exec, _mesa_PopAttrib); + SET_PushAttrib(exec, _mesa_PushAttrib); + SET_RasterPos2d(exec, _mesa_RasterPos2d); + SET_RasterPos2dv(exec, _mesa_RasterPos2dv); + SET_RasterPos2s(exec, _mesa_RasterPos2s); + SET_RasterPos2sv(exec, _mesa_RasterPos2sv); + SET_RasterPos3d(exec, _mesa_RasterPos3d); + SET_RasterPos3dv(exec, _mesa_RasterPos3dv); + SET_RasterPos3f(exec, _mesa_RasterPos3f); + SET_RasterPos3fv(exec, _mesa_RasterPos3fv); + SET_RasterPos3i(exec, _mesa_RasterPos3i); + SET_RasterPos3iv(exec, _mesa_RasterPos3iv); + SET_RasterPos3s(exec, _mesa_RasterPos3s); + SET_RasterPos3sv(exec, _mesa_RasterPos3sv); + SET_RasterPos4d(exec, _mesa_RasterPos4d); + SET_RasterPos4dv(exec, _mesa_RasterPos4dv); + SET_RasterPos4f(exec, _mesa_RasterPos4f); + SET_RasterPos4fv(exec, _mesa_RasterPos4fv); + SET_RasterPos4i(exec, _mesa_RasterPos4i); + SET_RasterPos4iv(exec, _mesa_RasterPos4iv); + SET_RasterPos4s(exec, _mesa_RasterPos4s); + SET_RasterPos4sv(exec, _mesa_RasterPos4sv); + SET_ReadPixels(exec, _mesa_ReadPixels); + SET_Rotated(exec, _mesa_Rotated); + SET_Scaled(exec, _mesa_Scaled); + SET_SecondaryColorPointerEXT(exec, _mesa_SecondaryColorPointerEXT); + SET_TexEnvf(exec, _mesa_TexEnvf); + SET_TexEnviv(exec, _mesa_TexEnviv); + SET_TexGend(exec, _mesa_TexGend); + SET_TexGendv(exec, _mesa_TexGendv); + SET_TexGenf(exec, _mesa_TexGenf); + SET_TexGenfv(exec, _mesa_TexGenfv); + SET_TexGeni(exec, _mesa_TexGeni); + SET_TexGeniv(exec, _mesa_TexGeniv); + SET_TexImage1D(exec, _mesa_TexImage1D); + SET_TexParameterf(exec, _mesa_TexParameterf); + SET_TexParameterfv(exec, _mesa_TexParameterfv); + SET_TexParameteriv(exec, _mesa_TexParameteriv); + SET_Translated(exec, _mesa_Translated); +#endif + + /* 1.1 */ + SET_BindTexture(exec, _mesa_BindTexture); + SET_DeleteTextures(exec, _mesa_DeleteTextures); + SET_GenTextures(exec, _mesa_GenTextures); +#if _HAVE_FULL_GL + SET_AreTexturesResident(exec, _mesa_AreTexturesResident); + SET_AreTexturesResidentEXT(exec, _mesa_AreTexturesResident); + SET_ColorPointer(exec, _mesa_ColorPointer); + SET_CopyTexImage1D(exec, _mesa_CopyTexImage1D); + SET_CopyTexImage2D(exec, _mesa_CopyTexImage2D); + SET_CopyTexSubImage1D(exec, _mesa_CopyTexSubImage1D); + SET_CopyTexSubImage2D(exec, _mesa_CopyTexSubImage2D); + SET_DisableClientState(exec, _mesa_DisableClientState); + SET_EdgeFlagPointer(exec, _mesa_EdgeFlagPointer); + SET_EnableClientState(exec, _mesa_EnableClientState); + SET_GenTexturesEXT(exec, _mesa_GenTextures); + SET_GetPointerv(exec, _mesa_GetPointerv); + SET_IndexPointer(exec, _mesa_IndexPointer); + SET_InterleavedArrays(exec, _mesa_InterleavedArrays); + SET_IsTexture(exec, _mesa_IsTexture); + SET_IsTextureEXT(exec, _mesa_IsTexture); + SET_NormalPointer(exec, _mesa_NormalPointer); + SET_PopClientAttrib(exec, _mesa_PopClientAttrib); + SET_PrioritizeTextures(exec, _mesa_PrioritizeTextures); + SET_PushClientAttrib(exec, _mesa_PushClientAttrib); + SET_TexCoordPointer(exec, _mesa_TexCoordPointer); + SET_TexSubImage1D(exec, _mesa_TexSubImage1D); + SET_TexSubImage2D(exec, _mesa_TexSubImage2D); + SET_VertexPointer(exec, _mesa_VertexPointer); +#endif + + /* 1.2 */ +#if _HAVE_FULL_GL + SET_CopyTexSubImage3D(exec, _mesa_CopyTexSubImage3D); + SET_TexImage3D(exec, _mesa_TexImage3D); + SET_TexSubImage3D(exec, _mesa_TexSubImage3D); +#endif + + /* OpenGL 1.2 GL_ARB_imaging */ +#if _HAVE_FULL_GL + SET_BlendColor(exec, _mesa_BlendColor); + SET_BlendEquation(exec, _mesa_BlendEquation); + SET_BlendEquationSeparateEXT(exec, _mesa_BlendEquationSeparateEXT); + SET_ColorSubTable(exec, _mesa_ColorSubTable); + SET_ColorTable(exec, _mesa_ColorTable); + SET_ColorTableParameterfv(exec, _mesa_ColorTableParameterfv); + SET_ColorTableParameteriv(exec, _mesa_ColorTableParameteriv); + SET_ConvolutionFilter1D(exec, _mesa_ConvolutionFilter1D); + SET_ConvolutionFilter2D(exec, _mesa_ConvolutionFilter2D); + SET_ConvolutionParameterf(exec, _mesa_ConvolutionParameterf); + SET_ConvolutionParameterfv(exec, _mesa_ConvolutionParameterfv); + SET_ConvolutionParameteri(exec, _mesa_ConvolutionParameteri); + SET_ConvolutionParameteriv(exec, _mesa_ConvolutionParameteriv); + SET_CopyColorSubTable(exec, _mesa_CopyColorSubTable); + SET_CopyColorTable(exec, _mesa_CopyColorTable); + SET_CopyConvolutionFilter1D(exec, _mesa_CopyConvolutionFilter1D); + SET_CopyConvolutionFilter2D(exec, _mesa_CopyConvolutionFilter2D); + SET_GetColorTable(exec, _mesa_GetColorTable); + SET_GetColorTableEXT(exec, _mesa_GetColorTable); + SET_GetColorTableParameterfv(exec, _mesa_GetColorTableParameterfv); + SET_GetColorTableParameterfvEXT(exec, _mesa_GetColorTableParameterfv); + SET_GetColorTableParameteriv(exec, _mesa_GetColorTableParameteriv); + SET_GetColorTableParameterivEXT(exec, _mesa_GetColorTableParameteriv); + SET_GetConvolutionFilter(exec, _mesa_GetConvolutionFilter); + SET_GetConvolutionFilterEXT(exec, _mesa_GetConvolutionFilter); + SET_GetConvolutionParameterfv(exec, _mesa_GetConvolutionParameterfv); + SET_GetConvolutionParameterfvEXT(exec, _mesa_GetConvolutionParameterfv); + SET_GetConvolutionParameteriv(exec, _mesa_GetConvolutionParameteriv); + SET_GetConvolutionParameterivEXT(exec, _mesa_GetConvolutionParameteriv); + SET_GetHistogram(exec, _mesa_GetHistogram); + SET_GetHistogramEXT(exec, _mesa_GetHistogram); + SET_GetHistogramParameterfv(exec, _mesa_GetHistogramParameterfv); + SET_GetHistogramParameterfvEXT(exec, _mesa_GetHistogramParameterfv); + SET_GetHistogramParameteriv(exec, _mesa_GetHistogramParameteriv); + SET_GetHistogramParameterivEXT(exec, _mesa_GetHistogramParameteriv); + SET_GetMinmax(exec, _mesa_GetMinmax); + SET_GetMinmaxEXT(exec, _mesa_GetMinmax); + SET_GetMinmaxParameterfv(exec, _mesa_GetMinmaxParameterfv); + SET_GetMinmaxParameterfvEXT(exec, _mesa_GetMinmaxParameterfv); + SET_GetMinmaxParameteriv(exec, _mesa_GetMinmaxParameteriv); + SET_GetMinmaxParameterivEXT(exec, _mesa_GetMinmaxParameteriv); + SET_GetSeparableFilter(exec, _mesa_GetSeparableFilter); + SET_GetSeparableFilterEXT(exec, _mesa_GetSeparableFilter); + SET_Histogram(exec, _mesa_Histogram); + SET_Minmax(exec, _mesa_Minmax); + SET_ResetHistogram(exec, _mesa_ResetHistogram); + SET_ResetMinmax(exec, _mesa_ResetMinmax); + SET_SeparableFilter2D(exec, _mesa_SeparableFilter2D); +#endif + + /* OpenGL 2.0 */ + SET_StencilFuncSeparate(exec, _mesa_StencilFuncSeparate); + SET_StencilMaskSeparate(exec, _mesa_StencilMaskSeparate); + SET_StencilOpSeparate(exec, _mesa_StencilOpSeparate); + + /* 2. GL_EXT_blend_color */ +#if 0 +/* SET_BlendColorEXT(exec, _mesa_BlendColorEXT); */ +#endif + + /* 3. GL_EXT_polygon_offset */ +#if _HAVE_FULL_GL + SET_PolygonOffsetEXT(exec, _mesa_PolygonOffsetEXT); +#endif + + /* 6. GL_EXT_texture3d */ +#if 0 +/* SET_CopyTexSubImage3DEXT(exec, _mesa_CopyTexSubImage3D); */ +/* SET_TexImage3DEXT(exec, _mesa_TexImage3DEXT); */ +/* SET_TexSubImage3DEXT(exec, _mesa_TexSubImage3D); */ +#endif + + /* 11. GL_EXT_histogram */ +#if _HAVE_FULL_GL + SET_GetHistogramEXT(exec, _mesa_GetHistogram); + SET_GetHistogramParameterfvEXT(exec, _mesa_GetHistogramParameterfv); + SET_GetHistogramParameterivEXT(exec, _mesa_GetHistogramParameteriv); + SET_GetMinmaxEXT(exec, _mesa_GetMinmax); + SET_GetMinmaxParameterfvEXT(exec, _mesa_GetMinmaxParameterfv); + SET_GetMinmaxParameterivEXT(exec, _mesa_GetMinmaxParameteriv); +#endif + + /* ?. GL_SGIX_pixel_texture */ +#if _HAVE_FULL_GL + SET_PixelTexGenSGIX(exec, _mesa_PixelTexGenSGIX); +#endif + + /* 15. GL_SGIS_pixel_texture */ +#if _HAVE_FULL_GL + SET_PixelTexGenParameteriSGIS(exec, _mesa_PixelTexGenParameteriSGIS); + SET_PixelTexGenParameterivSGIS(exec, _mesa_PixelTexGenParameterivSGIS); + SET_PixelTexGenParameterfSGIS(exec, _mesa_PixelTexGenParameterfSGIS); + SET_PixelTexGenParameterfvSGIS(exec, _mesa_PixelTexGenParameterfvSGIS); + SET_GetPixelTexGenParameterivSGIS(exec, _mesa_GetPixelTexGenParameterivSGIS); + SET_GetPixelTexGenParameterfvSGIS(exec, _mesa_GetPixelTexGenParameterfvSGIS); +#endif + + /* 30. GL_EXT_vertex_array */ +#if _HAVE_FULL_GL + SET_ColorPointerEXT(exec, _mesa_ColorPointerEXT); + SET_EdgeFlagPointerEXT(exec, _mesa_EdgeFlagPointerEXT); + SET_IndexPointerEXT(exec, _mesa_IndexPointerEXT); + SET_NormalPointerEXT(exec, _mesa_NormalPointerEXT); + SET_TexCoordPointerEXT(exec, _mesa_TexCoordPointerEXT); + SET_VertexPointerEXT(exec, _mesa_VertexPointerEXT); +#endif + + /* 37. GL_EXT_blend_minmax */ +#if 0 + SET_BlendEquationEXT(exec, _mesa_BlendEquationEXT); +#endif + + /* 54. GL_EXT_point_parameters */ +#if _HAVE_FULL_GL + SET_PointParameterfEXT(exec, _mesa_PointParameterfEXT); + SET_PointParameterfvEXT(exec, _mesa_PointParameterfvEXT); +#endif + + /* 78. GL_EXT_paletted_texture */ +#if 0 + SET_ColorTableEXT(exec, _mesa_ColorTableEXT); + SET_ColorSubTableEXT(exec, _mesa_ColorSubTableEXT); +#endif +#if _HAVE_FULL_GL + SET_GetColorTableEXT(exec, _mesa_GetColorTable); + SET_GetColorTableParameterfvEXT(exec, _mesa_GetColorTableParameterfv); + SET_GetColorTableParameterivEXT(exec, _mesa_GetColorTableParameteriv); +#endif + + /* 97. GL_EXT_compiled_vertex_array */ +#if _HAVE_FULL_GL + SET_LockArraysEXT(exec, _mesa_LockArraysEXT); + SET_UnlockArraysEXT(exec, _mesa_UnlockArraysEXT); +#endif + + /* 148. GL_EXT_multi_draw_arrays */ +#if _HAVE_FULL_GL + SET_MultiDrawArraysEXT(exec, _mesa_MultiDrawArraysEXT); + SET_MultiDrawElementsEXT(exec, _mesa_MultiDrawElementsEXT); +#endif + + /* 173. GL_INGR_blend_func_separate */ +#if _HAVE_FULL_GL + SET_BlendFuncSeparateEXT(exec, _mesa_BlendFuncSeparateEXT); +#endif + + /* 196. GL_MESA_resize_buffers */ +#if _HAVE_FULL_GL + SET_ResizeBuffersMESA(exec, _mesa_ResizeBuffersMESA); +#endif + + /* 197. GL_MESA_window_pos */ +#if _HAVE_FULL_GL + SET_WindowPos2dMESA(exec, _mesa_WindowPos2dMESA); + SET_WindowPos2dvMESA(exec, _mesa_WindowPos2dvMESA); + SET_WindowPos2fMESA(exec, _mesa_WindowPos2fMESA); + SET_WindowPos2fvMESA(exec, _mesa_WindowPos2fvMESA); + SET_WindowPos2iMESA(exec, _mesa_WindowPos2iMESA); + SET_WindowPos2ivMESA(exec, _mesa_WindowPos2ivMESA); + SET_WindowPos2sMESA(exec, _mesa_WindowPos2sMESA); + SET_WindowPos2svMESA(exec, _mesa_WindowPos2svMESA); + SET_WindowPos3dMESA(exec, _mesa_WindowPos3dMESA); + SET_WindowPos3dvMESA(exec, _mesa_WindowPos3dvMESA); + SET_WindowPos3fMESA(exec, _mesa_WindowPos3fMESA); + SET_WindowPos3fvMESA(exec, _mesa_WindowPos3fvMESA); + SET_WindowPos3iMESA(exec, _mesa_WindowPos3iMESA); + SET_WindowPos3ivMESA(exec, _mesa_WindowPos3ivMESA); + SET_WindowPos3sMESA(exec, _mesa_WindowPos3sMESA); + SET_WindowPos3svMESA(exec, _mesa_WindowPos3svMESA); + SET_WindowPos4dMESA(exec, _mesa_WindowPos4dMESA); + SET_WindowPos4dvMESA(exec, _mesa_WindowPos4dvMESA); + SET_WindowPos4fMESA(exec, _mesa_WindowPos4fMESA); + SET_WindowPos4fvMESA(exec, _mesa_WindowPos4fvMESA); + SET_WindowPos4iMESA(exec, _mesa_WindowPos4iMESA); + SET_WindowPos4ivMESA(exec, _mesa_WindowPos4ivMESA); + SET_WindowPos4sMESA(exec, _mesa_WindowPos4sMESA); + SET_WindowPos4svMESA(exec, _mesa_WindowPos4svMESA); +#endif + + /* 200. GL_IBM_multimode_draw_arrays */ +#if _HAVE_FULL_GL + SET_MultiModeDrawArraysIBM(exec, _mesa_MultiModeDrawArraysIBM); + SET_MultiModeDrawElementsIBM(exec, _mesa_MultiModeDrawElementsIBM); +#endif + + /* 233. GL_NV_vertex_program */ +#if FEATURE_NV_vertex_program + SET_BindProgramNV(exec, _mesa_BindProgram); + SET_DeleteProgramsNV(exec, _mesa_DeletePrograms); + SET_ExecuteProgramNV(exec, _mesa_ExecuteProgramNV); + SET_GenProgramsNV(exec, _mesa_GenPrograms); + SET_AreProgramsResidentNV(exec, _mesa_AreProgramsResidentNV); + SET_RequestResidentProgramsNV(exec, _mesa_RequestResidentProgramsNV); + SET_GetProgramParameterfvNV(exec, _mesa_GetProgramParameterfvNV); + SET_GetProgramParameterdvNV(exec, _mesa_GetProgramParameterdvNV); + SET_GetProgramivNV(exec, _mesa_GetProgramivNV); + SET_GetProgramStringNV(exec, _mesa_GetProgramStringNV); + SET_GetTrackMatrixivNV(exec, _mesa_GetTrackMatrixivNV); + SET_GetVertexAttribdvNV(exec, _mesa_GetVertexAttribdvNV); + SET_GetVertexAttribfvNV(exec, _mesa_GetVertexAttribfvNV); + SET_GetVertexAttribivNV(exec, _mesa_GetVertexAttribivNV); + SET_GetVertexAttribPointervNV(exec, _mesa_GetVertexAttribPointervNV); + SET_IsProgramNV(exec, _mesa_IsProgram); + SET_LoadProgramNV(exec, _mesa_LoadProgramNV); + SET_ProgramParameter4dNV(exec, _mesa_ProgramParameter4dNV); + SET_ProgramParameter4dvNV(exec, _mesa_ProgramParameter4dvNV); + SET_ProgramParameter4fNV(exec, _mesa_ProgramParameter4fNV); + SET_ProgramParameter4fvNV(exec, _mesa_ProgramParameter4fvNV); + SET_ProgramParameters4dvNV(exec, _mesa_ProgramParameters4dvNV); + SET_ProgramParameters4fvNV(exec, _mesa_ProgramParameters4fvNV); + SET_TrackMatrixNV(exec, _mesa_TrackMatrixNV); + SET_VertexAttribPointerNV(exec, _mesa_VertexAttribPointerNV); + /* glVertexAttrib*NV functions handled in api_loopback.c */ +#endif + + /* 282. GL_NV_fragment_program */ +#if FEATURE_NV_fragment_program + SET_ProgramNamedParameter4fNV(exec, _mesa_ProgramNamedParameter4fNV); + SET_ProgramNamedParameter4dNV(exec, _mesa_ProgramNamedParameter4dNV); + SET_ProgramNamedParameter4fvNV(exec, _mesa_ProgramNamedParameter4fvNV); + SET_ProgramNamedParameter4dvNV(exec, _mesa_ProgramNamedParameter4dvNV); + SET_GetProgramNamedParameterfvNV(exec, _mesa_GetProgramNamedParameterfvNV); + SET_GetProgramNamedParameterdvNV(exec, _mesa_GetProgramNamedParameterdvNV); + SET_ProgramLocalParameter4dARB(exec, _mesa_ProgramLocalParameter4dARB); + SET_ProgramLocalParameter4dvARB(exec, _mesa_ProgramLocalParameter4dvARB); + SET_ProgramLocalParameter4fARB(exec, _mesa_ProgramLocalParameter4fARB); + SET_ProgramLocalParameter4fvARB(exec, _mesa_ProgramLocalParameter4fvARB); + SET_GetProgramLocalParameterdvARB(exec, _mesa_GetProgramLocalParameterdvARB); + SET_GetProgramLocalParameterfvARB(exec, _mesa_GetProgramLocalParameterfvARB); +#endif + + /* 262. GL_NV_point_sprite */ +#if _HAVE_FULL_GL + SET_PointParameteriNV(exec, _mesa_PointParameteriNV); + SET_PointParameterivNV(exec, _mesa_PointParameterivNV); +#endif + + /* 268. GL_EXT_stencil_two_side */ +#if _HAVE_FULL_GL + SET_ActiveStencilFaceEXT(exec, _mesa_ActiveStencilFaceEXT); +#endif + + /* ???. GL_EXT_depth_bounds_test */ + SET_DepthBoundsEXT(exec, _mesa_DepthBoundsEXT); + + /* ARB 1. GL_ARB_multitexture */ +#if _HAVE_FULL_GL + SET_ActiveTextureARB(exec, _mesa_ActiveTextureARB); + SET_ClientActiveTextureARB(exec, _mesa_ClientActiveTextureARB); +#endif + + /* ARB 3. GL_ARB_transpose_matrix */ +#if _HAVE_FULL_GL + SET_LoadTransposeMatrixdARB(exec, _mesa_LoadTransposeMatrixdARB); + SET_LoadTransposeMatrixfARB(exec, _mesa_LoadTransposeMatrixfARB); + SET_MultTransposeMatrixdARB(exec, _mesa_MultTransposeMatrixdARB); + SET_MultTransposeMatrixfARB(exec, _mesa_MultTransposeMatrixfARB); +#endif + + /* ARB 5. GL_ARB_multisample */ +#if _HAVE_FULL_GL + SET_SampleCoverageARB(exec, _mesa_SampleCoverageARB); +#endif + + /* ARB 12. GL_ARB_texture_compression */ +#if _HAVE_FULL_GL + SET_CompressedTexImage3DARB(exec, _mesa_CompressedTexImage3DARB); + SET_CompressedTexImage2DARB(exec, _mesa_CompressedTexImage2DARB); + SET_CompressedTexImage1DARB(exec, _mesa_CompressedTexImage1DARB); + SET_CompressedTexSubImage3DARB(exec, _mesa_CompressedTexSubImage3DARB); + SET_CompressedTexSubImage2DARB(exec, _mesa_CompressedTexSubImage2DARB); + SET_CompressedTexSubImage1DARB(exec, _mesa_CompressedTexSubImage1DARB); + SET_GetCompressedTexImageARB(exec, _mesa_GetCompressedTexImageARB); +#endif + + /* ARB 14. GL_ARB_point_parameters */ + /* reuse EXT_point_parameters functions */ + + /* ARB 26. GL_ARB_vertex_program */ + /* ARB 27. GL_ARB_fragment_program */ +#if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program + /* glVertexAttrib1sARB aliases glVertexAttrib1sNV */ + /* glVertexAttrib1fARB aliases glVertexAttrib1fNV */ + /* glVertexAttrib1dARB aliases glVertexAttrib1dNV */ + /* glVertexAttrib2sARB aliases glVertexAttrib2sNV */ + /* glVertexAttrib2fARB aliases glVertexAttrib2fNV */ + /* glVertexAttrib2dARB aliases glVertexAttrib2dNV */ + /* glVertexAttrib3sARB aliases glVertexAttrib3sNV */ + /* glVertexAttrib3fARB aliases glVertexAttrib3fNV */ + /* glVertexAttrib3dARB aliases glVertexAttrib3dNV */ + /* glVertexAttrib4sARB aliases glVertexAttrib4sNV */ + /* glVertexAttrib4fARB aliases glVertexAttrib4fNV */ + /* glVertexAttrib4dARB aliases glVertexAttrib4dNV */ + /* glVertexAttrib4NubARB aliases glVertexAttrib4NubNV */ + /* glVertexAttrib1svARB aliases glVertexAttrib1svNV */ + /* glVertexAttrib1fvARB aliases glVertexAttrib1fvNV */ + /* glVertexAttrib1dvARB aliases glVertexAttrib1dvNV */ + /* glVertexAttrib2svARB aliases glVertexAttrib2svNV */ + /* glVertexAttrib2fvARB aliases glVertexAttrib2fvNV */ + /* glVertexAttrib2dvARB aliases glVertexAttrib2dvNV */ + /* glVertexAttrib3svARB aliases glVertexAttrib3svNV */ + /* glVertexAttrib3fvARB aliases glVertexAttrib3fvNV */ + /* glVertexAttrib3dvARB aliases glVertexAttrib3dvNV */ + /* glVertexAttrib4svARB aliases glVertexAttrib4svNV */ + /* glVertexAttrib4fvARB aliases glVertexAttrib4fvNV */ + /* glVertexAttrib4dvARB aliases glVertexAttrib4dvNV */ + /* glVertexAttrib4NubvARB aliases glVertexAttrib4NubvNV */ + /* glVertexAttrib4bvARB handled in api_loopback.c */ + /* glVertexAttrib4ivARB handled in api_loopback.c */ + /* glVertexAttrib4ubvARB handled in api_loopback.c */ + /* glVertexAttrib4usvARB handled in api_loopback.c */ + /* glVertexAttrib4uivARB handled in api_loopback.c */ + /* glVertexAttrib4NbvARB handled in api_loopback.c */ + /* glVertexAttrib4NsvARB handled in api_loopback.c */ + /* glVertexAttrib4NivARB handled in api_loopback.c */ + /* glVertexAttrib4NusvARB handled in api_loopback.c */ + /* glVertexAttrib4NuivARB handled in api_loopback.c */ + SET_VertexAttribPointerARB(exec, _mesa_VertexAttribPointerARB); + SET_EnableVertexAttribArrayARB(exec, _mesa_EnableVertexAttribArrayARB); + SET_DisableVertexAttribArrayARB(exec, _mesa_DisableVertexAttribArrayARB); + SET_ProgramStringARB(exec, _mesa_ProgramStringARB); + /* glBindProgramARB aliases glBindProgramNV */ + /* glDeleteProgramsARB aliases glDeleteProgramsNV */ + /* glGenProgramsARB aliases glGenProgramsNV */ + /* glIsProgramARB aliases glIsProgramNV */ + SET_GetVertexAttribdvARB(exec, _mesa_GetVertexAttribdvARB); + SET_GetVertexAttribfvARB(exec, _mesa_GetVertexAttribfvARB); + SET_GetVertexAttribivARB(exec, _mesa_GetVertexAttribivARB); + /* glGetVertexAttribPointervARB aliases glGetVertexAttribPointervNV */ + SET_ProgramEnvParameter4dARB(exec, _mesa_ProgramEnvParameter4dARB); + SET_ProgramEnvParameter4dvARB(exec, _mesa_ProgramEnvParameter4dvARB); + SET_ProgramEnvParameter4fARB(exec, _mesa_ProgramEnvParameter4fARB); + SET_ProgramEnvParameter4fvARB(exec, _mesa_ProgramEnvParameter4fvARB); + SET_ProgramLocalParameter4dARB(exec, _mesa_ProgramLocalParameter4dARB); + SET_ProgramLocalParameter4dvARB(exec, _mesa_ProgramLocalParameter4dvARB); + SET_ProgramLocalParameter4fARB(exec, _mesa_ProgramLocalParameter4fARB); + SET_ProgramLocalParameter4fvARB(exec, _mesa_ProgramLocalParameter4fvARB); + SET_GetProgramEnvParameterdvARB(exec, _mesa_GetProgramEnvParameterdvARB); + SET_GetProgramEnvParameterfvARB(exec, _mesa_GetProgramEnvParameterfvARB); + SET_GetProgramLocalParameterdvARB(exec, _mesa_GetProgramLocalParameterdvARB); + SET_GetProgramLocalParameterfvARB(exec, _mesa_GetProgramLocalParameterfvARB); + SET_GetProgramivARB(exec, _mesa_GetProgramivARB); + SET_GetProgramStringARB(exec, _mesa_GetProgramStringARB); +#endif + + /* ARB 28. GL_ARB_vertex_buffer_object */ +#if FEATURE_ARB_vertex_buffer_object + SET_BindBufferARB(exec, _mesa_BindBufferARB); + SET_BufferDataARB(exec, _mesa_BufferDataARB); + SET_BufferSubDataARB(exec, _mesa_BufferSubDataARB); + SET_DeleteBuffersARB(exec, _mesa_DeleteBuffersARB); + SET_GenBuffersARB(exec, _mesa_GenBuffersARB); + SET_GetBufferParameterivARB(exec, _mesa_GetBufferParameterivARB); + SET_GetBufferPointervARB(exec, _mesa_GetBufferPointervARB); + SET_GetBufferSubDataARB(exec, _mesa_GetBufferSubDataARB); + SET_IsBufferARB(exec, _mesa_IsBufferARB); + SET_MapBufferARB(exec, _mesa_MapBufferARB); + SET_UnmapBufferARB(exec, _mesa_UnmapBufferARB); +#endif + + /* ARB 29. GL_ARB_occlusion_query */ +#if FEATURE_ARB_occlusion_query + SET_GenQueriesARB(exec, _mesa_GenQueriesARB); + SET_DeleteQueriesARB(exec, _mesa_DeleteQueriesARB); + SET_IsQueryARB(exec, _mesa_IsQueryARB); + SET_BeginQueryARB(exec, _mesa_BeginQueryARB); + SET_EndQueryARB(exec, _mesa_EndQueryARB); + SET_GetQueryivARB(exec, _mesa_GetQueryivARB); + SET_GetQueryObjectivARB(exec, _mesa_GetQueryObjectivARB); + SET_GetQueryObjectuivARB(exec, _mesa_GetQueryObjectuivARB); +#endif + + /* ARB 37. GL_ARB_draw_buffers */ + SET_DrawBuffersARB(exec, _mesa_DrawBuffersARB); + +#if FEATURE_ARB_shader_objects + SET_DeleteObjectARB(exec, _mesa_DeleteObjectARB); + SET_GetHandleARB(exec, _mesa_GetHandleARB); + SET_DetachObjectARB(exec, _mesa_DetachObjectARB); + SET_CreateShaderObjectARB(exec, _mesa_CreateShaderObjectARB); + SET_ShaderSourceARB(exec, _mesa_ShaderSourceARB); + SET_CompileShaderARB(exec, _mesa_CompileShaderARB); + SET_CreateProgramObjectARB(exec, _mesa_CreateProgramObjectARB); + SET_AttachObjectARB(exec, _mesa_AttachObjectARB); + SET_LinkProgramARB(exec, _mesa_LinkProgramARB); + SET_UseProgramObjectARB(exec, _mesa_UseProgramObjectARB); + SET_ValidateProgramARB(exec, _mesa_ValidateProgramARB); + SET_Uniform1fARB(exec, _mesa_Uniform1fARB); + SET_Uniform2fARB(exec, _mesa_Uniform2fARB); + SET_Uniform3fARB(exec, _mesa_Uniform3fARB); + SET_Uniform4fARB(exec, _mesa_Uniform4fARB); + SET_Uniform1iARB(exec, _mesa_Uniform1iARB); + SET_Uniform2iARB(exec, _mesa_Uniform2iARB); + SET_Uniform3iARB(exec, _mesa_Uniform3iARB); + SET_Uniform4iARB(exec, _mesa_Uniform4iARB); + SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB); + SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB); + SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB); + SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB); + SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB); + SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB); + SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB); + SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB); + SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB); + SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB); + SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB); + SET_GetObjectParameterfvARB(exec, _mesa_GetObjectParameterfvARB); + SET_GetObjectParameterivARB(exec, _mesa_GetObjectParameterivARB); + SET_GetInfoLogARB(exec, _mesa_GetInfoLogARB); + SET_GetAttachedObjectsARB(exec, _mesa_GetAttachedObjectsARB); + SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB); + SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB); + SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB); + SET_GetUniformivARB(exec, _mesa_GetUniformivARB); + SET_GetShaderSourceARB(exec, _mesa_GetShaderSourceARB); +#endif /* FEATURE_ARB_shader_objects */ + +#if FEATURE_ARB_vertex_shader + SET_BindAttribLocationARB(exec, _mesa_BindAttribLocationARB); + SET_GetActiveAttribARB(exec, _mesa_GetActiveAttribARB); + SET_GetAttribLocationARB(exec, _mesa_GetAttribLocationARB); +#endif /* FEATURE_ARB_vertex_shader */ + + /* GL_ATI_fragment_shader */ +#if FEATURE_ATI_fragment_shader + SET_GenFragmentShadersATI(exec, _mesa_GenFragmentShadersATI); + SET_BindFragmentShaderATI(exec, _mesa_BindFragmentShaderATI); + SET_DeleteFragmentShaderATI(exec, _mesa_DeleteFragmentShaderATI); + SET_BeginFragmentShaderATI(exec, _mesa_BeginFragmentShaderATI); + SET_EndFragmentShaderATI(exec, _mesa_EndFragmentShaderATI); + SET_PassTexCoordATI(exec, _mesa_PassTexCoordATI); + SET_SampleMapATI(exec, _mesa_SampleMapATI); + SET_ColorFragmentOp1ATI(exec, _mesa_ColorFragmentOp1ATI); + SET_ColorFragmentOp2ATI(exec, _mesa_ColorFragmentOp2ATI); + SET_ColorFragmentOp3ATI(exec, _mesa_ColorFragmentOp3ATI); + SET_AlphaFragmentOp1ATI(exec, _mesa_AlphaFragmentOp1ATI); + SET_AlphaFragmentOp2ATI(exec, _mesa_AlphaFragmentOp2ATI); + SET_AlphaFragmentOp3ATI(exec, _mesa_AlphaFragmentOp3ATI); + SET_SetFragmentShaderConstantATI(exec, _mesa_SetFragmentShaderConstantATI); +#endif + +#if FEATURE_EXT_framebuffer_object + SET_IsRenderbufferEXT(exec, _mesa_IsRenderbufferEXT); + SET_BindRenderbufferEXT(exec, _mesa_BindRenderbufferEXT); + SET_DeleteRenderbuffersEXT(exec, _mesa_DeleteRenderbuffersEXT); + SET_GenRenderbuffersEXT(exec, _mesa_GenRenderbuffersEXT); + SET_RenderbufferStorageEXT(exec, _mesa_RenderbufferStorageEXT); + SET_GetRenderbufferParameterivEXT(exec, _mesa_GetRenderbufferParameterivEXT); + SET_IsFramebufferEXT(exec, _mesa_IsFramebufferEXT); + SET_BindFramebufferEXT(exec, _mesa_BindFramebufferEXT); + SET_DeleteFramebuffersEXT(exec, _mesa_DeleteFramebuffersEXT); + SET_GenFramebuffersEXT(exec, _mesa_GenFramebuffersEXT); + SET_CheckFramebufferStatusEXT(exec, _mesa_CheckFramebufferStatusEXT); + SET_FramebufferTexture1DEXT(exec, _mesa_FramebufferTexture1DEXT); + SET_FramebufferTexture2DEXT(exec, _mesa_FramebufferTexture2DEXT); + SET_FramebufferTexture3DEXT(exec, _mesa_FramebufferTexture3DEXT); + SET_FramebufferRenderbufferEXT(exec, _mesa_FramebufferRenderbufferEXT); + SET_GetFramebufferAttachmentParameterivEXT(exec, _mesa_GetFramebufferAttachmentParameterivEXT); + SET_GenerateMipmapEXT(exec, _mesa_GenerateMipmapEXT); +#endif +} + + + +/**********************************************************************/ +/** \name State update logic */ +/*@{*/ + + +static void +update_separate_specular( GLcontext *ctx ) +{ + if (NEED_SECONDARY_COLOR(ctx)) + ctx->_TriangleCaps |= DD_SEPARATE_SPECULAR; + else + ctx->_TriangleCaps &= ~DD_SEPARATE_SPECULAR; +} + + +/** + * Update state dependent on vertex arrays. + */ +static void +update_arrays( GLcontext *ctx ) +{ + GLuint i, min; + + /* find min of _MaxElement values for all enabled arrays */ + + /* 0 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_POS].Enabled) { + min = ctx->Array.VertexAttrib[VERT_ATTRIB_POS]._MaxElement; + } + else if (ctx->Array.Vertex.Enabled) { + min = ctx->Array.Vertex._MaxElement; + } + else { + /* can't draw anything without vertex positions! */ + min = 0; + } + + /* 1 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_WEIGHT]._MaxElement); + } + /* no conventional vertex weight array */ + + /* 2 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_NORMAL]._MaxElement); + } + else if (ctx->Array.Normal.Enabled) { + min = MIN2(min, ctx->Array.Normal._MaxElement); + } + + /* 3 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_COLOR0]._MaxElement); + } + else if (ctx->Array.Color.Enabled) { + min = MIN2(min, ctx->Array.Color._MaxElement); + } + + /* 4 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_COLOR1]._MaxElement); + } + else if (ctx->Array.SecondaryColor.Enabled) { + min = MIN2(min, ctx->Array.SecondaryColor._MaxElement); + } + + /* 5 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_FOG].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_FOG]._MaxElement); + } + else if (ctx->Array.FogCoord.Enabled) { + min = MIN2(min, ctx->Array.FogCoord._MaxElement); + } + + /* 6 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_SIX].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_SIX]._MaxElement); + } + + /* 7 */ + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[VERT_ATTRIB_SEVEN].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[VERT_ATTRIB_SEVEN]._MaxElement); + } + + /* 8..15 */ + for (i = VERT_ATTRIB_TEX0; i < VERT_ATTRIB_MAX; i++) { + if (ctx->VertexProgram._Enabled + && ctx->Array.VertexAttrib[i].Enabled) { + min = MIN2(min, ctx->Array.VertexAttrib[i]._MaxElement); + } + else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits + && ctx->Array.TexCoord[i - VERT_ATTRIB_TEX0].Enabled) { + min = MIN2(min, ctx->Array.TexCoord[i - VERT_ATTRIB_TEX0]._MaxElement); + } + } + + if (ctx->Array.Index.Enabled) { + min = MIN2(min, ctx->Array.Index._MaxElement); + } + + if (ctx->Array.EdgeFlag.Enabled) { + min = MIN2(min, ctx->Array.EdgeFlag._MaxElement); + } + + /* _MaxElement is one past the last legal array element */ + ctx->Array._MaxElement = min; +} + + +/** + * Update derived vertex/fragment program state. + */ +static void +update_program(GLcontext *ctx) +{ + /* For now, just set the _Enabled (really enabled) flags. + * In the future we may have to check other state to be sure we really + * have a runable program or shader. + */ + ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled + && ctx->VertexProgram.Current->Instructions; + ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled + && ctx->FragmentProgram.Current->Instructions; + ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled + && ctx->ATIFragmentShader.Current->Instructions; + + ctx->FragmentProgram._Current = ctx->FragmentProgram.Current; + ctx->FragmentProgram._Active = ctx->FragmentProgram._Enabled; + + if (ctx->_MaintainTexEnvProgram && !ctx->FragmentProgram._Enabled) { + if (!ctx->_TexEnvProgram) + ctx->_TexEnvProgram = (struct fragment_program *) + ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); + + ctx->FragmentProgram._Current = ctx->_TexEnvProgram; + ctx->FragmentProgram._Active = GL_TRUE; + } +} + + +/** + * If __GLcontextRec::NewState is non-zero then this function \b must be called + * before rendering any primitive. Basically, function pointers and + * miscellaneous flags are updated to reflect the current state of the state + * machine. + * + * Calls dd_function_table::UpdateState to perform any internal state + * management necessary. + * + * \sa _mesa_update_modelview_project(), _mesa_update_texture(), + * _mesa_update_buffer_bounds(), _mesa_update_polygon(), + * _mesa_update_lighting() and _mesa_update_tnl_spaces(). + */ +void +_mesa_update_state( GLcontext *ctx ) +{ + GLuint new_state = ctx->NewState; + + if (MESA_VERBOSE & VERBOSE_STATE) + _mesa_print_state("_mesa_update_state", new_state); + + if (new_state & _NEW_PROGRAM) + update_program( ctx ); + + if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) + _mesa_update_modelview_project( ctx, new_state ); + + if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) + _mesa_update_texture( ctx, new_state ); + + if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) + _mesa_update_framebuffer(ctx); + + if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) + _mesa_update_draw_buffer_bounds( ctx ); + + if (new_state & _NEW_POINT) + _mesa_update_point( ctx ); + + if (new_state & _NEW_POLYGON) + _mesa_update_polygon( ctx ); + + if (new_state & _NEW_LIGHT) + _mesa_update_lighting( ctx ); + + if (new_state & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_pixel( ctx, new_state ); + + if (new_state & _DD_NEW_SEPARATE_SPECULAR) + update_separate_specular( ctx ); + + if (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) + update_arrays( ctx ); + + if (ctx->_MaintainTexEnvProgram) { + if (new_state & (_NEW_TEXTURE | _DD_NEW_SEPARATE_SPECULAR | _NEW_FOG)) + _mesa_UpdateTexEnvProgram(ctx); + } + + /* ctx->_NeedEyeCoords is now up to date. + * + * If the truth value of this variable has changed, update for the + * new lighting space and recompute the positions of lights and the + * normal transform. + * + * If the lighting space hasn't changed, may still need to recompute + * light positions & normal transforms for other reasons. + */ + if (new_state & _MESA_NEW_NEED_EYE_COORDS) + _mesa_update_tnl_spaces( ctx, new_state ); + + /* + * Give the driver a chance to act upon the new_state flags. + * The driver might plug in different span functions, for example. + * Also, this is where the driver can invalidate the state of any + * active modules (such as swrast_setup, swrast, tnl, etc). + * + * Set ctx->NewState to zero to avoid recursion if + * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) + */ + new_state = ctx->NewState; + ctx->NewState = 0; + ctx->Driver.UpdateState(ctx, new_state); + ctx->Array.NewState = 0; +} + +/*@}*/ diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h new file mode 100644 index 00000000000..58cfcc41462 --- /dev/null +++ b/src/mesa/main/state.h @@ -0,0 +1,43 @@ +/** + * \file state.h + * State management. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef STATE_H +#define STATE_H + +#include "mtypes.h" + +extern void +_mesa_init_exec_table(struct _glapi_table *exec); + +extern void +_mesa_update_state( GLcontext *ctx ); + + +#endif diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c new file mode 100644 index 00000000000..dfda4aa8fda --- /dev/null +++ b/src/mesa/main/stencil.c @@ -0,0 +1,466 @@ +/** + * \file stencil.c + * Stencil operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "context.h" +#include "depth.h" +#include "macros.h" +#include "stencil.h" +#include "mtypes.h" +#include "enable.h" + + +/** + * Set the clear value for the stencil buffer. + * + * \param s clear value. + * + * \sa glClearStencil(). + * + * Updates gl_stencil_attrib::Clear. On change + * flushes the vertices and notifies the driver via + * the dd_function_table::ClearStencil callback. + */ +void GLAPIENTRY +_mesa_ClearStencil( GLint s ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->Stencil.Clear == (GLstencil) s) + return; + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.Clear = (GLstencil) s; + + if (ctx->Driver.ClearStencil) { + (*ctx->Driver.ClearStencil)( ctx, s ); + } +} + + +/** + * Set the function and reference value for stencil testing. + * + * \param func test function. + * \param ref reference value. + * \param mask bitmask. + * + * \sa glStencilFunc(). + * + * Verifies the parameters and updates the respective values in + * __GLcontextRec::Stencil. On change flushes the vertices and notifies the + * driver via the dd_function_table::StencilFunc callback. + */ +void GLAPIENTRY +_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + const GLint face = ctx->Stencil.ActiveFace; + GLint maxref; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_LEQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glStencilFunc" ); + return; + } + + maxref = (1 << STENCIL_BITS) - 1; + ref = (GLstencil) CLAMP( ref, 0, maxref ); + + if (ctx->Stencil.Function[face] == func && + ctx->Stencil.ValueMask[face] == (GLstencil) mask && + ctx->Stencil.Ref[face] == ref) + return; + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.Function[face] = func; + ctx->Stencil.Ref[face] = ref; + ctx->Stencil.ValueMask[face] = (GLstencil) mask; + + if (ctx->Driver.StencilFunc) { + (*ctx->Driver.StencilFunc)( ctx, func, ref, mask ); + } +} + + +/** + * Set the stencil writing mask. + * + * \param mask bit-mask to enable/disable writing of individual bits in the + * stencil planes. + * + * \sa glStencilMask(). + * + * Updates gl_stencil_attrib::WriteMask. On change flushes the vertices and + * notifies the driver via the dd_function_table::StencilMask callback. + */ +void GLAPIENTRY +_mesa_StencilMask( GLuint mask ) +{ + GET_CURRENT_CONTEXT(ctx); + const GLint face = ctx->Stencil.ActiveFace; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (ctx->Stencil.WriteMask[face] == (GLstencil) mask) + return; + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.WriteMask[face] = (GLstencil) mask; + + if (ctx->Driver.StencilMask) { + (*ctx->Driver.StencilMask)( ctx, mask ); + } +} + + +/** + * Set the stencil test actions. + * + * \param fail action to take when stencil test fails. + * \param zfail action to take when stencil test passes, but the depth test fails. + * \param zpass action to take when stencil test passes and the depth test + * passes (or depth testing is not enabled). + * + * \sa glStencilOp(). + * + * Verifies the parameters and updates the respective fields in + * __GLcontextRec::Stencil. On change flushes the vertices and notifies the + * driver via the dd_function_table::StencilOp callback. + */ +void GLAPIENTRY +_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + GET_CURRENT_CONTEXT(ctx); + const GLint face = ctx->Stencil.ActiveFace; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (fail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + break; + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + if (ctx->Extensions.EXT_stencil_wrap) { + break; + } + /* FALL-THROUGH */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp"); + return; + } + switch (zfail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + break; + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + if (ctx->Extensions.EXT_stencil_wrap) { + break; + } + /* FALL-THROUGH */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp"); + return; + } + switch (zpass) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + break; + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + if (ctx->Extensions.EXT_stencil_wrap) { + break; + } + /* FALL-THROUGH */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp"); + return; + } + + if (ctx->Stencil.ZFailFunc[face] == zfail && + ctx->Stencil.ZPassFunc[face] == zpass && + ctx->Stencil.FailFunc[face] == fail) + return; + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.ZFailFunc[face] = zfail; + ctx->Stencil.ZPassFunc[face] = zpass; + ctx->Stencil.FailFunc[face] = fail; + + if (ctx->Driver.StencilOp) { + (*ctx->Driver.StencilOp)(ctx, fail, zfail, zpass); + } +} + + + +#if _HAVE_FULL_GL +/* GL_EXT_stencil_two_side */ +void GLAPIENTRY +_mesa_ActiveStencilFaceEXT(GLenum face) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (face == GL_FRONT || face == GL_BACK) { + FLUSH_VERTICES(ctx, _NEW_STENCIL); + ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 1; + } + + if (ctx->Driver.ActiveStencilFace) { + (*ctx->Driver.ActiveStencilFace)( ctx, (GLuint) ctx->Stencil.ActiveFace ); + } +} +#endif + + + +/** + * OpenGL 2.0 function. + * \todo Make StencilOp() call this function. And eventually remove the + * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate + * instead. + */ +void GLAPIENTRY +_mesa_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)"); + return; + } + + switch (fail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + break; + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + if (ctx->Extensions.EXT_stencil_wrap) { + break; + } + /* FALL-THROUGH */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(fail)"); + return; + } + switch (zfail) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + break; + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + if (ctx->Extensions.EXT_stencil_wrap) { + break; + } + /* FALL-THROUGH */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)"); + return; + } + switch (zpass) { + case GL_KEEP: + case GL_ZERO: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + break; + case GL_INCR_WRAP_EXT: + case GL_DECR_WRAP_EXT: + if (ctx->Extensions.EXT_stencil_wrap) { + break; + } + /* FALL-THROUGH */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + ctx->Stencil.FailFunc[0] = fail; + ctx->Stencil.ZFailFunc[0] = zfail; + ctx->Stencil.ZPassFunc[0] = zpass; + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + ctx->Stencil.FailFunc[1] = fail; + ctx->Stencil.ZFailFunc[1] = zfail; + ctx->Stencil.ZPassFunc[1] = zpass; + } + + if (ctx->Driver.StencilOpSeparate) { + ctx->Driver.StencilOpSeparate(ctx, face, fail, zfail, zpass); + } +} + + +/* OpenGL 2.0 */ +void GLAPIENTRY +_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + GET_CURRENT_CONTEXT(ctx); + GLint maxref; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); + return; + } + + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_LEQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)"); + return; + } + + maxref = (1 << STENCIL_BITS) - 1; + ref = (GLstencil) CLAMP(ref, 0, maxref); + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + ctx->Stencil.Function[0] = func; + ctx->Stencil.Ref[0] = ref; + ctx->Stencil.ValueMask[0] = (GLstencil) mask; + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + ctx->Stencil.Function[1] = func; + ctx->Stencil.Ref[1] = ref; + ctx->Stencil.ValueMask[1] = (GLstencil) mask; + } + + if (ctx->Driver.StencilFuncSeparate) { + ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask); + } +} + + +/* OpenGL 2.0 */ +void GLAPIENTRY +_mesa_StencilMaskSeparate(GLenum face, GLuint mask) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { + _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_STENCIL); + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { + ctx->Stencil.WriteMask[0] = (GLstencil) mask; + } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) { + ctx->Stencil.WriteMask[1] = (GLstencil) mask; + } + + if (ctx->Driver.StencilMaskSeparate) { + ctx->Driver.StencilMaskSeparate(ctx, face, mask); + } +} + + +/** + * Initialize the context stipple state. + * + * \param ctx GL context. + * + * Initializes __GLcontextRec::Stencil attribute group. + */ +void _mesa_init_stencil( GLcontext * ctx ) +{ + + /* Stencil group */ + ctx->Stencil.Enabled = GL_FALSE; + ctx->Stencil.TestTwoSide = GL_FALSE; + ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 1 = GL_BACK */ + ctx->Stencil.Function[0] = GL_ALWAYS; + ctx->Stencil.Function[1] = GL_ALWAYS; + ctx->Stencil.FailFunc[0] = GL_KEEP; + ctx->Stencil.FailFunc[1] = GL_KEEP; + ctx->Stencil.ZPassFunc[0] = GL_KEEP; + ctx->Stencil.ZPassFunc[1] = GL_KEEP; + ctx->Stencil.ZFailFunc[0] = GL_KEEP; + ctx->Stencil.ZFailFunc[1] = GL_KEEP; + ctx->Stencil.Ref[0] = 0; + ctx->Stencil.Ref[1] = 0; + ctx->Stencil.ValueMask[0] = STENCIL_MAX; + ctx->Stencil.ValueMask[1] = STENCIL_MAX; + ctx->Stencil.WriteMask[0] = STENCIL_MAX; + ctx->Stencil.WriteMask[1] = STENCIL_MAX; + ctx->Stencil.Clear = 0; +} diff --git a/src/mesa/main/stencil.h b/src/mesa/main/stencil.h new file mode 100644 index 00000000000..ec2927cfd20 --- /dev/null +++ b/src/mesa/main/stencil.h @@ -0,0 +1,73 @@ +/** + * \file stencil.h + * Stencil operations. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef STENCIL_H +#define STENCIL_H + + +#include "mtypes.h" + + +extern void GLAPIENTRY +_mesa_ClearStencil( GLint s ); + + +extern void GLAPIENTRY +_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask ); + + +extern void GLAPIENTRY +_mesa_StencilMask( GLuint mask ); + + +extern void GLAPIENTRY +_mesa_StencilOp( GLenum fail, GLenum zfail, GLenum zpass ); + + +extern void GLAPIENTRY +_mesa_ActiveStencilFaceEXT(GLenum face); + + +extern void GLAPIENTRY +_mesa_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + +extern void GLAPIENTRY +_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + + +extern void GLAPIENTRY +_mesa_StencilMaskSeparate(GLenum face, GLuint mask); + + +extern void +_mesa_init_stencil( GLcontext * ctx ); + +#endif diff --git a/src/mesa/main/texcompress.c b/src/mesa/main/texcompress.c new file mode 100644 index 00000000000..d18b1d0b418 --- /dev/null +++ b/src/mesa/main/texcompress.c @@ -0,0 +1,254 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texcompress.c + * Helper functions for texture compression. + */ + + +#include "glheader.h" +#include "imports.h" +#include "colormac.h" +#include "context.h" +#include "image.h" +#include "texcompress.h" +#include "texformat.h" +#include "texstore.h" + +/** + * Get the list of supported internal compression formats. + * + * \param ctx GL context. + * \param formats the resulting format list (may be NULL). + * + * \return number of formats. + */ +GLuint +_mesa_get_compressed_formats( GLcontext *ctx, GLint *formats ) +{ + GLuint n = 0; + if (ctx->Extensions.ARB_texture_compression) { + if (ctx->Extensions.TDFX_texture_compression_FXT1) { + if (formats) { + formats[n++] = GL_COMPRESSED_RGB_FXT1_3DFX; + formats[n++] = GL_COMPRESSED_RGBA_FXT1_3DFX; + } + else { + n += 2; + } + } + if (ctx->Extensions.EXT_texture_compression_s3tc) { + if (formats) { + formats[n++] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + /* Skip this one because it has a restriction (all transparent + * pixels become black). See the texture compressions spec for + * a detailed explanation. This is what NVIDIA does. + formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + */ + formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + formats[n++] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } + else { + n += 3; + } + } + if (ctx->Extensions.S3_s3tc) { + if (formats) { + formats[n++] = GL_RGB_S3TC; + formats[n++] = GL_RGB4_S3TC; + formats[n++] = GL_RGBA_S3TC; + formats[n++] = GL_RGBA4_S3TC; + } + else { + n += 4; + } + } + } + return n; +} + + + +/** + * Return number of bytes needed to store a texture of the given size + * using the specified compressed format. + * This is called via the ctx->Driver.CompressedTextureSize function, + * unless a device driver overrides it. + * + * \param width texture width in texels. + * \param height texture height in texels. + * \param depth texture depth in texels. + * \param format - one of the specific compressed texture formats + * + * \return size in bytes, or zero if bad format + */ +GLuint +_mesa_compressed_texture_size( GLcontext *ctx, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format ) +{ + GLuint size; + + ASSERT(depth == 1); + (void) depth; + + switch (format) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + /* round up width to next multiple of 8, height to next multiple of 4 */ + width = (width + 7) & ~7; + height = (height + 3) & ~3; + /* 16 bytes per 8x4 tile of RGB[A] texels */ + size = width * height / 2; + /* Textures smaller than 8x4 will effectively be made into 8x4 and + * take 16 bytes. + */ + if (size < 16) + size = 16; + return size; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + /* round up width, height to next multiple of 4 */ + width = (width + 3) & ~3; + height = (height + 3) & ~3; + /* 8 bytes per 4x4 tile of RGB[A] texels */ + size = width * height / 2; + /* Textures smaller than 4x4 will effectively be made into 4x4 and + * take 8 bytes. + */ + if (size < 8) + size = 8; + return size; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + /* round up width, height to next multiple of 4 */ + width = (width + 3) & ~3; + height = (height + 3) & ~3; + /* 16 bytes per 4x4 tile of RGBA texels */ + size = width * height; /* simple! */ + /* Textures smaller than 4x4 will effectively be made into 4x4 and + * take 16 bytes. + */ + if (size < 16) + size = 16; + return size; + default: + _mesa_problem(ctx, "bad texformat in compressed_texture_size"); + return 0; + } +} + + +/* + * Compute the bytes per row in a compressed texture image. + * We use this for computing the destination address for sub-texture updates. + * \param format one of the specific texture compression formats + * \param width image width in pixels + * \return stride, in bytes, between rows for compressed image + */ +GLint +_mesa_compressed_row_stride(GLenum format, GLsizei width) +{ + GLint stride; + + switch (format) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + stride = ((width + 7) / 8) * 16; /* 16 bytes per 8x4 tile */ + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + stride = ((width + 3) / 4) * 8; /* 8 bytes per 4x4 tile */ + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + stride = ((width + 3) / 4) * 16; /* 16 bytes per 4x4 tile */ + break; + default: + return 0; + } + + return stride; +} + + +/* + * Return the address of the pixel at (col, row, img) in a + * compressed texture image. + * \param col, row, img - image position (3D) + * \param format - compressed image format + * \param width - image width + * \param image - the image address + * \return address of pixel at (row, col) + */ +GLubyte * +_mesa_compressed_image_address(GLint col, GLint row, GLint img, + GLenum format, + GLsizei width, const GLubyte *image) +{ + GLubyte *addr; + + (void) img; + + /* We try to spot a "complete" subtexture "above" ROW, COL; + * this texture is given by appropriate rounding of WIDTH x ROW. + * Then we just add the amount left (usually on the left). + * + * Example for X*Y microtiles (Z bytes each) + * offset = Z * (((width + X - 1) / X) * (row / Y) + col / X); + */ + + switch (format) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + addr = (GLubyte *) image + 16 * (((width + 7) / 8) * (row / 4) + col / 8); + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + addr = (GLubyte *) image + 8 * (((width + 3) / 4) * (row / 4) + col / 4); + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + addr = (GLubyte *) image + 16 * (((width + 3) / 4) * (row / 4) + col / 4); + break; + default: + return NULL; + } + + return addr; +} diff --git a/src/mesa/main/texcompress.h b/src/mesa/main/texcompress.h new file mode 100644 index 00000000000..50074145469 --- /dev/null +++ b/src/mesa/main/texcompress.h @@ -0,0 +1,65 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef TEXCOMPRESS_H +#define TEXCOMPRESS_H + +#include "mtypes.h" + +#if _HAVE_FULL_GL +extern GLuint +_mesa_get_compressed_formats( GLcontext *ctx, GLint *formats ); + +extern GLuint +_mesa_compressed_texture_size( GLcontext *ctx, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format ); + +extern GLint +_mesa_compressed_row_stride(GLenum format, GLsizei width); + + +extern GLubyte * +_mesa_compressed_image_address(GLint col, GLint row, GLint img, + GLenum format, + GLsizei width, const GLubyte *image); + + +extern void +_mesa_init_texture_s3tc( GLcontext *ctx ); + +extern void +_mesa_init_texture_fxt1( GLcontext *ctx ); + + + +#else +#define _mesa_get_compressed_formats( c, f ) 0 +#define _mesa_compressed_texture_size( c, w, h, d, f ) 0 +#define _mesa_compressed_row_stride( f, w) 0 +#define _mesa_compressed_image_address(c, r, i, f, w, i2 ) 0 +#define _mesa_compress_teximage( c, w, h, sF, s, sRS, dF, d, drs ) ((void)0) +#endif + +#endif /* TEXCOMPRESS_H */ diff --git a/src/mesa/main/texcompress_fxt1.c b/src/mesa/main/texcompress_fxt1.c new file mode 100644 index 00000000000..d5e2c790f60 --- /dev/null +++ b/src/mesa/main/texcompress_fxt1.c @@ -0,0 +1,1663 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texcompress_fxt1.c + * GL_EXT_texture_compression_fxt1 support. + */ + + +#include "glheader.h" +#include "imports.h" +#include "colormac.h" +#include "context.h" +#include "convolve.h" +#include "image.h" +#include "texcompress.h" +#include "texformat.h" +#include "texstore.h" + + +static GLint +fxt1_encode (GLuint width, GLuint height, GLint comps, + const void *source, GLint srcRowStride, + void *dest, GLint destRowStride); + +void +fxt1_decode_1 (const void *texture, GLint stride, + GLint i, GLint j, GLubyte *rgba); + + +/** + * Called during context initialization. + */ +void +_mesa_init_texture_fxt1( GLcontext *ctx ) +{ + (void) ctx; +} + + +/** + * Called via TexFormat->StoreImage to store an RGB_FXT1 texture. + */ +static GLboolean +texstore_rgb_fxt1(STORE_PARAMS) +{ + const GLchan *pixels; + GLint srcRowStride; + GLubyte *dst; + const GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */ + const GLchan *tempImage = NULL; + + ASSERT(dstFormat == &_mesa_texformat_rgb_fxt1); + ASSERT(dstXoffset % 8 == 0); + ASSERT(dstYoffset % 4 == 0); + ASSERT(dstZoffset == 0); + (void) dstZoffset; (void) dstImageStride; + + if (srcFormat != GL_RGB || + srcType != CHAN_TYPE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGB/GLchan */ + tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + pixels = tempImage; + srcRowStride = 3 * srcWidth; + srcFormat = GL_RGB; + } + else { + pixels = (const GLchan *) srcAddr; + srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, + srcType) / sizeof(GLchan); + } + + dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, + GL_COMPRESSED_RGB_FXT1_3DFX, + texWidth, (GLubyte *) dstAddr); + + fxt1_encode(srcWidth, srcHeight, 3, pixels, srcRowStride, + dst, dstRowStride); + + if (tempImage) + _mesa_free((void*) tempImage); + + return GL_TRUE; +} + + +/** + * Called via TexFormat->StoreImage to store an RGBA_FXT1 texture. + */ +static GLboolean +texstore_rgba_fxt1(STORE_PARAMS) +{ + const GLchan *pixels; + GLint srcRowStride; + GLubyte *dst; + GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */ + const GLchan *tempImage = NULL; + + ASSERT(dstFormat == &_mesa_texformat_rgba_fxt1); + ASSERT(dstXoffset % 8 == 0); + ASSERT(dstYoffset % 4 == 0); + ASSERT(dstZoffset == 0); + (void) dstZoffset; (void) dstImageStride; + + if (srcFormat != GL_RGBA || + srcType != CHAN_TYPE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGBA/GLchan */ + tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + pixels = tempImage; + srcRowStride = 4 * srcWidth; + srcFormat = GL_RGBA; + } + else { + pixels = (const GLchan *) srcAddr; + srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, + srcType) / sizeof(GLchan); + } + + dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, + GL_COMPRESSED_RGBA_FXT1_3DFX, + texWidth, (GLubyte *) dstAddr); + + fxt1_encode(srcWidth, srcHeight, 4, pixels, srcRowStride, + dst, dstRowStride); + + if (tempImage) + _mesa_free((void*) tempImage); + + return GL_TRUE; +} + + +static void +fetch_texel_2d_rgba_fxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) k; + fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel); +} + + +static void +fetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* just sample as GLchan and convert to float here */ + GLchan rgba[4]; + (void) k; + fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba); + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); +} + + +static void +fetch_texel_2d_rgb_fxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) k; + fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel); + texel[ACOMP] = 255; +} + + +static void +fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* just sample as GLchan and convert to float here */ + GLchan rgba[4]; + (void) k; + fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba); + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = 1.0F; +} + + + +const struct gl_texture_format _mesa_texformat_rgb_fxt1 = { + MESA_FORMAT_RGB_FXT1, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /*approx*/ /* RedBits */ + 4, /*approx*/ /* GreenBits */ + 4, /*approx*/ /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + texstore_rgb_fxt1, /* StoreTexImageFunc */ + NULL, /*impossible*/ /* FetchTexel1D */ + fetch_texel_2d_rgb_fxt1, /* FetchTexel2D */ + NULL, /*impossible*/ /* FetchTexel3D */ + NULL, /*impossible*/ /* FetchTexel1Df */ + fetch_texel_2d_f_rgb_fxt1, /* FetchTexel2Df */ + NULL, /*impossible*/ /* FetchTexel3Df */ +}; + +const struct gl_texture_format _mesa_texformat_rgba_fxt1 = { + MESA_FORMAT_RGBA_FXT1, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /*approx*/ /* RedBits */ + 4, /*approx*/ /* GreenBits */ + 4, /*approx*/ /* BlueBits */ + 1, /*approx*/ /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + texstore_rgba_fxt1, /* StoreTexImageFunc */ + NULL, /*impossible*/ /* FetchTexel1D */ + fetch_texel_2d_rgba_fxt1, /* FetchTexel2D */ + NULL, /*impossible*/ /* FetchTexel3D */ + NULL, /*impossible*/ /* FetchTexel1Df */ + fetch_texel_2d_f_rgba_fxt1, /* FetchTexel2Df */ + NULL, /*impossible*/ /* FetchTexel3Df */ +}; + + +/***************************************************************************\ + * FXT1 encoder + * + * The encoder was built by reversing the decoder, + * and is vaguely based on Texus2 by 3dfx. Note that this code + * is merely a proof of concept, since it is highly UNoptimized; + * moreover, it is sub-optimal due to initial conditions passed + * to Lloyd's algorithm (the interpolation modes are even worse). +\***************************************************************************/ + + +#define MAX_COMP 4 /* ever needed maximum number of components in texel */ +#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */ +#define N_TEXELS 32 /* number of texels in a block (always 32) */ +#define LL_N_REP 50 /* number of iterations in lloyd's vq */ +#define LL_RMS_D 10 /* fault tolerance (maximum delta) */ +#define LL_RMS_E 255 /* fault tolerance (maximum error) */ +#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */ +#define ISTBLACK(v) (*((GLuint *)(v)) == 0) + + +/* + * Define a 64-bit unsigned integer type and macros + */ +#if defined(__GNUC__) && !defined(__cplusplus) + +#define FX64_NATIVE 1 + +typedef unsigned long long Fx64; + +#define FX64_MOV32(a, b) a = b +#define FX64_OR32(a, b) a |= b +#define FX64_SHL(a, c) a <<= c + +#else /* !__GNUC__ */ + +#define FX64_NATIVE 0 + +typedef struct { + GLuint lo, hi; +} Fx64; + +#define FX64_MOV32(a, b) a.lo = b +#define FX64_OR32(a, b) a.lo |= b + +#define FX64_SHL(a, c) \ + do { \ + if ((c) >= 32) { \ + a.hi = a.lo << ((c) - 32); \ + a.lo = 0; \ + } else { \ + a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \ + a.lo <<= (c); \ + } \ + } while (0) + +#endif /* !__GNUC__ */ + + +#define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */ +#define SAFECDOT 1 /* for paranoids */ + +#define MAKEIVEC(NV, NC, IV, B, V0, V1) \ + do { \ + /* compute interpolation vector */ \ + GLfloat d2 = 0.0F; \ + GLfloat rd2; \ + \ + for (i = 0; i < NC; i++) { \ + IV[i] = (V1[i] - V0[i]) * F(i); \ + d2 += IV[i] * IV[i]; \ + } \ + rd2 = (GLfloat)NV / d2; \ + B = 0; \ + for (i = 0; i < NC; i++) { \ + IV[i] *= F(i); \ + B -= IV[i] * V0[i]; \ + IV[i] *= rd2; \ + } \ + B = B * rd2 + 0.5f; \ + } while (0) + +#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\ + do { \ + GLfloat dot = 0.0F; \ + for (i = 0; i < NC; i++) { \ + dot += V[i] * IV[i]; \ + } \ + TEXEL = (GLint)(dot + B); \ + if (SAFECDOT) { \ + if (TEXEL < 0) { \ + TEXEL = 0; \ + } else if (TEXEL > NV) { \ + TEXEL = NV; \ + } \ + } \ + } while (0) + + +static GLint +fxt1_bestcol (GLfloat vec[][MAX_COMP], GLint nv, + GLubyte input[MAX_COMP], GLint nc) +{ + GLint i, j, best = -1; + GLfloat err = 1e9; /* big enough */ + + for (j = 0; j < nv; j++) { + GLfloat e = 0.0F; + for (i = 0; i < nc; i++) { + e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]); + } + if (e < err) { + err = e; + best = j; + } + } + + return best; +} + + +static GLint +fxt1_worst (GLfloat vec[MAX_COMP], + GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) +{ + GLint i, k, worst = -1; + GLfloat err = -1.0F; /* small enough */ + + for (k = 0; k < n; k++) { + GLfloat e = 0.0F; + for (i = 0; i < nc; i++) { + e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]); + } + if (e > err) { + err = e; + worst = k; + } + } + + return worst; +} + + +static GLint +fxt1_variance (GLdouble variance[MAX_COMP], + GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) +{ + GLint i, k, best = 0; + GLint sx, sx2; + GLdouble var, maxvar = -1; /* small enough */ + GLdouble teenth = 1.0 / n; + + for (i = 0; i < nc; i++) { + sx = sx2 = 0; + for (k = 0; k < n; k++) { + GLint t = input[k][i]; + sx += t; + sx2 += t * t; + } + var = sx2 * teenth - sx * sx * teenth * teenth; + if (maxvar < var) { + maxvar = var; + best = i; + } + if (variance) { + variance[i] = var; + } + } + + return best; +} + + +static GLint +fxt1_choose (GLfloat vec[][MAX_COMP], GLint nv, + GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) +{ +#if 0 + /* Choose colors from a grid. + */ + GLint i, j; + + for (j = 0; j < nv; j++) { + GLint m = j * (n - 1) / (nv - 1); + for (i = 0; i < nc; i++) { + vec[j][i] = input[m][i]; + } + } +#else + /* Our solution here is to find the darkest and brightest colors in + * the 8x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + GLint i, j, k; + GLint minSum = 2000; /* big enough */ + GLint maxSum = -1; /* small enough */ + GLint minCol = 0; /* phoudoin: silent compiler! */ + GLint maxCol = 0; /* phoudoin: silent compiler! */ + + struct { + GLint flag; + GLint key; + GLint freq; + GLint idx; + } hist[N_TEXELS]; + GLint lenh = 0; + + memset(hist, 0, sizeof(hist)); + + for (k = 0; k < n; k++) { + GLint l; + GLint key = 0; + GLint sum = 0; + for (i = 0; i < nc; i++) { + key <<= 8; + key |= input[k][i]; + sum += input[k][i]; + } + for (l = 0; l < n; l++) { + if (!hist[l].flag) { + /* alloc new slot */ + hist[l].flag = !0; + hist[l].key = key; + hist[l].freq = 1; + hist[l].idx = k; + lenh = l + 1; + break; + } else if (hist[l].key == key) { + hist[l].freq++; + break; + } + } + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + } + + if (lenh <= nv) { + for (j = 0; j < lenh; j++) { + for (i = 0; i < nc; i++) { + vec[j][i] = (GLfloat)input[hist[j].idx][i]; + } + } + for (; j < nv; j++) { + for (i = 0; i < nc; i++) { + vec[j][i] = vec[0][i]; + } + } + return 0; + } + + for (j = 0; j < nv; j++) { + for (i = 0; i < nc; i++) { + vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (GLfloat)(nv - 1); + } + } +#endif + + return !0; +} + + +static GLint +fxt1_lloyd (GLfloat vec[][MAX_COMP], GLint nv, + GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) +{ + /* Use the generalized lloyd's algorithm for VQ: + * find 4 color vectors. + * + * for each sample color + * sort to nearest vector. + * + * replace each vector with the centroid of it's matching colors. + * + * repeat until RMS doesn't improve. + * + * if a color vector has no samples, or becomes the same as another + * vector, replace it with the color which is farthest from a sample. + * + * vec[][MAX_COMP] initial vectors and resulting colors + * nv number of resulting colors required + * input[N_TEXELS][MAX_COMP] input texels + * nc number of components in input / vec + * n number of input samples + */ + + GLint sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */ + GLint cnt[MAX_VECT]; /* how many times a certain vector was chosen */ + GLfloat error, lasterror = 1e9; + + GLint i, j, k, rep; + + /* the quantizer */ + for (rep = 0; rep < LL_N_REP; rep++) { + /* reset sums & counters */ + for (j = 0; j < nv; j++) { + for (i = 0; i < nc; i++) { + sum[j][i] = 0; + } + cnt[j] = 0; + } + error = 0; + + /* scan whole block */ + for (k = 0; k < n; k++) { +#if 1 + GLint best = -1; + GLfloat err = 1e9; /* big enough */ + /* determine best vector */ + for (j = 0; j < nv; j++) { + GLfloat e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) + + (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) + + (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]); + if (nc == 4) { + e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]); + } + if (e < err) { + err = e; + best = j; + } + } +#else + GLint best = fxt1_bestcol(vec, nv, input[k], nc, &err); +#endif + /* add in closest color */ + for (i = 0; i < nc; i++) { + sum[best][i] += input[k][i]; + } + /* mark this vector as used */ + cnt[best]++; + /* accumulate error */ + error += err; + } + + /* check RMS */ + if ((error < LL_RMS_E) || + ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) { + return !0; /* good match */ + } + lasterror = error; + + /* move each vector to the barycenter of its closest colors */ + for (j = 0; j < nv; j++) { + if (cnt[j]) { + GLfloat div = 1.0F / cnt[j]; + for (i = 0; i < nc; i++) { + vec[j][i] = div * sum[j][i]; + } + } else { + /* this vec has no samples or is identical with a previous vec */ + GLint worst = fxt1_worst(vec[j], input, nc, n); + for (i = 0; i < nc; i++) { + vec[j][i] = input[worst][i]; + } + } + } + } + + return 0; /* could not converge fast enough */ +} + + +static void +fxt1_quantize_CHROMA (GLuint *cc, + GLubyte input[N_TEXELS][MAX_COMP]) +{ + const GLint n_vect = 4; /* 4 base vectors to find */ + const GLint n_comp = 3; /* 3 components: R, G, B */ + GLfloat vec[MAX_VECT][MAX_COMP]; + GLint i, j, k; + Fx64 hi; /* high quadword */ + GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ + + if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) { + fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS); + } + + FX64_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */ + for (j = n_vect - 1; j >= 0; j--) { + for (i = 0; i < n_comp; i++) { + /* add in colors */ + FX64_SHL(hi, 5); + FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F)); + } + } + ((Fx64 *)cc)[1] = hi; + + lohi = lolo = 0; + /* right microtile */ + for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) { + lohi <<= 2; + lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp); + } + /* left microtile */ + for (; k >= 0; k--) { + lolo <<= 2; + lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp); + } + cc[1] = lohi; + cc[0] = lolo; +} + + +static void +fxt1_quantize_ALPHA0 (GLuint *cc, + GLubyte input[N_TEXELS][MAX_COMP], + GLubyte reord[N_TEXELS][MAX_COMP], GLint n) +{ + const GLint n_vect = 3; /* 3 base vectors to find */ + const GLint n_comp = 4; /* 4 components: R, G, B, A */ + GLfloat vec[MAX_VECT][MAX_COMP]; + GLint i, j, k; + Fx64 hi; /* high quadword */ + GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ + + /* the last vector indicates zero */ + for (i = 0; i < n_comp; i++) { + vec[n_vect][i] = 0; + } + + /* the first n texels in reord are guaranteed to be non-zero */ + if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) { + fxt1_lloyd(vec, n_vect, reord, n_comp, n); + } + + FX64_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */ + for (j = n_vect - 1; j >= 0; j--) { + /* add in alphas */ + FX64_SHL(hi, 5); + FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F)); + } + for (j = n_vect - 1; j >= 0; j--) { + for (i = 0; i < n_comp - 1; i++) { + /* add in colors */ + FX64_SHL(hi, 5); + FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F)); + } + } + ((Fx64 *)cc)[1] = hi; + + lohi = lolo = 0; + /* right microtile */ + for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) { + lohi <<= 2; + lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp); + } + /* left microtile */ + for (; k >= 0; k--) { + lolo <<= 2; + lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp); + } + cc[1] = lohi; + cc[0] = lolo; +} + + +static void +fxt1_quantize_ALPHA1 (GLuint *cc, + GLubyte input[N_TEXELS][MAX_COMP]) +{ + const GLint n_vect = 3; /* highest vector number in each microtile */ + const GLint n_comp = 4; /* 4 components: R, G, B, A */ + GLfloat vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */ + GLfloat b, iv[MAX_COMP]; /* interpolation vector */ + GLint i, j, k; + Fx64 hi; /* high quadword */ + GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ + + GLint minSum; + GLint maxSum; + GLint minColL = 0, maxColL = 0; + GLint minColR = 0, maxColR = 0; + GLint sumL = 0, sumR = 0; + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + if (minSum > sum) { + minSum = sum; + minColL = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColL = k; + } + sumL += sum; + } + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + if (minSum > sum) { + minSum = sum; + minColR = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColR = k; + } + sumR += sum; + } + + /* choose the common vector (yuck!) */ + { + GLint j1, j2; + GLint v1 = 0, v2 = 0; + GLfloat err = 1e9; /* big enough */ + GLfloat tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ + for (i = 0; i < n_comp; i++) { + tv[0][i] = input[minColL][i]; + tv[1][i] = input[maxColL][i]; + tv[2][i] = input[minColR][i]; + tv[3][i] = input[maxColR][i]; + } + for (j1 = 0; j1 < 2; j1++) { + for (j2 = 2; j2 < 4; j2++) { + GLfloat e = 0.0F; + for (i = 0; i < n_comp; i++) { + e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]); + } + if (e < err) { + err = e; + v1 = j1; + v2 = j2; + } + } + } + for (i = 0; i < n_comp; i++) { + vec[0][i] = tv[1 - v1][i]; + vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR); + vec[2][i] = tv[5 - v2][i]; + } + } + + /* left microtile */ + cc[0] = 0; + if (minColL != maxColL) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); + + /* add in texels */ + lolo = 0; + for (k = N_TEXELS / 2 - 1; k >= 0; k--) { + GLint texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lolo <<= 2; + lolo |= texel; + } + + cc[0] = lolo; + } + + /* right microtile */ + cc[1] = 0; + if (minColR != maxColR) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]); + + /* add in texels */ + lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + GLint texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lohi <<= 2; + lohi |= texel; + } + + cc[1] = lohi; + } + + FX64_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */ + for (j = n_vect - 1; j >= 0; j--) { + /* add in alphas */ + FX64_SHL(hi, 5); + FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F)); + } + for (j = n_vect - 1; j >= 0; j--) { + for (i = 0; i < n_comp - 1; i++) { + /* add in colors */ + FX64_SHL(hi, 5); + FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F)); + } + } + ((Fx64 *)cc)[1] = hi; +} + + +static void +fxt1_quantize_HI (GLuint *cc, + GLubyte input[N_TEXELS][MAX_COMP], + GLubyte reord[N_TEXELS][MAX_COMP], GLint n) +{ + const GLint n_vect = 6; /* highest vector number */ + const GLint n_comp = 3; /* 3 components: R, G, B */ + GLfloat b = 0.0F; /* phoudoin: silent compiler! */ + GLfloat iv[MAX_COMP]; /* interpolation vector */ + GLint i, k; + GLuint hihi; /* high quadword: hi dword */ + + GLint minSum = 2000; /* big enough */ + GLint maxSum = -1; /* small enough */ + GLint minCol = 0; /* phoudoin: silent compiler! */ + GLint maxCol = 0; /* phoudoin: silent compiler! */ + + /* Our solution here is to find the darkest and brightest colors in + * the 8x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + for (k = 0; k < n; k++) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += reord[k][i]; + } + if (minSum > sum) { + minSum = sum; + minCol = k; + } + if (maxSum < sum) { + maxSum = sum; + maxCol = k; + } + } + + hihi = 0; /* cc-hi = "00" */ + for (i = 0; i < n_comp; i++) { + /* add in colors */ + hihi <<= 5; + hihi |= reord[maxCol][i] >> 3; + } + for (i = 0; i < n_comp; i++) { + /* add in colors */ + hihi <<= 5; + hihi |= reord[minCol][i] >> 3; + } + cc[3] = hihi; + cc[0] = cc[1] = cc[2] = 0; + + /* compute interpolation vector */ + if (minCol != maxCol) { + MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]); + } + + /* add in texels */ + for (k = N_TEXELS - 1; k >= 0; k--) { + GLint t = k * 3; + GLuint *kk = (GLuint *)((char *)cc + t / 8); + GLint texel = n_vect + 1; /* transparent black */ + + if (!ISTBLACK(input[k])) { + if (minCol != maxCol) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + kk[0] |= texel << (t & 7); + } + } else { + /* add in texel */ + kk[0] |= texel << (t & 7); + } + } +} + + +static void +fxt1_quantize_MIXED1 (GLuint *cc, + GLubyte input[N_TEXELS][MAX_COMP]) +{ + const GLint n_vect = 2; /* highest vector number in each microtile */ + const GLint n_comp = 3; /* 3 components: R, G, B */ + GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ + GLfloat b, iv[MAX_COMP]; /* interpolation vector */ + GLint i, j, k; + Fx64 hi; /* high quadword */ + GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ + + GLint minSum; + GLint maxSum; + GLint minColL = 0, maxColL = -1; + GLint minColR = 0, maxColR = -1; + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + if (!ISTBLACK(input[k])) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + if (minSum > sum) { + minSum = sum; + minColL = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColL = k; + } + } + } + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + if (!ISTBLACK(input[k])) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + if (minSum > sum) { + minSum = sum; + minColR = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColR = k; + } + } + } + + /* left microtile */ + if (maxColL == -1) { + /* all transparent black */ + cc[0] = ~0u; + for (i = 0; i < n_comp; i++) { + vec[0][i] = 0; + vec[1][i] = 0; + } + } else { + cc[0] = 0; + for (i = 0; i < n_comp; i++) { + vec[0][i] = input[minColL][i]; + vec[1][i] = input[maxColL][i]; + } + if (minColL != maxColL) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); + + /* add in texels */ + lolo = 0; + for (k = N_TEXELS / 2 - 1; k >= 0; k--) { + GLint texel = n_vect + 1; /* transparent black */ + if (!ISTBLACK(input[k])) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + } + /* add in texel */ + lolo <<= 2; + lolo |= texel; + } + cc[0] = lolo; + } + } + + /* right microtile */ + if (maxColR == -1) { + /* all transparent black */ + cc[1] = ~0u; + for (i = 0; i < n_comp; i++) { + vec[2][i] = 0; + vec[3][i] = 0; + } + } else { + cc[1] = 0; + for (i = 0; i < n_comp; i++) { + vec[2][i] = input[minColR][i]; + vec[3][i] = input[maxColR][i]; + } + if (minColR != maxColR) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]); + + /* add in texels */ + lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + GLint texel = n_vect + 1; /* transparent black */ + if (!ISTBLACK(input[k])) { + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + } + /* add in texel */ + lohi <<= 2; + lohi |= texel; + } + cc[1] = lohi; + } + } + + FX64_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */ + for (j = 2 * 2 - 1; j >= 0; j--) { + for (i = 0; i < n_comp; i++) { + /* add in colors */ + FX64_SHL(hi, 5); + FX64_OR32(hi, vec[j][i] >> 3); + } + } + ((Fx64 *)cc)[1] = hi; +} + + +static void +fxt1_quantize_MIXED0 (GLuint *cc, + GLubyte input[N_TEXELS][MAX_COMP]) +{ + const GLint n_vect = 3; /* highest vector number in each microtile */ + const GLint n_comp = 3; /* 3 components: R, G, B */ + GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ + GLfloat b, iv[MAX_COMP]; /* interpolation vector */ + GLint i, j, k; + Fx64 hi; /* high quadword */ + GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ + + GLint minColL = 0, maxColL = 0; + GLint minColR = 0, maxColR = 0; +#if 0 + GLint minSum; + GLint maxSum; + + /* Our solution here is to find the darkest and brightest colors in + * the 4x4 tile and use those as the two representative colors. + * There are probably better algorithms to use (histogram-based). + */ + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + if (minSum > sum) { + minSum = sum; + minColL = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColL = k; + } + } + minSum = 2000; /* big enough */ + maxSum = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + GLint sum = 0; + for (i = 0; i < n_comp; i++) { + sum += input[k][i]; + } + if (minSum > sum) { + minSum = sum; + minColR = k; + } + if (maxSum < sum) { + maxSum = sum; + maxColR = k; + } + } +#else + GLint minVal; + GLint maxVal; + GLint maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2); + GLint maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2); + + /* Scan the channel with max variance for lo & hi + * and use those as the two representative colors. + */ + minVal = 2000; /* big enough */ + maxVal = -1; /* small enough */ + for (k = 0; k < N_TEXELS / 2; k++) { + GLint t = input[k][maxVarL]; + if (minVal > t) { + minVal = t; + minColL = k; + } + if (maxVal < t) { + maxVal = t; + maxColL = k; + } + } + minVal = 2000; /* big enough */ + maxVal = -1; /* small enough */ + for (; k < N_TEXELS; k++) { + GLint t = input[k][maxVarR]; + if (minVal > t) { + minVal = t; + minColR = k; + } + if (maxVal < t) { + maxVal = t; + maxColR = k; + } + } +#endif + + /* left microtile */ + cc[0] = 0; + for (i = 0; i < n_comp; i++) { + vec[0][i] = input[minColL][i]; + vec[1][i] = input[maxColL][i]; + } + if (minColL != maxColL) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); + + /* add in texels */ + lolo = 0; + for (k = N_TEXELS / 2 - 1; k >= 0; k--) { + GLint texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lolo <<= 2; + lolo |= texel; + } + + /* funky encoding for LSB of green */ + if ((GLint)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) { + for (i = 0; i < n_comp; i++) { + vec[1][i] = input[minColL][i]; + vec[0][i] = input[maxColL][i]; + } + lolo = ~lolo; + } + + cc[0] = lolo; + } + + /* right microtile */ + cc[1] = 0; + for (i = 0; i < n_comp; i++) { + vec[2][i] = input[minColR][i]; + vec[3][i] = input[maxColR][i]; + } + if (minColR != maxColR) { + /* compute interpolation vector */ + MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]); + + /* add in texels */ + lohi = 0; + for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { + GLint texel; + /* interpolate color */ + CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); + /* add in texel */ + lohi <<= 2; + lohi |= texel; + } + + /* funky encoding for LSB of green */ + if ((GLint)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) { + for (i = 0; i < n_comp; i++) { + vec[3][i] = input[minColR][i]; + vec[2][i] = input[maxColR][i]; + } + lohi = ~lohi; + } + + cc[1] = lohi; + } + + FX64_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */ + for (j = 2 * 2 - 1; j >= 0; j--) { + for (i = 0; i < n_comp; i++) { + /* add in colors */ + FX64_SHL(hi, 5); + FX64_OR32(hi, vec[j][i] >> 3); + } + } + ((Fx64 *)cc)[1] = hi; +} + + +static void +fxt1_quantize (GLuint *cc, const GLubyte *lines[], GLint comps) +{ + GLint trualpha; + GLubyte reord[N_TEXELS][MAX_COMP]; + + GLubyte input[N_TEXELS][MAX_COMP]; + GLint i, k, l; + + if (comps == 3) { + /* make the whole block opaque */ + memset(input, -1, sizeof(input)); + } + + /* 8 texels each line */ + for (l = 0; l < 4; l++) { + for (k = 0; k < 4; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4][i] = *lines[l]++; + } + } + for (; k < 8; k++) { + for (i = 0; i < comps; i++) { + input[k + l * 4 + 12][i] = *lines[l]++; + } + } + } + + /* block layout: + * 00, 01, 02, 03, 08, 09, 0a, 0b + * 10, 11, 12, 13, 18, 19, 1a, 1b + * 04, 05, 06, 07, 0c, 0d, 0e, 0f + * 14, 15, 16, 17, 1c, 1d, 1e, 1f + */ + + /* [dBorca] + * stupidity flows forth from this + */ + l = N_TEXELS; + trualpha = 0; + if (comps == 4) { + /* skip all transparent black texels */ + l = 0; + for (k = 0; k < N_TEXELS; k++) { + /* test all components against 0 */ + if (!ISTBLACK(input[k])) { + /* texel is not transparent black */ + COPY_4UBV(reord[l], input[k]); + if (reord[l][ACOMP] < (255 - ALPHA_TS)) { + /* non-opaque texel */ + trualpha = !0; + } + l++; + } + } + } + +#if 0 + if (trualpha) { + fxt1_quantize_ALPHA0(cc, input, reord, l); + } else if (l == 0) { + cc[0] = cc[1] = cc[2] = -1; + cc[3] = 0; + } else if (l < N_TEXELS) { + fxt1_quantize_HI(cc, input, reord, l); + } else { + fxt1_quantize_CHROMA(cc, input); + } + (void)fxt1_quantize_ALPHA1; + (void)fxt1_quantize_MIXED1; + (void)fxt1_quantize_MIXED0; +#else + if (trualpha) { + fxt1_quantize_ALPHA1(cc, input); + } else if (l == 0) { + cc[0] = cc[1] = cc[2] = ~0u; + cc[3] = 0; + } else if (l < N_TEXELS) { + fxt1_quantize_MIXED1(cc, input); + } else { + fxt1_quantize_MIXED0(cc, input); + } + (void)fxt1_quantize_ALPHA0; + (void)fxt1_quantize_HI; + (void)fxt1_quantize_CHROMA; +#endif +} + + +static GLint +fxt1_encode (GLuint width, GLuint height, GLint comps, + const void *source, GLint srcRowStride, + void *dest, GLint destRowStride) +{ + GLuint x, y; + const GLubyte *data; + GLuint *encoded = (GLuint *)dest; + GLubyte *newSource = NULL; + + /* Replicate image if width is not M8 or height is not M4 */ + if ((width & 7) | (height & 3)) { + GLint newWidth = (width + 7) & ~7; + GLint newHeight = (height + 3) & ~3; + newSource = (GLubyte *) + _mesa_malloc(comps * newWidth * newHeight * sizeof(GLubyte *)); + _mesa_upscale_teximage2d(width, height, newWidth, newHeight, + comps, (const GLchan *) source, + srcRowStride, newSource); + source = newSource; + width = newWidth; + height = newHeight; + srcRowStride = comps * newWidth; + } + + data = (const GLubyte *) source; + destRowStride = (destRowStride - width * 2) / 4; + for (y = 0; y < height; y += 4) { + GLuint offs = 0 + (y + 0) * srcRowStride; + for (x = 0; x < width; x += 8) { + const GLubyte *lines[4]; + lines[0] = &data[offs]; + lines[1] = lines[0] + srcRowStride; + lines[2] = lines[1] + srcRowStride; + lines[3] = lines[2] + srcRowStride; + offs += 8 * comps; + fxt1_quantize(encoded, lines, comps); + /* 128 bits per 8x4 block */ + encoded += 4; + } + encoded += destRowStride; + } + + if (newSource != NULL) { + _mesa_free(newSource); + } + + return 0; +} + + +/***************************************************************************\ + * FXT1 decoder + * + * The decoder is based on GL_3DFX_texture_compression_FXT1 + * specification and serves as a concept for the encoder. +\***************************************************************************/ + + +/* lookup table for scaling 5 bit colors up to 8 bits */ +static const GLubyte _rgb_scale_5[] = { + 0, 8, 16, 25, 33, 41, 49, 58, + 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, + 197, 206, 214, 222, 230, 239, 247, 255 +}; + +/* lookup table for scaling 6 bit colors up to 8 bits */ +static const GLubyte _rgb_scale_6[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 45, 49, 53, 57, 61, + 65, 69, 73, 77, 81, 85, 89, 93, + 97, 101, 105, 109, 113, 117, 121, 125, + 130, 134, 138, 142, 146, 150, 154, 158, + 162, 166, 170, 174, 178, 182, 186, 190, + 194, 198, 202, 206, 210, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 255 +}; + + +#define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31)) +#define UP5(c) _rgb_scale_5[(c) & 31] +#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)] +#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n) +#define ZERO_4UBV(v) *((GLuint *)(v)) = 0 + + +static void +fxt1_decode_1HI (const GLubyte *code, GLint t, GLubyte *rgba) +{ + const GLuint *cc; + + t *= 3; + cc = (const GLuint *)(code + t / 8); + t = (cc[0] >> (t & 7)) & 7; + + if (t == 7) { + ZERO_4UBV(rgba); + } else { + cc = (const GLuint *)(code + 12); + if (t == 0) { + rgba[BCOMP] = UP5(CC_SEL(cc, 0)); + rgba[GCOMP] = UP5(CC_SEL(cc, 5)); + rgba[RCOMP] = UP5(CC_SEL(cc, 10)); + } else if (t == 6) { + rgba[BCOMP] = UP5(CC_SEL(cc, 15)); + rgba[GCOMP] = UP5(CC_SEL(cc, 20)); + rgba[RCOMP] = UP5(CC_SEL(cc, 25)); + } else { + rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15))); + rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20))); + rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25))); + } + rgba[ACOMP] = 255; + } +} + + +static void +fxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLubyte *rgba) +{ + const GLuint *cc; + GLuint kk; + + cc = (const GLuint *)code; + if (t & 16) { + cc++; + t &= 15; + } + t = (cc[0] >> (t * 2)) & 3; + + t *= 15; + cc = (const GLuint *)(code + 8 + t / 8); + kk = cc[0] >> (t & 7); + rgba[BCOMP] = UP5(kk); + rgba[GCOMP] = UP5(kk >> 5); + rgba[RCOMP] = UP5(kk >> 10); + rgba[ACOMP] = 255; +} + + +static void +fxt1_decode_1MIXED (const GLubyte *code, GLint t, GLubyte *rgba) +{ + const GLuint *cc; + GLuint col[2][3]; + GLint glsb, selb; + + cc = (const GLuint *)code; + if (t & 16) { + t &= 15; + t = (cc[1] >> (t * 2)) & 3; + /* col 2 */ + col[0][BCOMP] = (*(const GLuint *)(code + 11)) >> 6; + col[0][GCOMP] = CC_SEL(cc, 99); + col[0][RCOMP] = CC_SEL(cc, 104); + /* col 3 */ + col[1][BCOMP] = CC_SEL(cc, 109); + col[1][GCOMP] = CC_SEL(cc, 114); + col[1][RCOMP] = CC_SEL(cc, 119); + glsb = CC_SEL(cc, 126); + selb = CC_SEL(cc, 33); + } else { + t = (cc[0] >> (t * 2)) & 3; + /* col 0 */ + col[0][BCOMP] = CC_SEL(cc, 64); + col[0][GCOMP] = CC_SEL(cc, 69); + col[0][RCOMP] = CC_SEL(cc, 74); + /* col 1 */ + col[1][BCOMP] = CC_SEL(cc, 79); + col[1][GCOMP] = CC_SEL(cc, 84); + col[1][RCOMP] = CC_SEL(cc, 89); + glsb = CC_SEL(cc, 125); + selb = CC_SEL(cc, 1); + } + + if (CC_SEL(cc, 124) & 1) { + /* alpha[0] == 1 */ + + if (t == 3) { + ZERO_4UBV(rgba); + } else { + if (t == 0) { + rgba[BCOMP] = UP5(col[0][BCOMP]); + rgba[GCOMP] = UP5(col[0][GCOMP]); + rgba[RCOMP] = UP5(col[0][RCOMP]); + } else if (t == 2) { + rgba[BCOMP] = UP5(col[1][BCOMP]); + rgba[GCOMP] = UP6(col[1][GCOMP], glsb); + rgba[RCOMP] = UP5(col[1][RCOMP]); + } else { + rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2; + rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2; + rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2; + } + rgba[ACOMP] = 255; + } + } else { + /* alpha[0] == 0 */ + + if (t == 0) { + rgba[BCOMP] = UP5(col[0][BCOMP]); + rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb); + rgba[RCOMP] = UP5(col[0][RCOMP]); + } else if (t == 3) { + rgba[BCOMP] = UP5(col[1][BCOMP]); + rgba[GCOMP] = UP6(col[1][GCOMP], glsb); + rgba[RCOMP] = UP5(col[1][RCOMP]); + } else { + rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP])); + rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb), + UP6(col[1][GCOMP], glsb)); + rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP])); + } + rgba[ACOMP] = 255; + } +} + + +static void +fxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLubyte *rgba) +{ + const GLuint *cc; + + cc = (const GLuint *)code; + if (CC_SEL(cc, 124) & 1) { + /* lerp == 1 */ + GLuint col0[4]; + + if (t & 16) { + t &= 15; + t = (cc[1] >> (t * 2)) & 3; + /* col 2 */ + col0[BCOMP] = (*(const GLuint *)(code + 11)) >> 6; + col0[GCOMP] = CC_SEL(cc, 99); + col0[RCOMP] = CC_SEL(cc, 104); + col0[ACOMP] = CC_SEL(cc, 119); + } else { + t = (cc[0] >> (t * 2)) & 3; + /* col 0 */ + col0[BCOMP] = CC_SEL(cc, 64); + col0[GCOMP] = CC_SEL(cc, 69); + col0[RCOMP] = CC_SEL(cc, 74); + col0[ACOMP] = CC_SEL(cc, 109); + } + + if (t == 0) { + rgba[BCOMP] = UP5(col0[BCOMP]); + rgba[GCOMP] = UP5(col0[GCOMP]); + rgba[RCOMP] = UP5(col0[RCOMP]); + rgba[ACOMP] = UP5(col0[ACOMP]); + } else if (t == 3) { + rgba[BCOMP] = UP5(CC_SEL(cc, 79)); + rgba[GCOMP] = UP5(CC_SEL(cc, 84)); + rgba[RCOMP] = UP5(CC_SEL(cc, 89)); + rgba[ACOMP] = UP5(CC_SEL(cc, 114)); + } else { + rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79))); + rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84))); + rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89))); + rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114))); + } + } else { + /* lerp == 0 */ + + if (t & 16) { + cc++; + t &= 15; + } + t = (cc[0] >> (t * 2)) & 3; + + if (t == 3) { + ZERO_4UBV(rgba); + } else { + GLuint kk; + cc = (const GLuint *)code; + rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13)); + t *= 15; + cc = (const GLuint *)(code + 8 + t / 8); + kk = cc[0] >> (t & 7); + rgba[BCOMP] = UP5(kk); + rgba[GCOMP] = UP5(kk >> 5); + rgba[RCOMP] = UP5(kk >> 10); + } + } +} + + +void +fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */ + GLint i, GLint j, GLubyte *rgba) +{ + static void (*decode_1[]) (const GLubyte *, GLint, GLubyte *) = { + fxt1_decode_1HI, /* cc-high = "00?" */ + fxt1_decode_1HI, /* cc-high = "00?" */ + fxt1_decode_1CHROMA, /* cc-chroma = "010" */ + fxt1_decode_1ALPHA, /* alpha = "011" */ + fxt1_decode_1MIXED, /* mixed = "1??" */ + fxt1_decode_1MIXED, /* mixed = "1??" */ + fxt1_decode_1MIXED, /* mixed = "1??" */ + fxt1_decode_1MIXED /* mixed = "1??" */ + }; + + const GLubyte *code = (const GLubyte *)texture + + ((j / 4) * (stride / 8) + (i / 8)) * 16; + GLint mode = CC_SEL(code, 125); + GLint t = i & 7; + + if (t & 4) { + t += 12; + } + t += (j & 3) * 4; + + decode_1[mode](code, t, rgba); +} diff --git a/src/mesa/main/texcompress_s3tc.c b/src/mesa/main/texcompress_s3tc.c new file mode 100644 index 00000000000..44ab9e2acad --- /dev/null +++ b/src/mesa/main/texcompress_s3tc.c @@ -0,0 +1,555 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texcompress_s3tc.c + * GL_EXT_texture_compression_s3tc support. + */ + +#ifndef USE_EXTERNAL_DXTN_LIB +#define USE_EXTERNAL_DXTN_LIB 0 +#endif + +#include "glheader.h" +#include "imports.h" +#include "colormac.h" +#include "context.h" +#include "convolve.h" +#include "image.h" +#include "texcompress.h" +#include "texformat.h" +#include "texstore.h" + +#if USE_EXTERNAL_DXTN_LIB +#ifdef __MINGW32__ +/* no dlopen */ +#define DXTN_EXT "dxtn.dll" +#define DXTN_PREFIX "" +#define dlopen(name, mode) LoadLibrary(name) +#define dlsym(hndl, proc) GetProcAddress(hndl, proc) +#define dlclose(hndl) FreeLibrary(hndl) +#elif defined(__DJGPP__) +/* has dlopen, but doesn't like the names */ +#include <dlfcn.h> +#define DXTN_EXT "dxtn.dxe" +#define DXTN_PREFIX "_" +#else +/* happiness */ +#include <dlfcn.h> +#define DXTN_EXT "libtxc_dxtn.so" +#define DXTN_PREFIX "" +#endif +#endif /* USE_EXTERNAL_DXTN_LIB */ + +typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut ); +dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL; +dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL; +dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL; +dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL; + +typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, GLenum destformat, GLubyte *dest, GLint dstRowStride); +dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL; + +void *dxtlibhandle = NULL; + +void +_mesa_init_texture_s3tc( GLcontext *ctx ) +{ + /* called during context initialization */ + ctx->Mesa_DXTn = GL_FALSE; +#if USE_EXTERNAL_DXTN_LIB + if (!dxtlibhandle) { + dxtlibhandle = dlopen (DXTN_EXT, RTLD_LAZY | RTLD_GLOBAL); + if (!dxtlibhandle) { + _mesa_warning(ctx, "couldn't open " DXTN_EXT ", software DXTn " + "compression/decompression unavailable\n"); + } + else { + /* the fetch functions are not per context! Might be problematic... */ + fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt)dlsym(dxtlibhandle, DXTN_PREFIX "fetch_2d_texel_rgb_dxt1"); + if (fetch_ext_rgb_dxt1 != NULL) { + fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt)dlsym(dxtlibhandle, DXTN_PREFIX "fetch_2d_texel_rgba_dxt1"); + } + if (fetch_ext_rgba_dxt1 != NULL) { + fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt)dlsym(dxtlibhandle, DXTN_PREFIX "fetch_2d_texel_rgba_dxt3"); + } + if (fetch_ext_rgba_dxt3 != NULL) { + fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt)dlsym(dxtlibhandle, DXTN_PREFIX "fetch_2d_texel_rgba_dxt5"); + } + if (fetch_ext_rgba_dxt5 != NULL) { + ext_tx_compress_dxtn = (dxtCompressTexFuncExt)dlsym(dxtlibhandle, DXTN_PREFIX "tx_compress_dxtn"); + } + + if (ext_tx_compress_dxtn == NULL) { + _mesa_warning(ctx, "couldn't reference all symbols in " + DXTN_EXT ", software DXTn compression/decompression " + "unavailable\n"); + fetch_ext_rgb_dxt1 = NULL; + fetch_ext_rgba_dxt1 = NULL; + fetch_ext_rgba_dxt3 = NULL; + fetch_ext_rgba_dxt5 = NULL; + ext_tx_compress_dxtn = NULL; + dlclose(dxtlibhandle); + dxtlibhandle = NULL; + } + } + } + if (dxtlibhandle) { + ctx->Mesa_DXTn = GL_TRUE; + _mesa_warning(ctx, "software DXTn compression/decompression available\n"); + } +#else + (void) ctx; +#endif +} + +/** + * Called via TexFormat->StoreImage to store an RGB_DXT1 texture. + */ +static GLboolean +texstore_rgb_dxt1(STORE_PARAMS) +{ + const GLchan *pixels; + GLint srcRowStride; + GLubyte *dst; + const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */ + const GLchan *tempImage = NULL; + + ASSERT(dstFormat == &_mesa_texformat_rgb_dxt1); + ASSERT(dstXoffset % 4 == 0); + ASSERT(dstYoffset % 4 == 0); + ASSERT(dstZoffset % 4 == 0); + (void) dstZoffset; (void) dstImageStride; + + if (srcFormat != GL_RGB || + srcType != CHAN_TYPE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGB/GLchan */ + tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + pixels = tempImage; + srcRowStride = 3 * srcWidth; + srcFormat = GL_RGB; + } + else { + pixels = (const GLchan *) srcAddr; + srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, + srcType) / sizeof(GLchan); + } + + dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + texWidth, (GLubyte *) dstAddr); + + if (ext_tx_compress_dxtn) { + (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, dst, dstRowStride); + } + else { + _mesa_problem(ctx, "external dxt library not available"); + } + + if (tempImage) + _mesa_free((void *) tempImage); + + return GL_TRUE; +} + + +/** + * Called via TexFormat->StoreImage to store an RGBA_DXT1 texture. + */ +static GLboolean +texstore_rgba_dxt1(STORE_PARAMS) +{ + const GLchan *pixels; + GLint srcRowStride; + GLubyte *dst; + const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */ + const GLchan *tempImage = NULL; + + ASSERT(dstFormat == &_mesa_texformat_rgba_dxt1); + ASSERT(dstXoffset % 4 == 0); + ASSERT(dstYoffset % 4 == 0); + ASSERT(dstZoffset % 4 == 0); + (void) dstZoffset; (void) dstImageStride; + + if (srcFormat != GL_RGBA || + srcType != CHAN_TYPE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGBA/GLchan */ + tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + pixels = tempImage; + srcRowStride = 4 * srcWidth; + srcFormat = GL_RGBA; + } + else { + pixels = (const GLchan *) srcAddr; + srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, + srcType) / sizeof(GLchan); + } + + dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + texWidth, (GLubyte *) dstAddr); + if (ext_tx_compress_dxtn) { + (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, dst, dstRowStride); + } + else { + _mesa_problem(ctx, "external dxt library not available"); + } + + if (tempImage) + _mesa_free((void*) tempImage); + + return GL_TRUE; +} + + +/** + * Called via TexFormat->StoreImage to store an RGBA_DXT3 texture. + */ +static GLboolean +texstore_rgba_dxt3(STORE_PARAMS) +{ + const GLchan *pixels; + GLint srcRowStride; + GLubyte *dst; + const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */ + const GLchan *tempImage = NULL; + + ASSERT(dstFormat == &_mesa_texformat_rgba_dxt3); + ASSERT(dstXoffset % 4 == 0); + ASSERT(dstYoffset % 4 == 0); + ASSERT(dstZoffset % 4 == 0); + (void) dstZoffset; (void) dstImageStride; + + if (srcFormat != GL_RGBA || + srcType != CHAN_TYPE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGBA/GLchan */ + tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + pixels = tempImage; + srcRowStride = 4 * srcWidth; + } + else { + pixels = (const GLchan *) srcAddr; + srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, + srcType) / sizeof(GLchan); + } + + dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + texWidth, (GLubyte *) dstAddr); + if (ext_tx_compress_dxtn) { + (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, dst, dstRowStride); + } + else { + _mesa_problem(ctx, "external dxt library not available"); + } + + if (tempImage) + _mesa_free((void *) tempImage); + + return GL_TRUE; +} + + +/** + * Called via TexFormat->StoreImage to store an RGBA_DXT5 texture. + */ +static GLboolean +texstore_rgba_dxt5(STORE_PARAMS) +{ + const GLchan *pixels; + GLint srcRowStride; + GLubyte *dst; + const GLint texWidth = dstRowStride * 4 / 16; /* a bit of a hack */ + const GLchan *tempImage = NULL; + + ASSERT(dstFormat == &_mesa_texformat_rgba_dxt5); + ASSERT(dstXoffset % 4 == 0); + ASSERT(dstYoffset % 4 == 0); + ASSERT(dstZoffset % 4 == 0); + (void) dstZoffset; (void) dstImageStride; + + if (srcFormat != GL_RGBA || + srcType != CHAN_TYPE || + ctx->_ImageTransferState || + srcPacking->SwapBytes) { + /* convert image to RGBA/GLchan */ + tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + if (!tempImage) + return GL_FALSE; /* out of memory */ + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + pixels = tempImage; + srcRowStride = 4 * srcWidth; + } + else { + pixels = (const GLchan *) srcAddr; + srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, + srcType) / sizeof(GLchan); + } + + dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + texWidth, (GLubyte *) dstAddr); + if (ext_tx_compress_dxtn) { + (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, dst, dstRowStride); + } + else { + _mesa_problem(ctx, "external dxt library not available"); + } + + if (tempImage) + _mesa_free((void *) tempImage); + + return GL_TRUE; +} + + +static void +fetch_texel_2d_rgb_dxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) k; + if (fetch_ext_rgb_dxt1) { + ASSERT (sizeof(GLchan) == sizeof(GLubyte)); + (*fetch_ext_rgb_dxt1)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel); + } + else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n"); +} + + +static void +fetch_texel_2d_f_rgb_dxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* just sample as GLchan and convert to float here */ + GLchan rgba[4]; + fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba); + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); +} + + +static void +fetch_texel_2d_rgba_dxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) k; + if (fetch_ext_rgba_dxt1) { + (*fetch_ext_rgba_dxt1)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel); + } + else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n"); +} + + +static void +fetch_texel_2d_f_rgba_dxt1( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* just sample as GLchan and convert to float here */ + GLchan rgba[4]; + fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba); + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); +} + + +static void +fetch_texel_2d_rgba_dxt3( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) k; + if (fetch_ext_rgba_dxt3) { + ASSERT (sizeof(GLchan) == sizeof(GLubyte)); + (*fetch_ext_rgba_dxt3)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel); + } + else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n"); +} + + +static void +fetch_texel_2d_f_rgba_dxt3( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* just sample as GLchan and convert to float here */ + GLchan rgba[4]; + fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba); + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); +} + + +static void +fetch_texel_2d_rgba_dxt5( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) k; + if (fetch_ext_rgba_dxt5) { + (*fetch_ext_rgba_dxt5)((texImage)->RowStride, (GLubyte *)(texImage)->Data, i, j, texel); + } + else _mesa_debug(NULL, "attempted to decode s3tc texture without library available\n"); +} + + +static void +fetch_texel_2d_f_rgba_dxt5( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* just sample as GLchan and convert to float here */ + GLchan rgba[4]; + fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba); + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); +} + + +const struct gl_texture_format _mesa_texformat_rgb_dxt1 = { + MESA_FORMAT_RGB_DXT1, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /*approx*/ /* RedBits */ + 4, /*approx*/ /* GreenBits */ + 4, /*approx*/ /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + texstore_rgb_dxt1, /* StoreTexImageFunc */ + NULL, /*impossible*/ /* FetchTexel1D */ + fetch_texel_2d_rgb_dxt1, /* FetchTexel2D */ + NULL, /*impossible*/ /* FetchTexel3D */ + NULL, /*impossible*/ /* FetchTexel1Df */ + fetch_texel_2d_f_rgb_dxt1, /* FetchTexel2Df */ + NULL, /*impossible*/ /* FetchTexel3Df */ +}; + +const struct gl_texture_format _mesa_texformat_rgba_dxt1 = { + MESA_FORMAT_RGBA_DXT1, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /*approx*/ /* RedBits */ + 4, /*approx*/ /* GreenBits */ + 4, /*approx*/ /* BlueBits */ + 1, /*approx*/ /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + texstore_rgba_dxt1, /* StoreTexImageFunc */ + NULL, /*impossible*/ /* FetchTexel1D */ + fetch_texel_2d_rgba_dxt1, /* FetchTexel2D */ + NULL, /*impossible*/ /* FetchTexel3D */ + NULL, /*impossible*/ /* FetchTexel1Df */ + fetch_texel_2d_f_rgba_dxt1, /* FetchTexel2Df */ + NULL, /*impossible*/ /* FetchTexel3Df */ +}; + +const struct gl_texture_format _mesa_texformat_rgba_dxt3 = { + MESA_FORMAT_RGBA_DXT3, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /*approx*/ /* RedBits */ + 4, /*approx*/ /* GreenBits */ + 4, /*approx*/ /* BlueBits */ + 4, /*approx*/ /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + texstore_rgba_dxt3, /* StoreTexImageFunc */ + NULL, /*impossible*/ /* FetchTexel1D */ + fetch_texel_2d_rgba_dxt3, /* FetchTexel2D */ + NULL, /*impossible*/ /* FetchTexel3D */ + NULL, /*impossible*/ /* FetchTexel1Df */ + fetch_texel_2d_f_rgba_dxt3, /* FetchTexel2Df */ + NULL, /*impossible*/ /* FetchTexel3Df */ +}; + +const struct gl_texture_format _mesa_texformat_rgba_dxt5 = { + MESA_FORMAT_RGBA_DXT5, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4,/*approx*/ /* RedBits */ + 4,/*approx*/ /* GreenBits */ + 4,/*approx*/ /* BlueBits */ + 4,/*approx*/ /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + texstore_rgba_dxt5, /* StoreTexImageFunc */ + NULL, /*impossible*/ /* FetchTexel1D */ + fetch_texel_2d_rgba_dxt5, /* FetchTexel2D */ + NULL, /*impossible*/ /* FetchTexel3D */ + NULL, /*impossible*/ /* FetchTexel1Df */ + fetch_texel_2d_f_rgba_dxt5, /* FetchTexel2Df */ + NULL, /*impossible*/ /* FetchTexel3Df */ +}; diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c new file mode 100644 index 00000000000..4cb97469a58 --- /dev/null +++ b/src/mesa/main/texenvprogram.c @@ -0,0 +1,1165 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "glheader.h" +#include "macros.h" +#include "enums.h" +#include "texenvprogram.h" + +#include "shader/program.h" +#include "shader/nvfragprog.h" +#include "shader/arbfragparse.h" + + +#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM) + +struct mode_opt { + unsigned Source:4; + unsigned Operand:3; +}; + +struct state_key { + GLuint enabled_units; + unsigned separate_specular:1; + unsigned fog_enabled:1; + unsigned fog_mode:2; + + struct { + unsigned enabled:1; + unsigned source_index:3; + unsigned ScaleShiftRGB:2; + unsigned ScaleShiftA:2; + + unsigned NumArgsRGB:2; + unsigned ModeRGB:4; + struct mode_opt OptRGB[3]; + + unsigned NumArgsA:2; + unsigned ModeA:4; + struct mode_opt OptA[3]; + } unit[8]; +}; + +#define FOG_LINEAR 0 +#define FOG_EXP 1 +#define FOG_EXP2 2 +#define FOG_UNKNOWN 3 + +static GLuint translate_fog_mode( GLenum mode ) +{ + switch (mode) { + case GL_LINEAR: return FOG_LINEAR; + case GL_EXP: return FOG_EXP; + case GL_EXP2: return FOG_EXP2; + default: return FOG_UNKNOWN; + } +} + +#define OPR_SRC_COLOR 0 +#define OPR_ONE_MINUS_SRC_COLOR 1 +#define OPR_SRC_ALPHA 2 +#define OPR_ONE_MINUS_SRC_ALPHA 3 +#define OPR_ZERO 4 +#define OPR_ONE 5 +#define OPR_UNKNOWN 7 + +static GLuint translate_operand( GLenum operand ) +{ + switch (operand) { + case GL_SRC_COLOR: return OPR_SRC_COLOR; + case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR; + case GL_SRC_ALPHA: return OPR_SRC_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA; + case GL_ZERO: return OPR_ZERO; + case GL_ONE: return OPR_ONE; + default: return OPR_UNKNOWN; + } +} + +#define SRC_TEXTURE 0 +#define SRC_TEXTURE0 1 +#define SRC_TEXTURE1 2 +#define SRC_TEXTURE2 3 +#define SRC_TEXTURE3 4 +#define SRC_TEXTURE4 5 +#define SRC_TEXTURE5 6 +#define SRC_TEXTURE6 7 +#define SRC_TEXTURE7 8 +#define SRC_CONSTANT 9 +#define SRC_PRIMARY_COLOR 10 +#define SRC_PREVIOUS 11 +#define SRC_UNKNOWN 15 + +static GLuint translate_source( GLenum src ) +{ + switch (src) { + case GL_TEXTURE: return SRC_TEXTURE; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0); + case GL_CONSTANT: return SRC_CONSTANT; + case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR; + case GL_PREVIOUS: return SRC_PREVIOUS; + default: return SRC_UNKNOWN; + } +} + +#define MODE_REPLACE 0 +#define MODE_MODULATE 1 +#define MODE_ADD 2 +#define MODE_ADD_SIGNED 3 +#define MODE_INTERPOLATE 4 +#define MODE_SUBTRACT 5 +#define MODE_DOT3_RGB 6 +#define MODE_DOT3_RGB_EXT 7 +#define MODE_DOT3_RGBA 8 +#define MODE_DOT3_RGBA_EXT 9 +#define MODE_MODULATE_ADD_ATI 10 +#define MODE_MODULATE_SIGNED_ADD_ATI 11 +#define MODE_MODULATE_SUBTRACT_ATI 12 +#define MODE_UNKNOWN 15 + +static GLuint translate_mode( GLenum mode ) +{ + switch (mode) { + case GL_REPLACE: return MODE_REPLACE; + case GL_MODULATE: return MODE_MODULATE; + case GL_ADD: return MODE_ADD; + case GL_ADD_SIGNED: return MODE_ADD_SIGNED; + case GL_INTERPOLATE: return MODE_INTERPOLATE; + case GL_SUBTRACT: return MODE_SUBTRACT; + case GL_DOT3_RGB: return MODE_DOT3_RGB; + case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT; + case GL_DOT3_RGBA: return MODE_DOT3_RGBA; + case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT; + case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI; + case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI; + case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI; + default: return MODE_UNKNOWN; + } +} + +#define TEXTURE_UNKNOWN_INDEX 7 +static GLuint translate_tex_src_bit( GLuint bit ) +{ + switch (bit) { + case TEXTURE_1D_BIT: return TEXTURE_1D_INDEX; + case TEXTURE_2D_BIT: return TEXTURE_2D_INDEX; + case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX; + case TEXTURE_3D_BIT: return TEXTURE_3D_INDEX; + case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX; + default: return TEXTURE_UNKNOWN_INDEX; + } +} + +static struct state_key *make_state_key( GLcontext *ctx ) +{ + struct state_key *key = CALLOC_STRUCT(state_key); + GLuint i, j; + + for (i=0;i<MAX_TEXTURE_UNITS;i++) { + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; + + if (!texUnit->_ReallyEnabled) + continue; + + key->unit[i].enabled = 1; + key->enabled_units |= (1<<i); + + key->unit[i].source_index = + translate_tex_src_bit(texUnit->_ReallyEnabled); + + key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB; + key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA; + + key->unit[i].ModeRGB = + translate_mode(texUnit->_CurrentCombine->ModeRGB); + key->unit[i].ModeA = + translate_mode(texUnit->_CurrentCombine->ModeA); + + key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB; + key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftRGB; + + for (j=0;j<3;j++) { + key->unit[i].OptRGB[j].Operand = + translate_operand(texUnit->_CurrentCombine->OperandRGB[j]); + key->unit[i].OptA[j].Operand = + translate_operand(texUnit->_CurrentCombine->OperandA[j]); + key->unit[i].OptRGB[j].Source = + translate_source(texUnit->_CurrentCombine->SourceRGB[j]); + key->unit[i].OptA[j].Source = + translate_source(texUnit->_CurrentCombine->SourceA[j]); + } + } + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + key->separate_specular = 1; + + if (ctx->Fog.Enabled) { + key->fog_enabled = 1; + key->fog_mode = translate_fog_mode(ctx->Fog.Mode); + } + + return key; +} + +/* Use uregs to represent registers internally, translate to Mesa's + * expected formats on emit. + * + * NOTE: These are passed by value extensively in this file rather + * than as usual by pointer reference. If this disturbs you, try + * remembering they are just 32bits in size. + * + * GCC is smart enough to deal with these dword-sized structures in + * much the same way as if I had defined them as dwords and was using + * macros to access and set the fields. This is much nicer and easier + * to evolve. + */ +struct ureg { + GLuint file:4; + GLuint idx:8; + GLuint negatebase:1; + GLuint abs:1; + GLuint negateabs:1; + GLuint swz:12; + GLuint pad:5; +}; + +const static struct ureg undef = { + ~0, + ~0, + 0, + 0, + 0, + 0, + 0 +}; + +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +/* State used to build the fragment program: + */ +struct texenv_fragment_program { + struct fragment_program *program; + GLcontext *ctx; + struct state_key *state; + + GLuint alu_temps; /* Track texture indirections, see spec. */ + GLuint temps_output; /* Track texture indirections, see spec. */ + + GLuint temp_in_use; /* Tracks temporary regs which are in + * use. + */ + + + GLboolean error; + + struct ureg src_texture[MAX_TEXTURE_UNITS]; + /* Reg containing each texture unit's sampled texture color, + * else undef. + */ + + struct ureg src_previous; /* Reg containing color from previous + * stage. May need to be decl'd. + */ + + GLuint last_tex_stage; /* Number of last enabled texture unit */ + + struct ureg half; + struct ureg one; + struct ureg zero; +}; + + + +static struct ureg make_ureg(GLuint file, GLuint idx) +{ + struct ureg reg; + reg.file = file; + reg.idx = idx; + reg.negatebase = 0; + reg.abs = 0; + reg.negateabs = 0; + reg.swz = SWIZZLE_NOOP; + reg.pad = 0; + return reg; +} + +static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w ) +{ + reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x), + GET_SWZ(reg.swz, y), + GET_SWZ(reg.swz, z), + GET_SWZ(reg.swz, w)); + + return reg; +} + +static struct ureg swizzle1( struct ureg reg, int x ) +{ + return swizzle(reg, x, x, x, x); +} + +static struct ureg negate( struct ureg reg ) +{ + reg.negatebase ^= 1; + return reg; +} + +static GLboolean is_undef( struct ureg reg ) +{ + return reg.file == 0xf; +} + + +static struct ureg get_temp( struct texenv_fragment_program *p ) +{ + int bit; + + /* First try and reuse temps which have been used already: + */ + bit = ffs( ~p->temp_in_use & p->alu_temps ); + + /* Then any unused temporary: + */ + if (!bit) + bit = ffs( ~p->temp_in_use ); + + if (!bit) { + _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__); + exit(1); + } + + p->temp_in_use |= 1<<(bit-1); + return make_ureg(PROGRAM_TEMPORARY, (bit-1)); +} + +static struct ureg get_tex_temp( struct texenv_fragment_program *p ) +{ + int bit; + + /* First try to find availble temp not previously used (to avoid + * starting a new texture indirection). According to the spec, the + * ~p->temps_output isn't necessary, but will keep it there for + * now: + */ + bit = ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output ); + + /* Then any unused temporary: + */ + if (!bit) + bit = ffs( ~p->temp_in_use ); + + if (!bit) { + _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__); + exit(1); + } + + p->temp_in_use |= 1<<(bit-1); + return make_ureg(PROGRAM_TEMPORARY, (bit-1)); +} + + +static void release_temps( struct texenv_fragment_program *p ) +{ + GLuint max_temp = p->ctx->Const.MaxFragmentProgramTemps; + + /* KW: To support tex_env_crossbar, don't release the registers in + * temps_output. + */ + if (max_temp >= sizeof(int) * 8) + p->temp_in_use = p->temps_output; + else + p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output; +} + + +static struct ureg register_param6( struct texenv_fragment_program *p, + GLint s0, + GLint s1, + GLint s2, + GLint s3, + GLint s4, + GLint s5) +{ + GLint tokens[6]; + GLuint idx; + tokens[0] = s0; + tokens[1] = s1; + tokens[2] = s2; + tokens[3] = s3; + tokens[4] = s4; + tokens[5] = s5; + idx = _mesa_add_state_reference( p->program->Parameters, tokens ); + return make_ureg(PROGRAM_STATE_VAR, idx); +} + + +#define register_param1(p,s0) register_param6(p,s0,0,0,0,0,0) +#define register_param2(p,s0,s1) register_param6(p,s0,s1,0,0,0,0) +#define register_param3(p,s0,s1,s2) register_param6(p,s0,s1,s2,0,0,0) +#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0) + + +static struct ureg register_input( struct texenv_fragment_program *p, GLuint input ) +{ + p->program->InputsRead |= (1<<input); + return make_ureg(PROGRAM_INPUT, input); +} + + +static void emit_arg( struct fp_src_register *reg, + struct ureg ureg ) +{ + reg->File = ureg.file; + reg->Index = ureg.idx; + reg->Swizzle = ureg.swz; + reg->NegateBase = ureg.negatebase; + reg->Abs = ureg.abs; + reg->NegateAbs = ureg.negateabs; +} + +static void emit_dst( struct fp_dst_register *dst, + struct ureg ureg, GLuint mask ) +{ + dst->File = ureg.file; + dst->Index = ureg.idx; + dst->WriteMask = mask; + dst->CondMask = 0; + dst->CondSwizzle = 0; +} + +static struct fp_instruction * +emit_op(struct texenv_fragment_program *p, + GLuint op, + struct ureg dest, + GLuint mask, + GLuint saturate, + struct ureg src0, + struct ureg src1, + struct ureg src2 ) +{ + GLuint nr = p->program->Base.NumInstructions++; + struct fp_instruction *inst = &p->program->Instructions[nr]; + + memset(inst, 0, sizeof(*inst)); + inst->Opcode = op; + + emit_arg( &inst->SrcReg[0], src0 ); + emit_arg( &inst->SrcReg[1], src1 ); + emit_arg( &inst->SrcReg[2], src2 ); + + inst->Saturate = saturate; + + emit_dst( &inst->DstReg, dest, mask ); + + /* Accounting for indirection tracking: + */ + if (dest.file == PROGRAM_TEMPORARY) + p->temps_output |= 1 << dest.idx; + + return inst; +} + + +static struct ureg emit_arith( struct texenv_fragment_program *p, + GLuint op, + struct ureg dest, + GLuint mask, + GLuint saturate, + struct ureg src0, + struct ureg src1, + struct ureg src2 ) +{ + emit_op(p, op, dest, mask, saturate, src0, src1, src2); + + /* Accounting for indirection tracking: + */ + if (src0.file == PROGRAM_TEMPORARY) + p->alu_temps |= 1 << src0.idx; + + if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY) + p->alu_temps |= 1 << src1.idx; + + if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY) + p->alu_temps |= 1 << src2.idx; + + if (dest.file == PROGRAM_TEMPORARY) + p->alu_temps |= 1 << dest.idx; + + p->program->NumAluInstructions++; + return dest; +} + +static struct ureg emit_texld( struct texenv_fragment_program *p, + GLuint op, + struct ureg dest, + GLuint destmask, + GLuint tex_unit, + GLuint tex_idx, + struct ureg coord ) +{ + struct fp_instruction *inst = emit_op( p, op, + dest, destmask, + 0, /* don't saturate? */ + coord, /* arg 0? */ + undef, + undef); + + inst->TexSrcIdx = tex_idx; + inst->TexSrcUnit = tex_unit; + + p->program->NumTexInstructions++; + + /* Is this a texture indirection? + */ + if ((coord.file == PROGRAM_TEMPORARY && + (p->temps_output & (1<<coord.idx))) || + (dest.file == PROGRAM_TEMPORARY && + (p->alu_temps & (1<<dest.idx)))) { + p->program->NumTexIndirections++; + p->temps_output = 1<<coord.idx; + p->alu_temps = 0; + assert(0); /* KW: texture env crossbar */ + } + + return dest; +} + + +static struct ureg register_const4f( struct texenv_fragment_program *p, + GLfloat s0, + GLfloat s1, + GLfloat s2, + GLfloat s3) +{ + GLfloat values[4]; + GLuint idx; + values[0] = s0; + values[1] = s1; + values[2] = s2; + values[3] = s3; + idx = _mesa_add_unnamed_constant( p->program->Parameters, values ); + return make_ureg(PROGRAM_STATE_VAR, idx); +} + +#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0) +#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1) +#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1) +#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1) + + + + +static struct ureg get_one( struct texenv_fragment_program *p ) +{ + if (is_undef(p->one)) + p->one = register_scalar_const(p, 1.0); + return p->one; +} + +static struct ureg get_half( struct texenv_fragment_program *p ) +{ + if (is_undef(p->half)) + p->one = register_scalar_const(p, 0.5); + return p->half; +} + +static struct ureg get_zero( struct texenv_fragment_program *p ) +{ + if (is_undef(p->zero)) + p->one = register_scalar_const(p, 0.0); + return p->zero; +} + + + + + +static void program_error( struct texenv_fragment_program *p, const char *msg ) +{ + _mesa_problem(NULL, msg); + p->error = 1; +} + +static struct ureg get_source( struct texenv_fragment_program *p, + GLuint src, GLuint unit ) +{ + switch (src) { + case SRC_TEXTURE: + assert(!is_undef(p->src_texture[unit])); + return p->src_texture[unit]; + + case SRC_TEXTURE0: + case SRC_TEXTURE1: + case SRC_TEXTURE2: + case SRC_TEXTURE3: + case SRC_TEXTURE4: + case SRC_TEXTURE5: + case SRC_TEXTURE6: + case SRC_TEXTURE7: + assert(!is_undef(p->src_texture[src - SRC_TEXTURE0])); + return p->src_texture[src - SRC_TEXTURE0]; + + case SRC_CONSTANT: + return register_param2(p, STATE_TEXENV_COLOR, unit); + + case SRC_PRIMARY_COLOR: + return register_input(p, FRAG_ATTRIB_COL0); + + case SRC_PREVIOUS: + default: + if (is_undef(p->src_previous)) + return register_input(p, FRAG_ATTRIB_COL0); + else + return p->src_previous; + } +} + +static struct ureg emit_combine_source( struct texenv_fragment_program *p, + GLuint mask, + GLuint unit, + GLuint source, + GLuint operand ) +{ + struct ureg arg, src, one; + + src = get_source(p, source, unit); + + switch (operand) { + case OPR_ONE_MINUS_SRC_COLOR: + /* Get unused tmp, + * Emit tmp = 1.0 - arg.xyzw + */ + arg = get_temp( p ); + one = get_one( p ); + return emit_arith( p, FP_OPCODE_SUB, arg, mask, 0, one, src, undef); + + case OPR_SRC_ALPHA: + if (mask == WRITEMASK_W) + return src; + else + return swizzle1( src, W ); + case OPR_ONE_MINUS_SRC_ALPHA: + /* Get unused tmp, + * Emit tmp = 1.0 - arg.wwww + */ + arg = get_temp(p); + one = get_one(p); + return emit_arith(p, FP_OPCODE_SUB, arg, mask, 0, + one, swizzle1(src, W), undef); + case OPR_ZERO: + return get_zero(p); + case OPR_ONE: + return get_one(p); + case OPR_SRC_COLOR: + default: + return src; + } +} + +static GLboolean args_match( struct state_key *key, GLuint unit ) +{ + int i, nr = key->unit[unit].NumArgsRGB; + + for (i = 0 ; i < nr ; i++) { + if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source) + return GL_FALSE; + + switch(key->unit[unit].OptA[i].Operand) { + case OPR_SRC_ALPHA: + switch(key->unit[unit].OptRGB[i].Operand) { + case OPR_SRC_COLOR: + case OPR_SRC_ALPHA: + break; + default: + return GL_FALSE; + } + break; + case OPR_ONE_MINUS_SRC_ALPHA: + switch(key->unit[unit].OptRGB[i].Operand) { + case OPR_ONE_MINUS_SRC_COLOR: + case OPR_ONE_MINUS_SRC_ALPHA: + break; + default: + return GL_FALSE; + } + break; + default: + return GL_FALSE; /* impossible */ + } + } + + return GL_TRUE; +} + +static struct ureg emit_combine( struct texenv_fragment_program *p, + struct ureg dest, + GLuint mask, + GLuint saturate, + GLuint unit, + GLuint nr, + GLuint mode, + struct mode_opt *opt) +{ + struct ureg src[3]; + struct ureg tmp, half; + int i; + + for (i = 0; i < nr; i++) + src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand ); + + switch (mode) { + case MODE_REPLACE: + if (mask == WRITEMASK_XYZW && !saturate) + return src[0]; + else + return emit_arith( p, FP_OPCODE_MOV, dest, mask, saturate, src[0], undef, undef ); + case MODE_MODULATE: + return emit_arith( p, FP_OPCODE_MUL, dest, mask, saturate, + src[0], src[1], undef ); + case MODE_ADD: + return emit_arith( p, FP_OPCODE_ADD, dest, mask, saturate, + src[0], src[1], undef ); + case MODE_ADD_SIGNED: + /* tmp = arg0 + arg1 + * result = tmp - .5 + */ + half = get_half(p); + emit_arith( p, FP_OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef ); + emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, tmp, half, undef ); + return dest; + case MODE_INTERPOLATE: + /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered: + */ + return emit_arith( p, FP_OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] ); + + case MODE_SUBTRACT: + return emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef ); + + case MODE_DOT3_RGBA: + case MODE_DOT3_RGBA_EXT: + case MODE_DOT3_RGB_EXT: + case MODE_DOT3_RGB: { + struct ureg tmp0 = get_temp( p ); + struct ureg tmp1 = get_temp( p ); + struct ureg neg1 = register_scalar_const(p, -1); + struct ureg two = register_scalar_const(p, 2); + + /* tmp0 = 2*src0 - 1 + * tmp1 = 2*src1 - 1 + * + * dst = tmp0 dot3 tmp1 + */ + emit_arith( p, FP_OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0, + two, src[0], neg1); + + if (memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0) + tmp1 = tmp0; + else + emit_arith( p, FP_OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0, + two, src[1], neg1); + emit_arith( p, FP_OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef); + return dest; + } + case MODE_MODULATE_ADD_ATI: + /* Arg0 * Arg2 + Arg1 */ + return emit_arith( p, FP_OPCODE_MAD, dest, mask, saturate, + src[0], src[2], src[1] ); + case MODE_MODULATE_SIGNED_ADD_ATI: { + /* Arg0 * Arg2 + Arg1 - 0.5 */ + struct ureg tmp0 = get_temp(p); + half = get_half(p); + emit_arith( p, FP_OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] ); + emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, tmp0, half, undef ); + return dest; + } + case MODE_MODULATE_SUBTRACT_ATI: + /* Arg0 * Arg2 - Arg1 */ + emit_arith( p, FP_OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) ); + return dest; + default: + return src[0]; + } +} + + +static struct ureg emit_texenv( struct texenv_fragment_program *p, int unit ) +{ + struct state_key *key = p->state; + GLuint saturate = (unit < p->last_tex_stage); + GLuint rgb_shift, alpha_shift; + struct ureg out, shift; + struct ureg dest; + + if (!key->unit[unit].enabled) { + return get_source(p, SRC_PREVIOUS, 0); + } + + switch (key->unit[unit].ModeRGB) { + case MODE_DOT3_RGB_EXT: + alpha_shift = key->unit[unit].ScaleShiftA; + rgb_shift = 0; + break; + case MODE_DOT3_RGBA_EXT: + alpha_shift = 0; + rgb_shift = 0; + break; + default: + rgb_shift = key->unit[unit].ScaleShiftRGB; + alpha_shift = key->unit[unit].ScaleShiftA; + break; + } + + /* If this is the very last calculation, emit direct to output reg: + */ + if (key->separate_specular || + unit != p->last_tex_stage || + alpha_shift || + rgb_shift) + dest = get_temp( p ); + else + dest = make_ureg(PROGRAM_OUTPUT, FRAG_OUTPUT_COLR); + + /* Emit the RGB and A combine ops + */ + if (key->unit[unit].ModeRGB == key->unit[unit].ModeA && + args_match(key, unit)) { + out = emit_combine( p, dest, WRITEMASK_XYZW, saturate, + unit, + key->unit[unit].NumArgsRGB, + key->unit[unit].ModeRGB, + key->unit[unit].OptRGB); + } + else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT || + key->unit[unit].ModeA == MODE_DOT3_RGBA) { + + out = emit_combine( p, dest, WRITEMASK_XYZW, saturate, + unit, + key->unit[unit].NumArgsRGB, + key->unit[unit].ModeRGB, + key->unit[unit].OptRGB); + } + else { + /* Need to do something to stop from re-emitting identical + * argument calculations here: + */ + out = emit_combine( p, dest, WRITEMASK_XYZ, saturate, + unit, + key->unit[unit].NumArgsRGB, + key->unit[unit].ModeRGB, + key->unit[unit].OptRGB); + out = emit_combine( p, dest, WRITEMASK_W, saturate, + unit, + key->unit[unit].NumArgsA, + key->unit[unit].ModeA, + key->unit[unit].OptA); + } + + /* Deal with the final shift: + */ + if (alpha_shift || rgb_shift) { + if (rgb_shift == alpha_shift) { + shift = register_scalar_const(p, 1<<rgb_shift); + } + else { + shift = register_const4f(p, + 1<<rgb_shift, + 1<<rgb_shift, + 1<<rgb_shift, + 1<<alpha_shift); + } + return emit_arith( p, FP_OPCODE_MUL, dest, WRITEMASK_XYZW, + saturate, out, shift, undef ); + } + else + return out; +} + + + +static void load_texture( struct texenv_fragment_program *p, GLuint unit ) +{ + if (is_undef(p->src_texture[unit])) { + GLuint dim = p->state->unit[unit].source_index; + struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit); + struct ureg tmp = get_tex_temp( p ); + + if (dim == TEXTURE_UNKNOWN_INDEX) + program_error(p, "TexSrcBit"); + + /* TODO: Use D0_MASK_XY where possible. + */ + p->src_texture[unit] = emit_texld( p, FP_OPCODE_TXP, + tmp, WRITEMASK_XYZW, + unit, dim, texcoord ); + } +} + +static GLboolean load_texenv_source( struct texenv_fragment_program *p, + GLuint src, GLuint unit ) +{ + switch (src) { + case SRC_TEXTURE: + load_texture(p, unit); + break; + + case SRC_TEXTURE0: + case SRC_TEXTURE1: + case SRC_TEXTURE2: + case SRC_TEXTURE3: + case SRC_TEXTURE4: + case SRC_TEXTURE5: + case SRC_TEXTURE6: + case SRC_TEXTURE7: + if (!p->state->unit[src - SRC_TEXTURE0].enabled) + return GL_FALSE; + load_texture(p, src - SRC_TEXTURE0); + break; + + default: + break; + } + + return GL_TRUE; +} + +static GLboolean load_texunit_sources( struct texenv_fragment_program *p, int unit ) +{ + struct state_key *key = p->state; + int i, nr = key->unit[unit].NumArgsRGB; + for (i = 0; i < nr; i++) { + if (!load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit) || + !load_texenv_source( p, key->unit[unit].OptA[i].Source, unit )) + return GL_FALSE; + } + return GL_TRUE; +} + +static void create_new_program(struct state_key *key, GLcontext *ctx, + struct fragment_program *program) +{ + struct texenv_fragment_program p; + GLuint unit; + struct ureg cf, out; + + _mesa_memset(&p, 0, sizeof(p)); + p.ctx = ctx; + p.state = key; + p.program = program; + + p.program->Instructions = MALLOC(sizeof(struct fp_instruction) * 100); + p.program->Base.NumInstructions = 0; + p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB; + p.program->NumTexIndirections = 1; /* correct? */ + p.program->NumTexInstructions = 0; + p.program->NumAluInstructions = 0; + p.program->Base.String = 0; + p.program->Base.NumInstructions = + p.program->Base.NumTemporaries = + p.program->Base.NumParameters = + p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0; + p.program->Parameters = _mesa_new_parameter_list(); + + p.program->InputsRead = 0; + p.program->OutputsWritten = 1 << FRAG_OUTPUT_COLR; + + for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) + p.src_texture[unit] = undef; + + p.src_previous = undef; + p.last_tex_stage = 0; + release_temps(&p); + + if (key->enabled_units) { + /* First pass - to support texture_env_crossbar, first identify + * all referenced texture sources and emit texld instructions + * for each: + */ + for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++) + if (key->unit[unit].enabled) { + if (load_texunit_sources( &p, unit )) + p.last_tex_stage = unit; + } + + /* Second pass - emit combine instructions to build final color: + */ + for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) + if (key->enabled_units & (1<<unit)) { + p.src_previous = emit_texenv( &p, unit ); + release_temps(&p); /* release all temps */ + } + } + + cf = get_source( &p, SRC_PREVIOUS, 0 ); + out = make_ureg( PROGRAM_OUTPUT, FRAG_OUTPUT_COLR ); + + if (key->separate_specular) { + /* Emit specular add. + */ + struct ureg s = register_input(&p, FRAG_ATTRIB_COL1); + emit_arith( &p, FP_OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef ); + } + else if (memcmp(&cf, &out, sizeof(cf)) != 0) { + /* Will wind up in here if no texture enabled or a couple of + * other scenarios (GL_REPLACE for instance). + */ + emit_arith( &p, FP_OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef ); + } + + /* Finish up: + */ + emit_arith( &p, FP_OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef); + + if (key->fog_enabled) { + /* Pull fog mode from GLcontext, the value in the state key is + * a reduced value and not what is expected in FogOption + */ + p.program->FogOption = ctx->Fog.Mode; + } else + p.program->FogOption = GL_NONE; + + if (p.program->NumTexIndirections > ctx->Const.MaxFragmentProgramTexIndirections) + program_error(&p, "Exceeded max nr indirect texture lookups"); + + if (p.program->NumTexInstructions > ctx->Const.MaxFragmentProgramTexInstructions) + program_error(&p, "Exceeded max TEX instructions"); + + if (p.program->NumAluInstructions > ctx->Const.MaxFragmentProgramAluInstructions) + program_error(&p, "Exceeded max ALU instructions"); + + + /* Notify driver the fragment program has (actually) changed. + */ + if (ctx->Driver.ProgramStringNotify || DISASSEM) { + if (ctx->Driver.ProgramStringNotify) + ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB, + &p.program->Base ); + + if (DISASSEM) { + _mesa_debug_fp_inst(p.program->NumTexInstructions + p.program->NumAluInstructions, + p.program->Instructions); + _mesa_printf("\n"); + } + + } + +} + +static void *search_cache( struct texenvprog_cache *cache, + GLuint hash, + const void *key, + GLuint keysize) +{ + struct texenvprog_cache *c; + + for (c = cache; c; c = c->next) { + if (c->hash == hash && memcmp(c->key, key, keysize) == 0) + return c->data; + } + + return NULL; +} + +static void cache_item( struct texenvprog_cache **cache, + GLuint hash, + void *key, + void *data ) +{ + struct texenvprog_cache *c = MALLOC(sizeof(*c)); + c->hash = hash; + c->key = key; + c->data = data; + c->next = *cache; + *cache = c; +} + +static GLuint hash_key( struct state_key *key ) +{ + GLuint *ikey = (GLuint *)key; + GLuint hash = 0, i; + + /* I'm sure this can be improved on, but speed is important: + */ + for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++) + hash ^= ikey[i]; + + return hash; +} + +void _mesa_UpdateTexEnvProgram( GLcontext *ctx ) +{ + struct state_key *key; + GLuint hash; + + if (ctx->FragmentProgram._Enabled) + return; + + key = make_state_key(ctx); + hash = hash_key(key); + + ctx->FragmentProgram._Current = ctx->_TexEnvProgram = + (struct fragment_program *) + search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key)); + + if (!ctx->_TexEnvProgram) { + if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash); + + ctx->FragmentProgram._Current = ctx->_TexEnvProgram = + (struct fragment_program *) + ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); + + create_new_program(key, ctx, ctx->_TexEnvProgram); + + cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram); + } else { + FREE(key); + if (0) _mesa_printf("Found existing texenv program for key %x\n", hash); + } + +} + +void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx ) +{ + struct texenvprog_cache *a, *tmp; + + for (a = ctx->Texture.env_fp_cache; a; a = tmp) { + tmp = a->next; + FREE(a->key); + FREE(a->data); + FREE(a); + } +} + diff --git a/src/mesa/main/texenvprogram.h b/src/mesa/main/texenvprogram.h new file mode 100644 index 00000000000..30c8cca3889 --- /dev/null +++ b/src/mesa/main/texenvprogram.h @@ -0,0 +1,40 @@ +/** + * \file texenvprogram.h + * Texture state management. + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef TEXENVPROGRAM_H +#define TEXENVPROGRAM_H + + +#include "mtypes.h" + +extern void _mesa_UpdateTexEnvProgram( GLcontext *ctx ); +extern void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx ); + +#endif diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c new file mode 100644 index 00000000000..878a10bb7cb --- /dev/null +++ b/src/mesa/main/texformat.c @@ -0,0 +1,1314 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texformat.c + * Texture formats. + * + * \author Gareth Hughes + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "image.h" +#include "imports.h" +#include "mtypes.h" +#include "texformat.h" +#include "teximage.h" +#include "texstate.h" +#include "texstore.h" + + + +/* Texel fetch routines for all supported formats + */ +#define DIM 1 +#include "texformat_tmp.h" + +#define DIM 2 +#include "texformat_tmp.h" + +#define DIM 3 +#include "texformat_tmp.h" + +/** + * Null texel fetch function. + * + * Have to have this so the FetchTexel function pointer is never NULL. + */ +static void fetch_null_texel( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + (void) texImage; (void) i; (void) j; (void) k; + texel[RCOMP] = 0; + texel[GCOMP] = 0; + texel[BCOMP] = 0; + texel[ACOMP] = 0; + _mesa_warning(NULL, "fetch_null_texel() called!"); +} + +static void fetch_null_texelf( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + (void) texImage; (void) i; (void) j; (void) k; + texel[RCOMP] = 0.0; + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 0.0; + _mesa_warning(NULL, "fetch_null_texelf() called!"); +} + +static void store_null_texel(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* no-op */ +} + + + +/***************************************************************/ +/** \name Default GLchan-based formats */ +/*@{*/ + +const struct gl_texture_format _mesa_texformat_rgba = { + MESA_FORMAT_RGBA, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + CHAN_BITS, /* RedBits */ + CHAN_BITS, /* GreenBits */ + CHAN_BITS, /* BlueBits */ + CHAN_BITS, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4 * sizeof(GLchan), /* TexelBytes */ + _mesa_texstore_rgba, /* StoreTexImageFunc */ + fetch_texel_1d_rgba, /* FetchTexel1D */ + fetch_texel_2d_rgba, /* FetchTexel2D */ + fetch_texel_3d_rgba, /* FetchTexel3D */ + fetch_texel_1d_f_rgba, /* FetchTexel1Df */ + fetch_texel_2d_f_rgba, /* FetchTexel2Df */ + fetch_texel_3d_f_rgba, /* FetchTexel3Df */ + store_texel_rgba /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb = { + MESA_FORMAT_RGB, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + CHAN_BITS, /* RedBits */ + CHAN_BITS, /* GreenBits */ + CHAN_BITS, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 3 * sizeof(GLchan), /* TexelBytes */ + _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_rgb, /* FetchTexel1D */ + fetch_texel_2d_rgb, /* FetchTexel2D */ + fetch_texel_3d_rgb, /* FetchTexel3D */ + fetch_texel_1d_f_rgb, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb, /* FetchTexel3Df */ + store_texel_rgb /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_alpha = { + MESA_FORMAT_ALPHA, /* MesaFormat */ + GL_ALPHA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + CHAN_BITS, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + sizeof(GLchan), /* TexelBytes */ + _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_alpha, /* FetchTexel1D */ + fetch_texel_2d_alpha, /* FetchTexel2D */ + fetch_texel_3d_alpha, /* FetchTexel3D */ + fetch_texel_1d_f_alpha, /* FetchTexel1Df */ + fetch_texel_2d_f_alpha, /* FetchTexel2Df */ + fetch_texel_3d_f_alpha, /* FetchTexel3Df */ + store_texel_alpha /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_luminance = { + MESA_FORMAT_LUMINANCE, /* MesaFormat */ + GL_LUMINANCE, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + CHAN_BITS, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + sizeof(GLchan), /* TexelBytes */ + _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_luminance, /* FetchTexel1D */ + fetch_texel_2d_luminance, /* FetchTexel2D */ + fetch_texel_3d_luminance, /* FetchTexel3D */ + fetch_texel_1d_f_luminance, /* FetchTexel1Df */ + fetch_texel_2d_f_luminance, /* FetchTexel2Df */ + fetch_texel_3d_f_luminance, /* FetchTexel3Df */ + store_texel_luminance /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_luminance_alpha = { + MESA_FORMAT_LUMINANCE_ALPHA, /* MesaFormat */ + GL_LUMINANCE_ALPHA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + CHAN_BITS, /* AlphaBits */ + CHAN_BITS, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2 * sizeof(GLchan), /* TexelBytes */ + _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_luminance_alpha, /* FetchTexel1D */ + fetch_texel_2d_luminance_alpha, /* FetchTexel2D */ + fetch_texel_3d_luminance_alpha, /* FetchTexel3D */ + fetch_texel_1d_f_luminance_alpha, /* FetchTexel1Df */ + fetch_texel_2d_f_luminance_alpha, /* FetchTexel2Df */ + fetch_texel_3d_f_luminance_alpha, /* FetchTexel3Df */ + store_texel_luminance_alpha /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_intensity = { + MESA_FORMAT_INTENSITY, /* MesaFormat */ + GL_INTENSITY, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + CHAN_BITS, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + sizeof(GLchan), /* TexelBytes */ + _mesa_texstore_rgba,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_intensity, /* FetchTexel1D */ + fetch_texel_2d_intensity, /* FetchTexel2D */ + fetch_texel_3d_intensity, /* FetchTexel3D */ + fetch_texel_1d_f_intensity, /* FetchTexel1Df */ + fetch_texel_2d_f_intensity, /* FetchTexel2Df */ + fetch_texel_3d_f_intensity, /* FetchTexel3Df */ + store_texel_intensity /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_depth_component_float32 = { + MESA_FORMAT_DEPTH_COMPONENT_FLOAT32, /* MesaFormat */ + GL_DEPTH_COMPONENT, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + sizeof(GLfloat) * 8, /* DepthBits */ + sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_depth_component_float32,/* StoreTexImageFunc */ + fetch_null_texel, /* FetchTexel1D */ + fetch_null_texel, /* FetchTexel1D */ + fetch_null_texel, /* FetchTexel1D */ + fetch_texel_1d_f_depth_component_f32,/* FetchTexel1Df */ + fetch_texel_2d_f_depth_component_f32,/* FetchTexel2Df */ + fetch_texel_3d_f_depth_component_f32,/* FetchTexel3Df */ + store_texel_depth_component_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_depth_component16 = { + MESA_FORMAT_DEPTH_COMPONENT16, /* MesaFormat */ + GL_DEPTH_COMPONENT, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + sizeof(GLushort) * 8, /* DepthBits */ + sizeof(GLushort), /* TexelBytes */ + _mesa_texstore_depth_component16, /* StoreTexImageFunc */ + fetch_null_texel, /* FetchTexel1D */ + fetch_null_texel, /* FetchTexel1D */ + fetch_null_texel, /* FetchTexel1D */ + fetch_texel_1d_f_depth_component16, /* FetchTexel1Df */ + fetch_texel_2d_f_depth_component16, /* FetchTexel2Df */ + fetch_texel_3d_f_depth_component16, /* FetchTexel3Df */ + store_texel_depth_component16 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgba_float32 = { + MESA_FORMAT_RGBA_FLOAT32, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 8 * sizeof(GLfloat), /* RedBits */ + 8 * sizeof(GLfloat), /* GreenBits */ + 8 * sizeof(GLfloat), /* BlueBits */ + 8 * sizeof(GLfloat), /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4 * sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_rgba_float32, /* StoreTexImageFunc */ + fetch_texel_1d_rgba_f32, /* FetchTexel1D */ + fetch_texel_2d_rgba_f32, /* FetchTexel1D */ + fetch_texel_3d_rgba_f32, /* FetchTexel1D */ + fetch_texel_1d_f_rgba_f32, /* FetchTexel1Df */ + fetch_texel_2d_f_rgba_f32, /* FetchTexel2Df */ + fetch_texel_3d_f_rgba_f32, /* FetchTexel3Df */ + store_texel_rgba_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgba_float16 = { + MESA_FORMAT_RGBA_FLOAT16, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 8 * sizeof(GLhalfARB), /* RedBits */ + 8 * sizeof(GLhalfARB), /* GreenBits */ + 8 * sizeof(GLhalfARB), /* BlueBits */ + 8 * sizeof(GLhalfARB), /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4 * sizeof(GLhalfARB), /* TexelBytes */ + _mesa_texstore_rgba_float16, /* StoreTexImageFunc */ + fetch_texel_1d_rgba_f16, /* FetchTexel1D */ + fetch_texel_2d_rgba_f16, /* FetchTexel1D */ + fetch_texel_3d_rgba_f16, /* FetchTexel1D */ + fetch_texel_1d_f_rgba_f16, /* FetchTexel1Df */ + fetch_texel_2d_f_rgba_f16, /* FetchTexel2Df */ + fetch_texel_3d_f_rgba_f16, /* FetchTexel3Df */ + store_texel_rgba_f16 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb_float32 = { + MESA_FORMAT_RGB_FLOAT32, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 8 * sizeof(GLfloat), /* RedBits */ + 8 * sizeof(GLfloat), /* GreenBits */ + 8 * sizeof(GLfloat), /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 3 * sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_rgb_f32, /* FetchTexel1D */ + fetch_texel_2d_rgb_f32, /* FetchTexel1D */ + fetch_texel_3d_rgb_f32, /* FetchTexel1D */ + fetch_texel_1d_f_rgb_f32, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb_f32, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb_f32, /* FetchTexel3Df */ + store_texel_rgb_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb_float16 = { + MESA_FORMAT_RGB_FLOAT16, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 8 * sizeof(GLhalfARB), /* RedBits */ + 8 * sizeof(GLhalfARB), /* GreenBits */ + 8 * sizeof(GLhalfARB), /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 3 * sizeof(GLhalfARB), /* TexelBytes */ + _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_rgb_f16, /* FetchTexel1D */ + fetch_texel_2d_rgb_f16, /* FetchTexel1D */ + fetch_texel_3d_rgb_f16, /* FetchTexel1D */ + fetch_texel_1d_f_rgb_f16, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb_f16, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb_f16, /* FetchTexel3Df */ + store_texel_rgb_f16 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_alpha_float32 = { + MESA_FORMAT_ALPHA_FLOAT32, /* MesaFormat */ + GL_ALPHA, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8 * sizeof(GLfloat), /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1 * sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_alpha_f32, /* FetchTexel1D */ + fetch_texel_2d_alpha_f32, /* FetchTexel1D */ + fetch_texel_3d_alpha_f32, /* FetchTexel1D */ + fetch_texel_1d_f_alpha_f32, /* FetchTexel1Df */ + fetch_texel_2d_f_alpha_f32, /* FetchTexel2Df */ + fetch_texel_3d_f_alpha_f32, /* FetchTexel3Df */ + store_texel_alpha_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_alpha_float16 = { + MESA_FORMAT_ALPHA_FLOAT16, /* MesaFormat */ + GL_ALPHA, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8 * sizeof(GLhalfARB), /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1 * sizeof(GLhalfARB), /* TexelBytes */ + _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_alpha_f16, /* FetchTexel1D */ + fetch_texel_2d_alpha_f16, /* FetchTexel1D */ + fetch_texel_3d_alpha_f16, /* FetchTexel1D */ + fetch_texel_1d_f_alpha_f16, /* FetchTexel1Df */ + fetch_texel_2d_f_alpha_f16, /* FetchTexel2Df */ + fetch_texel_3d_f_alpha_f16, /* FetchTexel3Df */ + store_texel_alpha_f16 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_luminance_float32 = { + MESA_FORMAT_LUMINANCE_FLOAT32, /* MesaFormat */ + GL_LUMINANCE, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 8 * sizeof(GLfloat), /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1 * sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_luminance_f32, /* FetchTexel1D */ + fetch_texel_2d_luminance_f32, /* FetchTexel2D */ + fetch_texel_3d_luminance_f32, /* FetchTexel3D */ + fetch_texel_1d_f_luminance_f32, /* FetchTexel1Df */ + fetch_texel_2d_f_luminance_f32, /* FetchTexel2Df */ + fetch_texel_3d_f_luminance_f32, /* FetchTexel3Df */ + store_texel_luminance_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_luminance_float16 = { + MESA_FORMAT_LUMINANCE_FLOAT16, /* MesaFormat */ + GL_LUMINANCE, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 8 * sizeof(GLhalfARB), /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1 * sizeof(GLhalfARB), /* TexelBytes */ + _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_luminance_f16, /* FetchTexel1D */ + fetch_texel_2d_luminance_f16, /* FetchTexel2D */ + fetch_texel_3d_luminance_f16, /* FetchTexel3D */ + fetch_texel_1d_f_luminance_f16, /* FetchTexel1Df */ + fetch_texel_2d_f_luminance_f16, /* FetchTexel2Df */ + fetch_texel_3d_f_luminance_f16, /* FetchTexel3Df */ + store_texel_luminance_f16 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_luminance_alpha_float32 = { + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, /* MesaFormat */ + GL_LUMINANCE_ALPHA, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8 * sizeof(GLfloat), /* AlphaBits */ + 8 * sizeof(GLfloat), /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2 * sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_rgba_float32, /* StoreTexImageFunc */ + fetch_texel_1d_luminance_alpha_f32, /* FetchTexel1D */ + fetch_texel_2d_luminance_alpha_f32, /* FetchTexel2D */ + fetch_texel_3d_luminance_alpha_f32, /* FetchTexel3D */ + fetch_texel_1d_f_luminance_alpha_f32,/* FetchTexel1Df */ + fetch_texel_2d_f_luminance_alpha_f32,/* FetchTexel2Df */ + fetch_texel_3d_f_luminance_alpha_f32,/* FetchTexel3Df */ + store_texel_luminance_alpha_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_luminance_alpha_float16 = { + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, /* MesaFormat */ + GL_LUMINANCE_ALPHA, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8 * sizeof(GLhalfARB), /* AlphaBits */ + 8 * sizeof(GLhalfARB), /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2 * sizeof(GLhalfARB), /* TexelBytes */ + _mesa_texstore_rgba_float16, /* StoreTexImageFunc */ + fetch_texel_1d_luminance_alpha_f16, /* FetchTexel1D */ + fetch_texel_2d_luminance_alpha_f16, /* FetchTexel2D */ + fetch_texel_3d_luminance_alpha_f16, /* FetchTexel3D */ + fetch_texel_1d_f_luminance_alpha_f16,/* FetchTexel1Df */ + fetch_texel_2d_f_luminance_alpha_f16,/* FetchTexel2Df */ + fetch_texel_3d_f_luminance_alpha_f16,/* FetchTexel3Df */ + store_texel_luminance_alpha_f16 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_intensity_float32 = { + MESA_FORMAT_INTENSITY_FLOAT32, /* MesaFormat */ + GL_INTENSITY, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 8 * sizeof(GLfloat), /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1 * sizeof(GLfloat), /* TexelBytes */ + _mesa_texstore_rgba_float32,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_intensity_f32, /* FetchTexel1D */ + fetch_texel_2d_intensity_f32, /* FetchTexel2D */ + fetch_texel_3d_intensity_f32, /* FetchTexel3D */ + fetch_texel_1d_f_intensity_f32, /* FetchTexel1Df */ + fetch_texel_2d_f_intensity_f32, /* FetchTexel2Df */ + fetch_texel_3d_f_intensity_f32, /* FetchTexel3Df */ + store_texel_intensity_f32 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_intensity_float16 = { + MESA_FORMAT_INTENSITY_FLOAT16, /* MesaFormat */ + GL_INTENSITY, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 8 * sizeof(GLhalfARB), /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1 * sizeof(GLhalfARB), /* TexelBytes */ + _mesa_texstore_rgba_float16,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_intensity_f16, /* FetchTexel1D */ + fetch_texel_2d_intensity_f16, /* FetchTexel2D */ + fetch_texel_3d_intensity_f16, /* FetchTexel3D */ + fetch_texel_1d_f_intensity_f16, /* FetchTexel1Df */ + fetch_texel_2d_f_intensity_f16, /* FetchTexel2Df */ + fetch_texel_3d_f_intensity_f16, /* FetchTexel3Df */ + store_texel_intensity_f16 /* StoreTexel */ +}; + + +/*@}*/ + + +/***************************************************************/ +/** \name Hardware formats */ +/*@{*/ + +const struct gl_texture_format _mesa_texformat_rgba8888 = { + MESA_FORMAT_RGBA8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_rgba8888, /* StoreTexImageFunc */ + fetch_texel_1d_rgba8888, /* FetchTexel1D */ + fetch_texel_2d_rgba8888, /* FetchTexel2D */ + fetch_texel_3d_rgba8888, /* FetchTexel3D */ + fetch_texel_1d_f_rgba8888, /* FetchTexel1Df */ + fetch_texel_2d_f_rgba8888, /* FetchTexel2Df */ + fetch_texel_3d_f_rgba8888, /* FetchTexel3Df */ + store_texel_rgba8888 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgba8888_rev = { + MESA_FORMAT_RGBA8888_REV, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_rgba8888, /* StoreTexImageFunc */ + fetch_texel_1d_rgba8888_rev, /* FetchTexel1D */ + fetch_texel_2d_rgba8888_rev, /* FetchTexel2D */ + fetch_texel_3d_rgba8888_rev, /* FetchTexel3D */ + fetch_texel_1d_f_rgba8888_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_rgba8888_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_rgba8888_rev, /* FetchTexel3Df */ + store_texel_rgba8888_rev /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_argb8888 = { + MESA_FORMAT_ARGB8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_argb8888, /* StoreTexImageFunc */ + fetch_texel_1d_argb8888, /* FetchTexel1D */ + fetch_texel_2d_argb8888, /* FetchTexel2D */ + fetch_texel_3d_argb8888, /* FetchTexel3D */ + fetch_texel_1d_f_argb8888, /* FetchTexel1Df */ + fetch_texel_2d_f_argb8888, /* FetchTexel2Df */ + fetch_texel_3d_f_argb8888, /* FetchTexel3Df */ + store_texel_argb8888 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_argb8888_rev = { + MESA_FORMAT_ARGB8888_REV, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_argb8888, /* StoreTexImageFunc */ + fetch_texel_1d_argb8888_rev, /* FetchTexel1D */ + fetch_texel_2d_argb8888_rev, /* FetchTexel2D */ + fetch_texel_3d_argb8888_rev, /* FetchTexel3D */ + fetch_texel_1d_f_argb8888_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_argb8888_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_argb8888_rev, /* FetchTexel3Df */ + store_texel_argb8888_rev /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb888 = { + MESA_FORMAT_RGB888, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 3, /* TexelBytes */ + _mesa_texstore_rgb888, /* StoreTexImageFunc */ + fetch_texel_1d_rgb888, /* FetchTexel1D */ + fetch_texel_2d_rgb888, /* FetchTexel2D */ + fetch_texel_3d_rgb888, /* FetchTexel3D */ + fetch_texel_1d_f_rgb888, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb888, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb888, /* FetchTexel3Df */ + store_texel_rgb888 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_bgr888 = { + MESA_FORMAT_BGR888, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 3, /* TexelBytes */ + _mesa_texstore_bgr888, /* StoreTexImageFunc */ + fetch_texel_1d_bgr888, /* FetchTexel1D */ + fetch_texel_2d_bgr888, /* FetchTexel2D */ + fetch_texel_3d_bgr888, /* FetchTexel3D */ + fetch_texel_1d_f_bgr888, /* FetchTexel1Df */ + fetch_texel_2d_f_bgr888, /* FetchTexel2Df */ + fetch_texel_3d_f_bgr888, /* FetchTexel3Df */ + store_texel_bgr888 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb565 = { + MESA_FORMAT_RGB565, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 6, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_rgb565, /* StoreTexImageFunc */ + fetch_texel_1d_rgb565, /* FetchTexel1D */ + fetch_texel_2d_rgb565, /* FetchTexel2D */ + fetch_texel_3d_rgb565, /* FetchTexel3D */ + fetch_texel_1d_f_rgb565, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb565, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb565, /* FetchTexel3Df */ + store_texel_rgb565 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb565_rev = { + MESA_FORMAT_RGB565_REV, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 6, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_rgb565, /* StoreTexImageFunc */ + fetch_texel_1d_rgb565_rev, /* FetchTexel1D */ + fetch_texel_2d_rgb565_rev, /* FetchTexel2D */ + fetch_texel_3d_rgb565_rev, /* FetchTexel3D */ + fetch_texel_1d_f_rgb565_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb565_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb565_rev, /* FetchTexel3Df */ + store_texel_rgb565_rev /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_argb4444 = { + MESA_FORMAT_ARGB4444, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 4, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb4444, /* StoreTexImageFunc */ + fetch_texel_1d_argb4444, /* FetchTexel1D */ + fetch_texel_2d_argb4444, /* FetchTexel2D */ + fetch_texel_3d_argb4444, /* FetchTexel3D */ + fetch_texel_1d_f_argb4444, /* FetchTexel1Df */ + fetch_texel_2d_f_argb4444, /* FetchTexel2Df */ + fetch_texel_3d_f_argb4444, /* FetchTexel3Df */ + store_texel_argb4444 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_argb4444_rev = { + MESA_FORMAT_ARGB4444_REV, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 4, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb4444, /* StoreTexImageFunc */ + fetch_texel_1d_argb4444_rev, /* FetchTexel1D */ + fetch_texel_2d_argb4444_rev, /* FetchTexel2D */ + fetch_texel_3d_argb4444_rev, /* FetchTexel3D */ + fetch_texel_1d_f_argb4444_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_argb4444_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_argb4444_rev, /* FetchTexel3Df */ + store_texel_argb4444_rev /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_argb1555 = { + MESA_FORMAT_ARGB1555, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 1, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb1555, /* StoreTexImageFunc */ + fetch_texel_1d_argb1555, /* FetchTexel1D */ + fetch_texel_2d_argb1555, /* FetchTexel2D */ + fetch_texel_3d_argb1555, /* FetchTexel3D */ + fetch_texel_1d_f_argb1555, /* FetchTexel1Df */ + fetch_texel_2d_f_argb1555, /* FetchTexel2Df */ + fetch_texel_3d_f_argb1555, /* FetchTexel3Df */ + store_texel_argb1555 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_argb1555_rev = { + MESA_FORMAT_ARGB1555_REV, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 1, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb1555, /* StoreTexImageFunc */ + fetch_texel_1d_argb1555_rev, /* FetchTexel1D */ + fetch_texel_2d_argb1555_rev, /* FetchTexel2D */ + fetch_texel_3d_argb1555_rev, /* FetchTexel3D */ + fetch_texel_1d_f_argb1555_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_argb1555_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_argb1555_rev, /* FetchTexel3Df */ + store_texel_argb1555_rev /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_al88 = { + MESA_FORMAT_AL88, /* MesaFormat */ + GL_LUMINANCE_ALPHA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_al88, /* StoreTexImageFunc */ + fetch_texel_1d_al88, /* FetchTexel1D */ + fetch_texel_2d_al88, /* FetchTexel2D */ + fetch_texel_3d_al88, /* FetchTexel3D */ + fetch_texel_1d_f_al88, /* FetchTexel1Df */ + fetch_texel_2d_f_al88, /* FetchTexel2Df */ + fetch_texel_3d_f_al88, /* FetchTexel3Df */ + store_texel_al88 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_al88_rev = { + MESA_FORMAT_AL88_REV, /* MesaFormat */ + GL_LUMINANCE_ALPHA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_al88, /* StoreTexImageFunc */ + fetch_texel_1d_al88_rev, /* FetchTexel1D */ + fetch_texel_2d_al88_rev, /* FetchTexel2D */ + fetch_texel_3d_al88_rev, /* FetchTexel3D */ + fetch_texel_1d_f_al88_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_al88_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_al88_rev, /* FetchTexel3Df */ + store_texel_al88_rev /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_rgb332 = { + MESA_FORMAT_RGB332, /* MesaFormat */ + GL_RGB, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 3, /* RedBits */ + 3, /* GreenBits */ + 2, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1, /* TexelBytes */ + _mesa_texstore_rgb332, /* StoreTexImageFunc */ + fetch_texel_1d_rgb332, /* FetchTexel1D */ + fetch_texel_2d_rgb332, /* FetchTexel2D */ + fetch_texel_3d_rgb332, /* FetchTexel3D */ + fetch_texel_1d_f_rgb332, /* FetchTexel1Df */ + fetch_texel_2d_f_rgb332, /* FetchTexel2Df */ + fetch_texel_3d_f_rgb332, /* FetchTexel3Df */ + store_texel_rgb332 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_a8 = { + MESA_FORMAT_A8, /* MesaFormat */ + GL_ALPHA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1, /* TexelBytes */ + _mesa_texstore_a8, /* StoreTexImageFunc */ + fetch_texel_1d_a8, /* FetchTexel1D */ + fetch_texel_2d_a8, /* FetchTexel2D */ + fetch_texel_3d_a8, /* FetchTexel3D */ + fetch_texel_1d_f_a8, /* FetchTexel1Df */ + fetch_texel_2d_f_a8, /* FetchTexel2Df */ + fetch_texel_3d_f_a8, /* FetchTexel3Df */ + store_texel_a8 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_l8 = { + MESA_FORMAT_L8, /* MesaFormat */ + GL_LUMINANCE, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 8, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1, /* TexelBytes */ + _mesa_texstore_a8,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_l8, /* FetchTexel1D */ + fetch_texel_2d_l8, /* FetchTexel2D */ + fetch_texel_3d_l8, /* FetchTexel3D */ + fetch_texel_1d_f_l8, /* FetchTexel1Df */ + fetch_texel_2d_f_l8, /* FetchTexel2Df */ + fetch_texel_3d_f_l8, /* FetchTexel3Df */ + store_texel_l8 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_i8 = { + MESA_FORMAT_I8, /* MesaFormat */ + GL_INTENSITY, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 8, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 1, /* TexelBytes */ + _mesa_texstore_a8,/*yes*/ /* StoreTexImageFunc */ + fetch_texel_1d_i8, /* FetchTexel1D */ + fetch_texel_2d_i8, /* FetchTexel2D */ + fetch_texel_3d_i8, /* FetchTexel3D */ + fetch_texel_1d_f_i8, /* FetchTexel1Df */ + fetch_texel_2d_f_i8, /* FetchTexel2Df */ + fetch_texel_3d_f_i8, /* FetchTexel3Df */ + store_texel_i8 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_ci8 = { + MESA_FORMAT_CI8, /* MesaFormat */ + GL_COLOR_INDEX, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 8, /* IndexBits */ + 0, /* DepthBits */ + 1, /* TexelBytes */ + _mesa_texstore_ci8, /* StoreTexImageFunc */ + fetch_texel_1d_ci8, /* FetchTexel1D */ + fetch_texel_2d_ci8, /* FetchTexel2D */ + fetch_texel_3d_ci8, /* FetchTexel3D */ + fetch_texel_1d_f_ci8, /* FetchTexel1Df */ + fetch_texel_2d_f_ci8, /* FetchTexel2Df */ + fetch_texel_3d_f_ci8, /* FetchTexel3Df */ + store_texel_ci8 /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_ycbcr = { + MESA_FORMAT_YCBCR, /* MesaFormat */ + GL_YCBCR_MESA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_ycbcr, /* StoreTexImageFunc */ + fetch_texel_1d_ycbcr, /* FetchTexel1D */ + fetch_texel_2d_ycbcr, /* FetchTexel2D */ + fetch_texel_3d_ycbcr, /* FetchTexel3D */ + fetch_texel_1d_f_ycbcr, /* FetchTexel1Df */ + fetch_texel_2d_f_ycbcr, /* FetchTexel2Df */ + fetch_texel_3d_f_ycbcr, /* FetchTexel3Df */ + store_texel_ycbcr /* StoreTexel */ +}; + +const struct gl_texture_format _mesa_texformat_ycbcr_rev = { + MESA_FORMAT_YCBCR_REV, /* MesaFormat */ + GL_YCBCR_MESA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_ycbcr, /* StoreTexImageFunc */ + fetch_texel_1d_ycbcr_rev, /* FetchTexel1D */ + fetch_texel_2d_ycbcr_rev, /* FetchTexel2D */ + fetch_texel_3d_ycbcr_rev, /* FetchTexel3D */ + fetch_texel_1d_f_ycbcr_rev, /* FetchTexel1Df */ + fetch_texel_2d_f_ycbcr_rev, /* FetchTexel2Df */ + fetch_texel_3d_f_ycbcr_rev, /* FetchTexel3Df */ + store_texel_ycbcr_rev /* StoreTexel */ +}; + +/*@}*/ + + +/***************************************************************/ +/** \name Null format (useful for proxy textures) */ +/*@{*/ + +const struct gl_texture_format _mesa_null_texformat = { + -1, /* MesaFormat */ + 0, /* BaseFormat */ + GL_NONE, /* DataType */ + 0, /* RedBits */ + 0, /* GreenBits */ + 0, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* TexelBytes */ + NULL, /* StoreTexImageFunc */ + fetch_null_texel, /* FetchTexel1D */ + fetch_null_texel, /* FetchTexel2D */ + fetch_null_texel, /* FetchTexel3D */ + fetch_null_texelf, /* FetchTexel1Df */ + fetch_null_texelf, /* FetchTexel2Df */ + fetch_null_texelf, /* FetchTexel3Df */ + store_null_texel /* StoreTexel */ +}; + +/*@}*/ + + +/** + * Choose an appropriate texture format given the format, type and + * internalFormat parameters passed to glTexImage(). + * + * \param ctx the GL context. + * \param internalFormat user's prefered internal texture format. + * \param format incoming image pixel format. + * \param type incoming image data type. + * + * \return a pointer to a gl_texture_format object which describes the + * choosen texture format, or NULL on failure. + * + * This is called via dd_function_table::ChooseTextureFormat. Hardware drivers + * will typically override this function with a specialized version. + */ +const struct gl_texture_format * +_mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ) +{ + (void) format; + (void) type; + + switch (internalFormat) { + /* RGBA formats */ + case 4: + case GL_RGBA: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return &_mesa_texformat_rgba; + case GL_RGBA8: + return &_mesa_texformat_rgba8888; + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + case GL_RGBA2: + return &_mesa_texformat_argb4444_rev; /* just to test another format*/ + case GL_RGBA4: + return &_mesa_texformat_argb4444; + + /* RGB formats */ + case 3: + case GL_RGB: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return &_mesa_texformat_rgb; + case GL_RGB8: + return &_mesa_texformat_rgb888; + case GL_R3_G3_B2: + return &_mesa_texformat_rgb332; + case GL_RGB4: + return &_mesa_texformat_rgb565_rev; /* just to test another format */ + case GL_RGB5: + return &_mesa_texformat_rgb565; + + /* Alpha formats */ + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA12: + case GL_ALPHA16: + return &_mesa_texformat_alpha; + case GL_ALPHA8: + return &_mesa_texformat_a8; + + /* Luminance formats */ + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return &_mesa_texformat_luminance; + case GL_LUMINANCE8: + return &_mesa_texformat_l8; + + /* Luminance/Alpha formats */ + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return &_mesa_texformat_luminance_alpha; + case GL_LUMINANCE8_ALPHA8: + return &_mesa_texformat_al88; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY12: + case GL_INTENSITY16: + return &_mesa_texformat_intensity; + case GL_INTENSITY8: + return &_mesa_texformat_i8; + + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + case GL_COLOR_INDEX8_EXT: + return &_mesa_texformat_ci8; + + default: + ; /* fallthrough */ + } + + if (ctx->Extensions.SGIX_depth_texture || + ctx->Extensions.ARB_depth_texture) { + switch (internalFormat) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT24_SGIX: + case GL_DEPTH_COMPONENT32_SGIX: + return &_mesa_texformat_depth_component_float32; + case GL_DEPTH_COMPONENT16_SGIX: + return &_mesa_texformat_depth_component16; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ARB_texture_compression) { + switch (internalFormat) { + case GL_COMPRESSED_ALPHA_ARB: + return &_mesa_texformat_alpha; + case GL_COMPRESSED_LUMINANCE_ARB: + return &_mesa_texformat_luminance; + case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: + return &_mesa_texformat_luminance_alpha; + case GL_COMPRESSED_INTENSITY_ARB: + return &_mesa_texformat_intensity; + case GL_COMPRESSED_RGB_ARB: + if (ctx->Extensions.TDFX_texture_compression_FXT1) + return &_mesa_texformat_rgb_fxt1; + else if (ctx->Extensions.EXT_texture_compression_s3tc || + ctx->Extensions.S3_s3tc) + return &_mesa_texformat_rgb_dxt1; + else + return &_mesa_texformat_rgb; + case GL_COMPRESSED_RGBA_ARB: + if (ctx->Extensions.TDFX_texture_compression_FXT1) + return &_mesa_texformat_rgba_fxt1; + else if (ctx->Extensions.EXT_texture_compression_s3tc || + ctx->Extensions.S3_s3tc) + return &_mesa_texformat_rgba_dxt3; /* Not rgba_dxt1, see spec */ + else + return &_mesa_texformat_rgba; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.MESA_ycbcr_texture) { + if (internalFormat == GL_YCBCR_MESA) { + if (type == GL_UNSIGNED_SHORT_8_8_MESA) + return &_mesa_texformat_ycbcr; + else + return &_mesa_texformat_ycbcr_rev; + } + } + + if (ctx->Extensions.TDFX_texture_compression_FXT1) { + switch (internalFormat) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + return &_mesa_texformat_rgb_fxt1; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return &_mesa_texformat_rgba_fxt1; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_texture_compression_s3tc) { + switch (internalFormat) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return &_mesa_texformat_rgb_dxt1; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return &_mesa_texformat_rgba_dxt1; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + return &_mesa_texformat_rgba_dxt3; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return &_mesa_texformat_rgba_dxt5; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.S3_s3tc) { + switch (internalFormat) { + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + return &_mesa_texformat_rgb_dxt1; + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + return &_mesa_texformat_rgba_dxt3; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ARB_texture_float) { + switch (internalFormat) { + case GL_ALPHA16F_ARB: + return &_mesa_texformat_alpha_float16; + case GL_ALPHA32F_ARB: + return &_mesa_texformat_alpha_float32; + case GL_LUMINANCE16F_ARB: + return &_mesa_texformat_luminance_float16; + case GL_LUMINANCE32F_ARB: + return &_mesa_texformat_luminance_float32; + case GL_LUMINANCE_ALPHA16F_ARB: + return &_mesa_texformat_luminance_alpha_float16; + case GL_LUMINANCE_ALPHA32F_ARB: + return &_mesa_texformat_luminance_alpha_float32; + case GL_INTENSITY16F_ARB: + return &_mesa_texformat_intensity_float16; + case GL_INTENSITY32F_ARB: + return &_mesa_texformat_intensity_float32; + case GL_RGB16F_ARB: + return &_mesa_texformat_rgb_float16; + case GL_RGB32F_ARB: + return &_mesa_texformat_rgb_float32; + case GL_RGBA16F_ARB: + return &_mesa_texformat_rgba_float16; + case GL_RGBA32F_ARB: + return &_mesa_texformat_rgba_float32; + default: + ; /* fallthrough */ + } + } + + _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); + return NULL; +} diff --git a/src/mesa/main/texformat.h b/src/mesa/main/texformat.h new file mode 100644 index 00000000000..35522d62189 --- /dev/null +++ b/src/mesa/main/texformat.h @@ -0,0 +1,229 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texformat.h + * Texture formats definitions. + * + * \author Gareth Hughes + */ + + +#ifndef TEXFORMAT_H +#define TEXFORMAT_H + + +#include "mtypes.h" + + +/** + * Mesa internal texture image formats. + * All texture images are stored in one of these formats. + * + * NOTE: when you add a new format, be sure to update the do_row() + * function in texstore.c used for auto mipmap generation. + */ +enum _format { + /** + * \name Hardware-friendly formats. + * + * Drivers can override the default formats and convert texture images to + * one of these as required. The driver's + * dd_function_table::ChooseTextureFormat function will choose one of these + * formats. + * + * \note In the default case, some of these formats will be duplicates of + * the generic formats listed below. However, these formats guarantee their + * internal component sizes, while GLchan may vary between GLubyte, GLushort + * and GLfloat. + */ + /*@{*/ + /* msb <------ TEXEL BITS -----------> lsb */ + /* ---- ---- ---- ---- ---- ---- ---- ---- */ + MESA_FORMAT_RGBA8888, /* RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA */ + MESA_FORMAT_RGBA8888_REV, /* AAAA AAAA BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_ARGB8888, /* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_ARGB8888_REV, /* BBBB BBBB GGGG GGGG RRRR RRRR AAAA AAAA */ + MESA_FORMAT_RGB888, /* RRRR RRRR GGGG GGGG BBBB BBBB */ + MESA_FORMAT_BGR888, /* BBBB BBBB GGGG GGGG RRRR RRRR */ + MESA_FORMAT_RGB565, /* RRRR RGGG GGGB BBBB */ + MESA_FORMAT_RGB565_REV, /* GGGB BBBB RRRR RGGG */ + MESA_FORMAT_ARGB4444, /* AAAA RRRR GGGG BBBB */ + MESA_FORMAT_ARGB4444_REV, /* GGGG BBBB AAAA RRRR */ + MESA_FORMAT_ARGB1555, /* ARRR RRGG GGGB BBBB */ + MESA_FORMAT_ARGB1555_REV, /* GGGB BBBB ARRR RRGG */ + MESA_FORMAT_AL88, /* AAAA AAAA LLLL LLLL */ + MESA_FORMAT_AL88_REV, /* LLLL LLLL AAAA AAAA */ + MESA_FORMAT_RGB332, /* RRRG GGBB */ + MESA_FORMAT_A8, /* AAAA AAAA */ + MESA_FORMAT_L8, /* LLLL LLLL */ + MESA_FORMAT_I8, /* IIII IIII */ + MESA_FORMAT_CI8, /* CCCC CCCC */ + MESA_FORMAT_YCBCR, /* YYYY YYYY UorV UorV */ + MESA_FORMAT_YCBCR_REV, /* UorV UorV YYYY YYYY */ + /*@}*/ + + /** + * \name Compressed texture formats. + */ + /*@{*/ + MESA_FORMAT_RGB_FXT1, + MESA_FORMAT_RGBA_FXT1, + MESA_FORMAT_RGB_DXT1, + MESA_FORMAT_RGBA_DXT1, + MESA_FORMAT_RGBA_DXT3, + MESA_FORMAT_RGBA_DXT5, + /*@}*/ + + /** + * \name Generic GLchan-based formats. + * + * Software-oriented texture formats. Texels are arrays of GLchan + * values so there are no byte order issues. + * + * \note Because these are based on the GLchan data type, one cannot assume + * 8 bits per channel with these formats. If you require GLubyte channels, + * use one of the hardware formats above. + */ + /*@{*/ + MESA_FORMAT_RGBA, + MESA_FORMAT_RGB, + MESA_FORMAT_ALPHA, + MESA_FORMAT_LUMINANCE, + MESA_FORMAT_LUMINANCE_ALPHA, + MESA_FORMAT_INTENSITY, + /*@}*/ + + /** + * Depth textures + */ + /*@{*/ + MESA_FORMAT_DEPTH_COMPONENT_FLOAT32, + MESA_FORMAT_DEPTH_COMPONENT16, + /*@}*/ + + /** + * \name Floating point texture formats. + */ + /*@{*/ + MESA_FORMAT_RGBA_FLOAT32, + MESA_FORMAT_RGBA_FLOAT16, + MESA_FORMAT_RGB_FLOAT32, + MESA_FORMAT_RGB_FLOAT16, + MESA_FORMAT_ALPHA_FLOAT32, + MESA_FORMAT_ALPHA_FLOAT16, + MESA_FORMAT_LUMINANCE_FLOAT32, + MESA_FORMAT_LUMINANCE_FLOAT16, + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, + MESA_FORMAT_INTENSITY_FLOAT32, + MESA_FORMAT_INTENSITY_FLOAT16 + /*@}*/ +}; + + +/** GLchan-valued formats */ +/*@{*/ +extern const struct gl_texture_format _mesa_texformat_rgba; +extern const struct gl_texture_format _mesa_texformat_rgb; +extern const struct gl_texture_format _mesa_texformat_alpha; +extern const struct gl_texture_format _mesa_texformat_luminance; +extern const struct gl_texture_format _mesa_texformat_luminance_alpha; +extern const struct gl_texture_format _mesa_texformat_intensity; +/*@}*/ + +/** Depth textures */ +/*@{*/ +extern const struct gl_texture_format _mesa_texformat_depth_component_float32; +extern const struct gl_texture_format _mesa_texformat_depth_component16; +/*@}*/ + +/** Floating point texture formats */ +/*@{*/ +extern const struct gl_texture_format _mesa_texformat_rgba_float32; +extern const struct gl_texture_format _mesa_texformat_rgba_float16; +extern const struct gl_texture_format _mesa_texformat_rgb_float32; +extern const struct gl_texture_format _mesa_texformat_rgb_float16; +extern const struct gl_texture_format _mesa_texformat_alpha_float32; +extern const struct gl_texture_format _mesa_texformat_alpha_float16; +extern const struct gl_texture_format _mesa_texformat_luminance_float32; +extern const struct gl_texture_format _mesa_texformat_luminance_float16; +extern const struct gl_texture_format _mesa_texformat_luminance_alpha_float32; +extern const struct gl_texture_format _mesa_texformat_luminance_alpha_float16; +extern const struct gl_texture_format _mesa_texformat_intensity_float32; +extern const struct gl_texture_format _mesa_texformat_intensity_float16; +/*@}*/ + +/** \name Assorted hardware-friendly formats */ +/*@{*/ +extern const struct gl_texture_format _mesa_texformat_rgba8888; +extern const struct gl_texture_format _mesa_texformat_rgba8888_rev; +extern const struct gl_texture_format _mesa_texformat_argb8888; +extern const struct gl_texture_format _mesa_texformat_argb8888_rev; +extern const struct gl_texture_format _mesa_texformat_rgb888; +extern const struct gl_texture_format _mesa_texformat_bgr888; +extern const struct gl_texture_format _mesa_texformat_rgb565; +extern const struct gl_texture_format _mesa_texformat_rgb565_rev; +extern const struct gl_texture_format _mesa_texformat_argb4444; +extern const struct gl_texture_format _mesa_texformat_argb4444_rev; +extern const struct gl_texture_format _mesa_texformat_argb1555; +extern const struct gl_texture_format _mesa_texformat_argb1555_rev; +extern const struct gl_texture_format _mesa_texformat_al88; +extern const struct gl_texture_format _mesa_texformat_al88_rev; +extern const struct gl_texture_format _mesa_texformat_rgb332; +extern const struct gl_texture_format _mesa_texformat_a8; +extern const struct gl_texture_format _mesa_texformat_l8; +extern const struct gl_texture_format _mesa_texformat_i8; +extern const struct gl_texture_format _mesa_texformat_ci8; + +/*@}*/ + +/** \name YCbCr formats */ +/*@{*/ +extern const struct gl_texture_format _mesa_texformat_ycbcr; +extern const struct gl_texture_format _mesa_texformat_ycbcr_rev; +/*@}*/ + +/** \name Compressed formats */ +/*@{*/ +extern const struct gl_texture_format _mesa_texformat_rgb_fxt1; +extern const struct gl_texture_format _mesa_texformat_rgba_fxt1; +extern const struct gl_texture_format _mesa_texformat_rgb_dxt1; +extern const struct gl_texture_format _mesa_texformat_rgba_dxt1; +extern const struct gl_texture_format _mesa_texformat_rgba_dxt3; +extern const struct gl_texture_format _mesa_texformat_rgba_dxt5; +/*@}*/ + +/** \name The null format */ +/*@{*/ +extern const struct gl_texture_format _mesa_null_texformat; +/*@}*/ + + +extern const struct gl_texture_format * +_mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ); + +#endif diff --git a/src/mesa/main/texformat_tmp.h b/src/mesa/main/texformat_tmp.h new file mode 100644 index 00000000000..22531d826f6 --- /dev/null +++ b/src/mesa/main/texformat_tmp.h @@ -0,0 +1,1762 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3.2 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texformat_tmp.h + * Texel fetch functions template. + * + * This template file is used by texformat.c to generate texel fetch functions + * for 1-D, 2-D and 3-D texture images. + * + * It should be expanded by defining \p DIM as the number texture dimensions + * (1, 2 or 3). According to the value of \p DIM a series of macros is defined + * for the texel lookup in the gl_texture_image::Data. + * + * \sa texformat.c and FetchTexel. + * + * \author Gareth Hughes + * \author Brian Paul + */ + + +#if DIM == 1 + +#define CHAN_ADDR( t, i, j, k, sz ) \ + ((void) (j), (void) (k), \ + ((GLchan *)(t)->Data + (i) * (sz))) +#define UBYTE_ADDR( t, i, j, k, sz ) \ + ((void) (j), (void) (k), \ + ((GLubyte *)(t)->Data + (i) * (sz))) +#define USHORT_ADDR( t, i, j, k ) \ + ((void) (j), (void) (k), \ + ((GLushort *)(t)->Data + (i))) +#define UINT_ADDR( t, i, j, k ) \ + ((void) (j), (void) (k), \ + ((GLuint *)(t)->Data + (i))) +#define FLOAT_ADDR( t, i, j, k, sz ) \ + ((void) (j), (void) (k), \ + ((GLfloat *)(t)->Data + (i) * (sz))) +#define HALF_ADDR( t, i, j, k, sz ) \ + ((void) (j), (void) (k), \ + ((GLhalfARB *)(t)->Data + (i) * (sz))) + +#define FETCH(x) fetch_texel_1d_##x + +#elif DIM == 2 + +#define CHAN_ADDR( t, i, j, k, sz ) \ + ((void) (k), \ + ((GLchan *)(t)->Data + ((t)->RowStride * (j) + (i)) * (sz))) +#define UBYTE_ADDR( t, i, j, k, sz ) \ + ((void) (k), \ + ((GLubyte *)(t)->Data + ((t)->RowStride * (j) + (i)) * (sz))) +#define USHORT_ADDR( t, i, j, k ) \ + ((void) (k), \ + ((GLushort *)(t)->Data + ((t)->RowStride * (j) + (i)))) +#define UINT_ADDR( t, i, j, k ) \ + ((void) (k), \ + ((GLuint *)(t)->Data + ((t)->RowStride * (j) + (i)))) +#define FLOAT_ADDR( t, i, j, k, sz ) \ + ((void) (k), \ + ((GLfloat *)(t)->Data + ((t)->RowStride * (j) + (i)) * (sz))) +#define HALF_ADDR( t, i, j, k, sz ) \ + ((void) (k), \ + ((GLhalfARB *)(t)->Data + ((t)->RowStride * (j) + (i)) * (sz))) + +#define FETCH(x) fetch_texel_2d_##x + +#elif DIM == 3 + +#define CHAN_ADDR( t, i, j, k, sz ) \ + (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->RowStride + (i)) * (sz) +#define UBYTE_ADDR( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->RowStride + (i)) * (sz)) +#define USHORT_ADDR( t, i, j, k ) \ + ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->RowStride + (i))) +#define UINT_ADDR( t, i, j, k ) \ + ((GLuint *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->RowStride + (i))) +#define FLOAT_ADDR( t, i, j, k, sz ) \ + ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->RowStride + (i)) * (sz)) +#define HALF_ADDR( t, i, j, k, sz ) \ + ((GLhalfARB *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->RowStride + (i)) * (sz)) + +#define FETCH(x) fetch_texel_3d_##x + +#else +#error illegal number of texture dimensions +#endif + + +/* MESA_FORMAT_RGBA **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA texture, returning 4 GLchans */ +static void FETCH(rgba)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 4 ); + COPY_CHAN4( texel, src ); +} + +/* Fetch texel from 1D, 2D or 3D RGBA texture, returning 4 GLfloats */ +static void FETCH(f_rgba)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = CHAN_TO_FLOAT(src[3]); +} + +#if DIM == 3 +/* Store a GLchan RGBA texel */ +static void store_texel_rgba(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLchan *rgba = (const GLchan *) texel; + GLchan *dst = CHAN_ADDR(texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + +/* MESA_FORMAT_RGB ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGB texture, returning 4 GLchans */ +static void FETCH(rgb)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D RGB texture, returning 4 GLfloats */ +static void FETCH(f_rgb)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLchan *rgba = (const GLchan *) texel; + GLchan *dst = CHAN_ADDR(texImage, i, j, k, 3); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; +} +#endif + +/* MESA_FORMAT_ALPHA *********************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA texture, returning 4 GLchans */ +static void FETCH(alpha)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0; + texel[ACOMP] = src[0]; +} + +/* Fetch texel from 1D, 2D or 3D ALPHA texture, returning 4 GLfloats */ +static void FETCH(f_alpha)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0; + texel[ACOMP] = CHAN_TO_FLOAT(src[0]); +} + +#if DIM == 3 +static void store_texel_alpha(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLchan *rgba = (const GLchan *) texel; + GLchan *dst = CHAN_ADDR(texImage, i, j, k, 1); + dst[0] = rgba[ACOMP]; +} +#endif + +/* MESA_FORMAT_LUMINANCE *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMIN texture, returning 4 GLchans */ +static void FETCH(luminance)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D LUMIN texture, returning 4 GLfloats */ +static void FETCH(f_luminance)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = CHAN_TO_FLOAT(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLchan *rgba = (const GLchan *) texel; + GLchan *dst = CHAN_ADDR(texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + +/* MESA_FORMAT_LUMINANCE_ALPHA ***********************************************/ + +/* Fetch texel from 1D, 2D or 3D L_A texture, returning 4 GLchans */ +static void FETCH(luminance_alpha)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 2 ); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[0]; + texel[BCOMP] = src[0]; + texel[ACOMP] = src[1]; +} + +/* Fetch texel from 1D, 2D or 3D L_A texture, returning 4 GLfloats */ +static void FETCH(f_luminance_alpha)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 2 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = CHAN_TO_FLOAT(src[0]); + texel[ACOMP] = CHAN_TO_FLOAT(src[1]); +} + +#if DIM == 3 +static void store_texel_luminance_alpha(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLchan *rgba = (const GLchan *) texel; + GLchan *dst = CHAN_ADDR(texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + +/* MESA_FORMAT_INTENSITY *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D INT. texture, returning 4 GLchans */ +static void FETCH(intensity)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[0]; + texel[BCOMP] = src[0]; + texel[ACOMP] = src[0]; +} + +/* Fetch texel from 1D, 2D or 3D INT. texture, returning 4 GLfloats */ +static void FETCH(f_intensity)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = CHAN_TO_FLOAT(src[0]); +} + +#if DIM == 3 +static void store_texel_intensity(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLchan *rgba = (const GLchan *) texel; + GLchan *dst = CHAN_ADDR(texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_DEPTH_COMPONENT_F32 *******************************************/ + +/* Fetch depth texel from 1D, 2D or 3D float32 DEPTH texture, + * returning 1 GLfloat. + * Note: no GLchan version of this function. + */ +static void FETCH(f_depth_component_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + texel[0] = src[0]; +} + +#if DIM == 3 +static void store_texel_depth_component_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 1); + dst[0] = *depth; +} +#endif + + +/* MESA_FORMAT_DEPTH_COMPONENT16 *********************************************/ + +/* Fetch depth texel from 1D, 2D or 3D float32 DEPTH texture, + * returning 1 GLfloat. + * Note: no GLchan version of this function. + */ +static void FETCH(f_depth_component16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + texel[0] = src[0] * (1.0F / 65535.0F); +} + +#if DIM == 3 +static void store_texel_depth_component16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *depth = (const GLushort *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + dst[0] = *depth; +} +#endif + + +/* MESA_FORMAT_RGBA_F32 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLchans. + */ +static void FETCH(rgba_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 4 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], src[0]); + UNCLAMPED_FLOAT_TO_CHAN(texel[GCOMP], src[1]); + UNCLAMPED_FLOAT_TO_CHAN(texel[BCOMP], src[2]); + UNCLAMPED_FLOAT_TO_CHAN(texel[ACOMP], src[3]); +} + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLfloats. + */ +static void FETCH(f_rgba_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 4 ); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = src[3]; +} + +#if DIM == 3 +static void store_texel_rgba_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 1); + dst[0] = depth[RCOMP]; + dst[1] = depth[GCOMP]; + dst[2] = depth[BCOMP]; + dst[3] = depth[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_F16 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture, + * returning 4 GLchans. + */ +static void FETCH(rgba_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 4 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], _mesa_half_to_float(src[0])); + UNCLAMPED_FLOAT_TO_CHAN(texel[GCOMP], _mesa_half_to_float(src[1])); + UNCLAMPED_FLOAT_TO_CHAN(texel[BCOMP], _mesa_half_to_float(src[2])); + UNCLAMPED_FLOAT_TO_CHAN(texel[ACOMP], _mesa_half_to_float(src[3])); +} + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgba_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 4 ); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = _mesa_half_to_float(src[2]); + texel[ACOMP] = _mesa_half_to_float(src[3]); +} + +#if DIM == 3 +static void store_texel_rgba_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLhalfARB *dst = HALF_ADDR(texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(*depth); +} +#endif + +/* MESA_FORMAT_RGB_F32 *******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture, + * returning 4 GLchans. + */ +static void FETCH(rgb_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 3 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], src[0]); + UNCLAMPED_FLOAT_TO_CHAN(texel[GCOMP], src[1]); + UNCLAMPED_FLOAT_TO_CHAN(texel[BCOMP], src[2]); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgb_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 1); + dst[0] = *depth; +} +#endif + + +/* MESA_FORAMT_RGB_F16 *******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture, + * returning 4 GLchans. + */ +static void FETCH(rgb_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 3 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], _mesa_half_to_float(src[0])); + UNCLAMPED_FLOAT_TO_CHAN(texel[GCOMP], _mesa_half_to_float(src[1])); + UNCLAMPED_FLOAT_TO_CHAN(texel[BCOMP], _mesa_half_to_float(src[2])); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgb_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = _mesa_half_to_float(src[2]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLhalfARB *dst = HALF_ADDR(texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(*depth); +} +#endif + + +/* MESA_FORMAT_ALPHA_F32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture, + * returning 4 GLchans. + */ +static void FETCH(alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0; + UNCLAMPED_FLOAT_TO_CHAN(texel[ACOMP], src[0]); +} + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = src[0]; +} + +#if DIM == 3 +static void store_texel_alpha_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 1); + dst[0] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_ALPHA_F32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture, + * returning 4 GLchans. + */ +static void FETCH(alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0; + UNCLAMPED_FLOAT_TO_CHAN(texel[ACOMP], _mesa_half_to_float(src[0])); +} + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = _mesa_half_to_float(src[0]); +} + +#if DIM == 3 +static void store_texel_alpha_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = HALF_ADDR(texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_LUMINANCE_F32 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture, + * returning 4 GLchans. + */ +static void FETCH(luminance_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], src[0]); + texel[GCOMP] = + texel[BCOMP] = texel[RCOMP]; + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_LUMINANCE_F16 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture, + * returning 4 GLchans. + */ +static void FETCH(luminance_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 1 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], _mesa_half_to_float(src[0])); + texel[GCOMP] = + texel[BCOMP] = texel[RCOMP]; + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = _mesa_half_to_float(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = HALF_ADDR(texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_LUMINANCE_ALPHA_F32 *******************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture, + * returning 4 GLchans. + */ +static void FETCH(luminance_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 2 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], src[0]); + texel[GCOMP] = + texel[BCOMP] = texel[RCOMP]; + UNCLAMPED_FLOAT_TO_CHAN(texel[ACOMP], src[1]); +} + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 2 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = src[1]; +} + +#if DIM == 3 +static void store_texel_luminance_alpha_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_LUMINANCE_ALPHA_F16 *******************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(luminance_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 2 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], _mesa_half_to_float(src[0])); + texel[GCOMP] = + texel[BCOMP] = texel[RCOMP]; + UNCLAMPED_FLOAT_TO_CHAN(texel[ACOMP], _mesa_half_to_float(src[1])); +} + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 2 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = _mesa_half_to_float(src[0]); + texel[ACOMP] = _mesa_half_to_float(src[1]); +} + +#if DIM == 3 +static void store_texel_luminance_alpha_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = HALF_ADDR(texImage, i, j, k, 2); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); + dst[1] = _mesa_float_to_half(rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_INTENSITY_F32 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture, + * returning 4 GLchans. + */ +static void FETCH(intensity_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], src[0]); + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = texel[RCOMP]; +} + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_intensity_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = FLOAT_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = src[0]; +} + +#if DIM == 3 +static void store_texel_intensity_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = FLOAT_ADDR(texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_INTENSITY_F16 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture, + * returning 4 GLchans. + */ +static void FETCH(intensity_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 1 ); + UNCLAMPED_FLOAT_TO_CHAN(texel[RCOMP], _mesa_half_to_float(src[0])); + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = texel[RCOMP]; +} + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_intensity_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = HALF_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = _mesa_half_to_float(src[0]); +} + +#if DIM == 3 +static void store_texel_intensity_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = HALF_ADDR(texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + + + +/* + * Begin Hardware formats + */ + +/* MESA_FORMAT_RGBA8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLchans */ +static void FETCH(rgba8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_CHAN( (s >> 24) ); + texel[GCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff ); + texel[ACOMP] = UBYTE_TO_CHAN( (s ) & 0xff ); +} + +/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */ +static void FETCH(f_rgba8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); +} + +#if DIM == 3 +static void store_texel_rgba8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = UINT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RGBA888_REV ***************************************************/ + +/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */ +static void FETCH(rgba8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_CHAN( (s ) & 0xff ); + texel[GCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff ); + texel[ACOMP] = UBYTE_TO_CHAN( (s >> 24) ); +} + +/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLfloats */ +static void FETCH(f_rgba8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_rgba8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = UINT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */ +static void FETCH(argb8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff ); + texel[GCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_CHAN( (s ) & 0xff ); + texel[ACOMP] = UBYTE_TO_CHAN( (s >> 24) ); +} + +/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLfloats */ +static void FETCH(f_argb8888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_argb8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = UINT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB8888_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLchans */ +static void FETCH(argb8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_CHAN( (s >> 8) & 0xff ); + texel[GCOMP] = UBYTE_TO_CHAN( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_CHAN( (s >> 24) ); + texel[ACOMP] = UBYTE_TO_CHAN( (s ) & 0xff ); +} + +/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */ +static void FETCH(f_argb8888_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint s = *UINT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); +} + +#if DIM == 3 +static void store_texel_argb8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = UINT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_RGB888 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */ +static void FETCH(rgb888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = UBYTE_TO_CHAN( src[2] ); + texel[GCOMP] = UBYTE_TO_CHAN( src[1] ); + texel[BCOMP] = UBYTE_TO_CHAN( src[0] ); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLfloats */ +static void FETCH(f_rgb888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = UBYTE_TO_FLOAT( src[2] ); + texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); + texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 3); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; +} +#endif + + +/* MESA_FORMAT_BGR888 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */ +static void FETCH(bgr888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = UBYTE_TO_CHAN( src[0] ); + texel[GCOMP] = UBYTE_TO_CHAN( src[1] ); + texel[BCOMP] = UBYTE_TO_CHAN( src[2] ); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLfloats */ +static void FETCH(f_bgr888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 3 ); + texel[RCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); + texel[BCOMP] = UBYTE_TO_FLOAT( src[2] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_bgr888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 3); + dst[0] = rgba[BCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[RCOMP]; +} +#endif + + +/* use color expansion like (g << 2) | (g >> 4) (does somewhat random rounding) + instead of slow (g << 2) * 255 / 252 (always rounds down) */ + +/* MESA_FORMAT_RGB565 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */ +static void FETCH(rgb565)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = *src; + texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) ); + texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) ); + texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLfloats */ +static void FETCH(f_rgb565)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = *src; + texel[RCOMP] = ((s >> 8) & 0xf8) * (1.0F / 248.0F); + texel[GCOMP] = ((s >> 3) & 0xfc) * (1.0F / 252.0F); + texel[BCOMP] = ((s << 3) & 0xf8) * (1.0F / 248.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb565(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_565(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_RGB565_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */ +static void FETCH(rgb565_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */ + texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) ); + texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) ); + texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLfloats */ +static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */ + texel[RCOMP] = ((s >> 8) & 0xf8) * (1.0F / 248.0F); + texel[GCOMP] = ((s >> 3) & 0xfc) * (1.0F / 252.0F); + texel[BCOMP] = ((s << 3) & 0xf8) * (1.0F / 248.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb565_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_565(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB4444 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */ +static void FETCH(argb4444)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = *src; + texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) | ((s >> 4) & 0xf0) ); + texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) | ((s ) & 0xf0) ); + texel[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) | ((s << 4) & 0xf0) ); + texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 12) & 0xf) | ((s >> 8) & 0xf0) ); +} + +/* Fetch texel from 1D, 2D or 3D argb4444 texture, return 4 GLfloats */ +static void FETCH(f_argb4444)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = *src; + texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); + texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); + texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_argb4444(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_4444(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB4444_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */ +static void FETCH(argb4444_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort s = *USHORT_ADDR( texImage, i, j, k ); + texel[RCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) | ((s << 4) & 0xf0) ); + texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 12) & 0xf) | ((s >> 8) & 0xf0) ); + texel[BCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) | ((s >> 4) & 0xf0) ); + texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) | ((s ) & 0xf0) ); +} + +/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLfloats */ +static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *USHORT_ADDR( texImage, i, j, k ); + texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); + texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); + texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_argb4444_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB1555 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ +static void FETCH(argb1555)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = *src; + texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) ); + texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) ); + texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 15) & 0x01) * 255 ); +} + +/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLfloats */ +static void FETCH(f_argb1555)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = *src; + texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F); + texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = ((s >> 15) & 0x01); +} + +#if DIM == 3 +static void store_texel_argb1555(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_1555(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB1555_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */ +static void FETCH(argb1555_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */ + texel[RCOMP] = UBYTE_TO_CHAN( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) ); + texel[GCOMP] = UBYTE_TO_CHAN( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) ); + texel[BCOMP] = UBYTE_TO_CHAN( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = UBYTE_TO_CHAN( ((s >> 15) & 0x01) * 255 ); +} + +/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLfloats */ +static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_ADDR( texImage, i, j, k ); + const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */ + texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F); + texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = ((s >> 15) & 0x01); +} + +#if DIM == 3 +static void store_texel_argb1555_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_1555_REV(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_AL88 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */ +static void FETCH(al88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort s = *USHORT_ADDR( texImage, i, j, k ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_CHAN( s & 0xff ); + texel[ACOMP] = UBYTE_TO_CHAN( s >> 8 ); +} + +/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLfloats */ +static void FETCH(f_al88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *USHORT_ADDR( texImage, i, j, k ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 ); +} + +#if DIM == 3 +static void store_texel_al88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_88(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL88_REV ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */ +static void FETCH(al88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort s = *USHORT_ADDR( texImage, i, j, k ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_CHAN( s >> 8 ); + texel[ACOMP] = UBYTE_TO_CHAN( s & 0xff ); +} + +/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLfloats */ +static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *USHORT_ADDR( texImage, i, j, k ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff ); +} + +#if DIM == 3 +static void store_texel_al88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = USHORT_ADDR(texImage, i, j, k); + *dst = PACK_COLOR_88(rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RGB332 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */ +static void FETCH(rgb332)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + static const GLubyte lut2to8[4] = {0, 85, 170, 255}; + static const GLubyte lut3to8[8] = {0, 36, 73, 109, 146, 182, 219, 255}; + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + const GLubyte s = *src; + texel[RCOMP] = UBYTE_TO_CHAN( lut3to8[(s >> 5) & 0x7] ); + texel[GCOMP] = UBYTE_TO_CHAN( lut3to8[(s >> 2) & 0x7] ); + texel[BCOMP] = UBYTE_TO_CHAN( lut2to8[(s ) & 0x3] ); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLfloats */ +static void FETCH(f_rgb332)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + const GLubyte s = *src; + texel[RCOMP] = ((s ) & 0xe0) * (1.0F / 224.0F); + texel[GCOMP] = ((s << 3) & 0xe0) * (1.0F / 224.0F); + texel[BCOMP] = ((s << 6) & 0xc0) * (1.0F / 192.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb332(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 1); + *dst = PACK_COLOR_332(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_A8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ +static void FETCH(a8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0; + texel[ACOMP] = UBYTE_TO_CHAN( src[0] ); +} + +/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLfloats */ +static void FETCH(f_a8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0; + texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_a8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_L8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */ +static void FETCH(l8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_CHAN( src[0] ); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLfloats */ +static void FETCH(f_l8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_l8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_I8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */ +static void FETCH(i8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = UBYTE_TO_CHAN( src[0] ); +} + +/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLfloats */ +static void FETCH(f_i8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_i8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_CI8 ***********************************************************/ + +/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a + * color table, and return 4 GLchans. + */ +static void FETCH(ci8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLubyte *src = UBYTE_ADDR( texImage, i, j, k, 1 ); + const struct gl_color_table *palette; + const GLchan *table; + GLuint index; + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Texture.SharedPalette) { + palette = &ctx->Texture.Palette; + } + else { + palette = &texImage->TexObject->Palette; + } + if (palette->Size == 0) + return; /* undefined results */ + ASSERT(palette->Type != GL_FLOAT); + table = (const GLchan *) palette->Table; + + /* Mask the index against size of palette to avoid going out of bounds */ + index = (*src) & (palette->Size - 1); + + switch (palette->Format) { + case GL_ALPHA: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0; + texel[ACOMP] = table[index]; + return; + case GL_LUMINANCE: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = table[index]; + texel[ACOMP] = CHAN_MAX; + break; + case GL_INTENSITY: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = table[index]; + return; + case GL_LUMINANCE_ALPHA: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = table[index * 2 + 0]; + texel[ACOMP] = table[index * 2 + 1]; + return; + case GL_RGB: + texel[RCOMP] = table[index * 3 + 0]; + texel[GCOMP] = table[index * 3 + 1]; + texel[BCOMP] = table[index * 3 + 2]; + texel[ACOMP] = CHAN_MAX; + return; + case GL_RGBA: + texel[RCOMP] = table[index * 4 + 0]; + texel[GCOMP] = table[index * 4 + 1]; + texel[BCOMP] = table[index * 4 + 2]; + texel[ACOMP] = table[index * 4 + 3]; + return; + default: + _mesa_problem(ctx, "Bad palette format in palette_sample"); + } +} + + +/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a + * color table, and return 4 GLfloats. + */ +static void FETCH(f_ci8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + GLchan rgba[4]; + /* Sample as GLchan */ + FETCH(ci8)(texImage, i, j, k, rgba); + /* and return as floats */ + texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); + texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); + texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); + texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]); +} + +#if DIM == 3 +static void store_texel_ci8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *index = (const GLubyte *) texel; + GLubyte *dst = UBYTE_ADDR(texImage, i, j, k, 1); + *dst = *index; +} +#endif + + +/* MESA_FORMAT_YCBCR *********************************************************/ + +/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLchans */ +/* We convert YCbCr to RGB here */ +/* XXX this may break if GLchan != GLubyte */ +static void FETCH(ycbcr)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src0 = USHORT_ADDR( texImage, (i & ~1), j, k ); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */ + const GLubyte cb = *src0 & 0xff; /* chroma U */ + const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */ + const GLubyte cr = *src1 & 0xff; /* chroma V */ + GLint r, g, b; + if (i & 1) { + /* odd pixel: use y1,cr,cb */ + r = (GLint) (1.164 * (y1-16) + 1.596 * (cr-128)); + g = (GLint) (1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (GLint) (1.164 * (y1-16) + 2.018 * (cb-128)); + } + else { + /* even pixel: use y0,cr,cb */ + r = (GLint) (1.164 * (y0-16) + 1.596 * (cr-128)); + g = (GLint) (1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (GLint) (1.164 * (y0-16) + 2.018 * (cb-128)); + } + texel[RCOMP] = CLAMP(r, 0, CHAN_MAX); + texel[GCOMP] = CLAMP(g, 0, CHAN_MAX); + texel[BCOMP] = CLAMP(b, 0, CHAN_MAX); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats */ +/* We convert YCbCr to RGB here */ +static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src0 = USHORT_ADDR( texImage, (i & ~1), j, k ); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */ + const GLubyte cb = *src0 & 0xff; /* chroma U */ + const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */ + const GLubyte cr = *src1 & 0xff; /* chroma V */ + GLfloat r, g, b; + if (i & 1) { + /* odd pixel: use y1,cr,cb */ + r = (1.164 * (y1-16) + 1.596 * (cr-128)); + g = (1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (1.164 * (y1-16) + 2.018 * (cb-128)); + } + else { + /* even pixel: use y0,cr,cb */ + r = (1.164 * (y0-16) + 1.596 * (cr-128)); + g = (1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (1.164 * (y0-16) + 2.018 * (cb-128)); + } + /* XXX remove / 255 here by tweaking arithmetic above */ + r /= 255.0; + g /= 255.0; + b /= 255.0; + /* XXX should we really clamp??? */ + texel[RCOMP] = CLAMP(r, 0.0, 1.0); + texel[GCOMP] = CLAMP(g, 0.0, 1.0); + texel[BCOMP] = CLAMP(b, 0.0, 1.0); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_ycbcr(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* XXX to do */ +} +#endif + + +/* MESA_FORMAT_YCBCR_REV *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLchans */ +/* We convert YCbCr to RGB here */ +/* XXX this may break if GLchan != GLubyte */ +static void FETCH(ycbcr_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src0 = USHORT_ADDR( texImage, (i & ~1), j, k ); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = *src0 & 0xff; /* luminance */ + const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */ + const GLubyte y1 = *src1 & 0xff; /* luminance */ + const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */ + GLint r, g, b; + if (i & 1) { + /* odd pixel: use y1,cr,cb */ + r = (GLint) (1.164 * (y1-16) + 1.596 * (cr-128)); + g = (GLint) (1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (GLint) (1.164 * (y1-16) + 2.018 * (cb-128)); + } + else { + /* even pixel: use y0,cr,cb */ + r = (GLint) (1.164 * (y0-16) + 1.596 * (cr-128)); + g = (GLint) (1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (GLint) (1.164 * (y0-16) + 2.018 * (cb-128)); + } + texel[RCOMP] = CLAMP(r, 0, CHAN_MAX); + texel[GCOMP] = CLAMP(g, 0, CHAN_MAX); + texel[BCOMP] = CLAMP(b, 0, CHAN_MAX); + texel[ACOMP] = CHAN_MAX; +} + +/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats */ +/* We convert YCbCr to RGB here */ +static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src0 = USHORT_ADDR( texImage, (i & ~1), j, k ); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = *src0 & 0xff; /* luminance */ + const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */ + const GLubyte y1 = *src1 & 0xff; /* luminance */ + const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */ + GLfloat r, g, b; + if (i & 1) { + /* odd pixel: use y1,cr,cb */ + r = (1.164 * (y1-16) + 1.596 * (cr-128)); + g = (1.164 * (y1-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (1.164 * (y1-16) + 2.018 * (cb-128)); + } + else { + /* even pixel: use y0,cr,cb */ + r = (1.164 * (y0-16) + 1.596 * (cr-128)); + g = (1.164 * (y0-16) - 0.813 * (cr-128) - 0.391 * (cb-128)); + b = (1.164 * (y0-16) + 2.018 * (cb-128)); + } + /* XXX remove / 255 here by tweaking arithmetic above */ + r /= 255.0; + g /= 255.0; + b /= 255.0; + /* XXX should we really clamp??? */ + texel[RCOMP] = CLAMP(r, 0.0, 1.0); + texel[GCOMP] = CLAMP(g, 0.0, 1.0); + texel[BCOMP] = CLAMP(b, 0.0, 1.0); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_ycbcr_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* XXX to do */ +} +#endif + + + +#undef CHAN_ADDR +#undef UBYTE_ADDR +#undef USHORT_ADDR +#undef UINT_ADDR +#undef FLOAT_ADDR +#undef HALF_ADDR +#undef FETCH +#undef DIM diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c new file mode 100644 index 00000000000..d4d023acda3 --- /dev/null +++ b/src/mesa/main/teximage.c @@ -0,0 +1,3330 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file teximage.c + * Texture images manipulation functions. + * + * \note Mesa's native texture data type is GLchan. Native formats are + * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, and + * GL_COLOR_INDEX. + * + * \note Device drivers are free to implement any internal format they want. + */ + + +#include "glheader.h" +#include "bufferobj.h" +#include "context.h" +#include "convolve.h" +#include "image.h" +#include "imports.h" +#include "macros.h" +#include "state.h" +#include "texcompress.h" +#include "texformat.h" +#include "teximage.h" +#include "texstate.h" +#include "texstore.h" +#include "mtypes.h" + + +/** + * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE + * elsewhere. + */ +void * +_mesa_alloc_texmemory(GLsizei bytes) +{ + return _mesa_align_malloc(bytes, 512); +} + + +/** + * Free texture memory allocated with _mesa_alloc_texmemory() + */ +void +_mesa_free_texmemory(void *m) +{ + _mesa_align_free(m); +} + + + + +#if 0 +static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) +{ +#if CHAN_TYPE == GL_FLOAT + _mesa_problem(NULL, "PrintTexture doesn't support float channels"); +#else + GLuint i, j, c; + const GLchan *data = (const GLchan *) img->Data; + + if (!data) { + _mesa_printf("No texture data\n"); + return; + } + + switch (img->Format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_COLOR_INDEX: + c = 1; + break; + case GL_LUMINANCE_ALPHA: + c = 2; + break; + case GL_RGB: + c = 3; + break; + case GL_RGBA: + c = 4; + break; + default: + _mesa_problem(NULL, "error in PrintTexture\n"); + return; + } + + for (i = 0; i < img->Height; i++) { + for (j = 0; j < img->Width; j++) { + if (c==1) + _mesa_printf("%02x ", data[0]); + else if (c==2) + _mesa_printf("%02x%02x ", data[0], data[1]); + else if (c==3) + _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]); + else if (c==4) + _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); + data += (img->RowStride - img->Width) * c; + } + _mesa_printf("\n"); + } +#endif +} +#endif + + +/* + * Compute floor(log_base_2(n)). + * If n < 0 return -1. + */ +static int +logbase2( int n ) +{ + GLint i = 1; + GLint log2 = 0; + + if (n < 0) + return -1; + + if (n == 0) + return 0; + + while ( n > i ) { + i *= 2; + log2++; + } + if (i != n) { + return log2 - 1; + } + else { + return log2; + } +} + + + +/** + * Return the simple base format for a given internal texture format. + * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. + * + * \param ctx GL context. + * \param internalFormat the internal texture format token or 1, 2, 3, or 4. + * + * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, + * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. + * + * This is the format which is used during texture application (i.e. the + * texture format and env mode determine the arithmetic used. + */ +GLint +_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) +{ + switch (internalFormat) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return GL_ALPHA; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return GL_LUMINANCE; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return GL_LUMINANCE_ALPHA; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return GL_INTENSITY; + case 3: + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return GL_RGB; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return GL_RGBA; + default: + ; /* fallthrough */ + } + + if (ctx->Extensions.EXT_paletted_texture) { + switch (internalFormat) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return GL_COLOR_INDEX; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.SGIX_depth_texture || + ctx->Extensions.ARB_depth_texture) { + switch (internalFormat) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16_SGIX: + case GL_DEPTH_COMPONENT24_SGIX: + case GL_DEPTH_COMPONENT32_SGIX: + return GL_DEPTH_COMPONENT; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.ARB_texture_compression) { + switch (internalFormat) { + case GL_COMPRESSED_ALPHA: + return GL_ALPHA; + case GL_COMPRESSED_LUMINANCE: + return GL_LUMINANCE; + case GL_COMPRESSED_LUMINANCE_ALPHA: + return GL_LUMINANCE_ALPHA; + case GL_COMPRESSED_INTENSITY: + return GL_INTENSITY; + case GL_COMPRESSED_RGB: + return GL_RGB; + case GL_COMPRESSED_RGBA: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.TDFX_texture_compression_FXT1) { + switch (internalFormat) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + return GL_RGB; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.EXT_texture_compression_s3tc) { + switch (internalFormat) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return GL_RGB; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.S3_s3tc) { + switch (internalFormat) { + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + return GL_RGB; + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + return GL_RGBA; + default: + ; /* fallthrough */ + } + } + + if (ctx->Extensions.MESA_ycbcr_texture) { + if (internalFormat == GL_YCBCR_MESA) + return GL_YCBCR_MESA; + } + + if (ctx->Extensions.ARB_texture_float) { + switch (internalFormat) { + case GL_ALPHA16F_ARB: + case GL_ALPHA32F_ARB: + return GL_ALPHA; + case GL_RGBA16F_ARB: + case GL_RGBA32F_ARB: + return GL_RGBA; + case GL_RGB16F_ARB: + case GL_RGB32F_ARB: + return GL_RGB; + case GL_INTENSITY16F_ARB: + case GL_INTENSITY32F_ARB: + return GL_INTENSITY; + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + return GL_LUMINANCE; + case GL_LUMINANCE_ALPHA16F_ARB: + case GL_LUMINANCE_ALPHA32F_ARB: + return GL_LUMINANCE_ALPHA; + default: + ; /* fallthrough */ + } + } + + return -1; /* error */ +} + + +/** + * Test if the given image format is a color/RGBA format (i.e., not color + * index, depth, stencil, etc). + * \param format the image format value (may by an internal texture format) + * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. + */ +static GLboolean +is_color_format(GLenum format) +{ + switch (format) { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case 3: + case GL_RGB: + case GL_BGR: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case 4: + case GL_ABGR_EXT: + case GL_RGBA: + case GL_BGRA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + /* float texture formats */ + case GL_ALPHA16F_ARB: + case GL_ALPHA32F_ARB: + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + case GL_LUMINANCE_ALPHA16F_ARB: + case GL_LUMINANCE_ALPHA32F_ARB: + case GL_INTENSITY16F_ARB: + case GL_INTENSITY32F_ARB: + case GL_RGB16F_ARB: + case GL_RGB32F_ARB: + case GL_RGBA16F_ARB: + case GL_RGBA32F_ARB: + /* compressed formats */ + case GL_COMPRESSED_ALPHA: + case GL_COMPRESSED_LUMINANCE: + case GL_COMPRESSED_LUMINANCE_ALPHA: + case GL_COMPRESSED_INTENSITY: + case GL_COMPRESSED_RGB: + case GL_COMPRESSED_RGBA: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return GL_TRUE; + case GL_YCBCR_MESA: /* not considered to be RGB */ + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a color index format. + */ +static GLboolean +is_index_format(GLenum format) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth component format. + */ +static GLboolean +is_depth_format(GLenum format) +{ + switch (format) { + case GL_DEPTH_COMPONENT16_ARB: + case GL_DEPTH_COMPONENT24_ARB: + case GL_DEPTH_COMPONENT32_ARB: + case GL_DEPTH_COMPONENT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a YCbCr format. + */ +static GLboolean +is_ycbcr_format(GLenum format) +{ + switch (format) { + case GL_YCBCR_MESA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if it is a supported compressed format. + * + * \param internalFormat the internal format token provided by the user. + * + * \ret GL_TRUE if \p internalFormat is a supported compressed format, or + * GL_FALSE otherwise. + * + * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX + * are supported. + */ +static GLboolean +is_compressed_format(GLcontext *ctx, GLenum internalFormat) +{ + (void) ctx; + switch (internalFormat) { + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Store a gl_texture_image pointer in a gl_texture_object structure + * according to the target and level parameters. + * + * \param tObj texture object. + * \param target texture target. + * \param level image level. + * \param texImage texture image. + * + * This was basically prompted by the introduction of cube maps. + */ +void +_mesa_set_tex_image(struct gl_texture_object *tObj, + GLenum target, GLint level, + struct gl_texture_image *texImage) +{ + ASSERT(tObj); + ASSERT(texImage); + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + tObj->Image[0][level] = texImage; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + { + GLuint face = ((GLuint) target - + (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); + tObj->Image[face][level] = texImage; + } + break; + case GL_TEXTURE_RECTANGLE_NV: + ASSERT(level == 0); + tObj->Image[0][level] = texImage; + break; + default: + _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); + return; + } + /* Set the 'back' pointer */ + texImage->TexObject = tObj; +} + + +/** + * Allocate a texture image structure. + * + * Called via ctx->Driver.NewTextureImage() unless overriden by a device + * driver. + * + * \return a pointer to gl_texture_image struct with all fields initialized to + * zero. + */ +struct gl_texture_image * +_mesa_new_texture_image( GLcontext *ctx ) +{ + (void) ctx; + return CALLOC_STRUCT(gl_texture_image); +} + + +/** + * Free texture image data. + * This function is a fallback called via ctx->Driver.FreeTexImageData(). + * + * \param teximage texture image. + * + * Free the texture image data if it's not marked as client data. + */ +void +_mesa_free_texture_image_data(GLcontext *ctx, + struct gl_texture_image *texImage) +{ + if (texImage->Data && !texImage->IsClientData) { + /* free the old texture data */ + _mesa_free_texmemory(texImage->Data); + } + + texImage->Data = NULL; +} + + +/** + * Free texture image. + * + * \param teximage texture image. + * + * Free the texture image structure and the associated image data. + */ +void +_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) +{ + if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + FREE( texImage ); +} + + +/** + * Test if a target is a proxy target. + * + * \param target texture target. + * + * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. + */ +static GLboolean +is_proxy_target(GLenum target) +{ + return (target == GL_PROXY_TEXTURE_1D || + target == GL_PROXY_TEXTURE_2D || + target == GL_PROXY_TEXTURE_3D || + target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || + target == GL_PROXY_TEXTURE_RECTANGLE_NV); +} + + +/** + * Get the texture object that corresponds to the target of the given texture unit. + * + * \param ctx GL context. + * \param texUnit texture unit. + * \param target texture target. + * + * \return pointer to the texture object on success, or NULL on failure. + * + * \sa gl_texture_unit. + */ +struct gl_texture_object * +_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + return texUnit->Current1D; + case GL_PROXY_TEXTURE_1D: + return ctx->Texture.Proxy1D; + case GL_TEXTURE_2D: + return texUnit->Current2D; + case GL_PROXY_TEXTURE_2D: + return ctx->Texture.Proxy2D; + case GL_TEXTURE_3D: + return texUnit->Current3D; + case GL_PROXY_TEXTURE_3D: + return ctx->Texture.Proxy3D; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_ARB: + return ctx->Extensions.ARB_texture_cube_map + ? texUnit->CurrentCubeMap : NULL; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + return ctx->Extensions.ARB_texture_cube_map + ? ctx->Texture.ProxyCubeMap : NULL; + case GL_TEXTURE_RECTANGLE_NV: + return ctx->Extensions.NV_texture_rectangle + ? texUnit->CurrentRect : NULL; + case GL_PROXY_TEXTURE_RECTANGLE_NV: + return ctx->Extensions.NV_texture_rectangle + ? ctx->Texture.ProxyRect : NULL; + default: + _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); + return NULL; + } +} + + +/** + * Get the texture image struct which corresponds to target and level + * of the given texture unit. + * + * \param ctx GL context. + * \param texUnit texture unit. + * \param target texture target. + * \param level image level. + * + * \return pointer to the texture image structure on success, or NULL on failure. + * + * \sa gl_texture_unit. + */ +struct gl_texture_image * +_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target, GLint level) +{ + ASSERT(texUnit); + ASSERT(level < MAX_TEXTURE_LEVELS); + switch (target) { + case GL_TEXTURE_1D: + return texUnit->Current1D->Image[0][level]; + case GL_PROXY_TEXTURE_1D: + return ctx->Texture.Proxy1D->Image[0][level]; + case GL_TEXTURE_2D: + return texUnit->Current2D->Image[0][level]; + case GL_PROXY_TEXTURE_2D: + return ctx->Texture.Proxy2D->Image[0][level]; + case GL_TEXTURE_3D: + return texUnit->Current3D->Image[0][level]; + case GL_PROXY_TEXTURE_3D: + return ctx->Texture.Proxy3D->Image[0][level]; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + if (ctx->Extensions.ARB_texture_cube_map) { + GLuint face = ((GLuint) target - + (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); + return texUnit->CurrentCubeMap->Image[face][level]; + } + else + return NULL; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + if (ctx->Extensions.ARB_texture_cube_map) + return ctx->Texture.ProxyCubeMap->Image[0][level]; + else + return NULL; + case GL_TEXTURE_RECTANGLE_NV: + if (ctx->Extensions.NV_texture_rectangle) { + ASSERT(level == 0); + return texUnit->CurrentRect->Image[0][level]; + } + else { + return NULL; + } + case GL_PROXY_TEXTURE_RECTANGLE_NV: + if (ctx->Extensions.NV_texture_rectangle) { + ASSERT(level == 0); + return ctx->Texture.ProxyRect->Image[0][level]; + } + else { + return NULL; + } + default: + _mesa_problem(ctx, "bad target in _mesa_select_tex_image()"); + return NULL; + } +} + + +/** + * Like _mesa_select_tex_image() but if the image doesn't exist, allocate + * it and install it. Only return NULL if passed a bad parameter or run + * out of memory. + */ +struct gl_texture_image * +_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target, GLint level) +{ + struct gl_texture_image *texImage; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!texImage) { + struct gl_texture_object *texObj; + texImage = ctx->Driver.NewTextureImage(ctx); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); + return NULL; + } + texObj = _mesa_select_tex_object(ctx, texUnit, target); + ASSERT(texObj); + _mesa_set_tex_image(texObj, target, level, texImage); + } + return texImage; +} + + +/** + * Return pointer to the specified proxy texture image. + * Note that proxy textures are per-context, not per-texture unit. + * \return pointer to texture image or NULL if invalid target, invalid + * level, or out of memory. + */ +struct gl_texture_image * +_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) +{ + struct gl_texture_image *texImage; + + if (level < 0 ) + return NULL; + + switch (target) { + case GL_PROXY_TEXTURE_1D: + if (level >= ctx->Const.MaxTextureLevels) + return NULL; + texImage = ctx->Texture.Proxy1D->Image[0][level]; + if (!texImage) { + texImage = ctx->Driver.NewTextureImage(ctx); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); + return NULL; + } + ctx->Texture.Proxy1D->Image[0][level] = texImage; + /* Set the 'back' pointer */ + texImage->TexObject = ctx->Texture.Proxy1D; + } + return texImage; + case GL_PROXY_TEXTURE_2D: + if (level >= ctx->Const.MaxTextureLevels) + return NULL; + texImage = ctx->Texture.Proxy2D->Image[0][level]; + if (!texImage) { + texImage = ctx->Driver.NewTextureImage(ctx); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); + return NULL; + } + ctx->Texture.Proxy2D->Image[0][level] = texImage; + /* Set the 'back' pointer */ + texImage->TexObject = ctx->Texture.Proxy2D; + } + return texImage; + case GL_PROXY_TEXTURE_3D: + if (level >= ctx->Const.Max3DTextureLevels) + return NULL; + texImage = ctx->Texture.Proxy3D->Image[0][level]; + if (!texImage) { + texImage = ctx->Driver.NewTextureImage(ctx); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); + return NULL; + } + ctx->Texture.Proxy3D->Image[0][level] = texImage; + /* Set the 'back' pointer */ + texImage->TexObject = ctx->Texture.Proxy3D; + } + return texImage; + case GL_PROXY_TEXTURE_CUBE_MAP: + if (level >= ctx->Const.MaxCubeTextureLevels) + return NULL; + texImage = ctx->Texture.ProxyCubeMap->Image[0][level]; + if (!texImage) { + texImage = ctx->Driver.NewTextureImage(ctx); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); + return NULL; + } + ctx->Texture.ProxyCubeMap->Image[0][level] = texImage; + /* Set the 'back' pointer */ + texImage->TexObject = ctx->Texture.ProxyCubeMap; + } + return texImage; + case GL_PROXY_TEXTURE_RECTANGLE_NV: + if (level > 0) + return NULL; + texImage = ctx->Texture.ProxyRect->Image[0][level]; + if (!texImage) { + texImage = ctx->Driver.NewTextureImage(ctx); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); + return NULL; + } + ctx->Texture.ProxyRect->Image[0][level] = texImage; + /* Set the 'back' pointer */ + texImage->TexObject = ctx->Texture.ProxyRect; + } + return texImage; + default: + return NULL; + } +} + + +/** + * Get the maximum number of allowed mipmap levels. + * + * \param ctx GL context. + * \param target texture target. + * + * \return the maximum number of allowed mipmap levels for the given + * texture target, or zero if passed a bad target. + * + * \sa gl_constants. + */ +GLint +_mesa_max_texture_levels(GLcontext *ctx, GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + return ctx->Const.MaxTextureLevels; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + return ctx->Const.Max3DTextureLevels; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_ARB: + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + return ctx->Const.MaxCubeTextureLevels; + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + return 1; + default: + return 0; /* bad target */ + } +} + + + +#if 000 /* not used anymore */ +/* + * glTexImage[123]D can accept a NULL image pointer. In this case we + * create a texture image with unspecified image contents per the OpenGL + * spec. + */ +static GLubyte * +make_null_texture(GLint width, GLint height, GLint depth, GLenum format) +{ + const GLint components = _mesa_components_in_format(format); + const GLint numPixels = width * height * depth; + GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); + +#ifdef DEBUG + /* + * Let's see if anyone finds this. If glTexImage2D() is called with + * a NULL image pointer then load the texture image with something + * interesting instead of leaving it indeterminate. + */ + if (data) { + static const char message[8][32] = { + " X X XXXXX XXX X ", + " XX XX X X X X X ", + " X X X X X X X ", + " X X XXXX XXX XXXXX ", + " X X X X X X ", + " X X X X X X X ", + " X X XXXXX XXX X X ", + " " + }; + + GLubyte *imgPtr = data; + GLint h, i, j, k; + for (h = 0; h < depth; h++) { + for (i = 0; i < height; i++) { + GLint srcRow = 7 - (i % 8); + for (j = 0; j < width; j++) { + GLint srcCol = j % 32; + GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; + for (k = 0; k < components; k++) { + *imgPtr++ = texel; + } + } + } + } + } +#endif + + return data; +} +#endif + + + +/** + * Reset the fields of a gl_texture_image struct to zero. + * + * \param img texture image structure. + * + * This is called when a proxy texture test fails, we set all the + * image members (except DriverData) to zero. + * It's also used in glTexImage[123]D as a safeguard to be sure all + * required fields get initialized properly by the Driver.TexImage[123]D + * functions. + */ +static void +clear_teximage_fields(struct gl_texture_image *img) +{ + ASSERT(img); + img->Format = 0; + img->IntFormat = 0; + img->Border = 0; + img->Width = 0; + img->Height = 0; + img->Depth = 0; + img->RowStride = 0; + img->Width2 = 0; + img->Height2 = 0; + img->Depth2 = 0; + img->WidthLog2 = 0; + img->HeightLog2 = 0; + img->DepthLog2 = 0; + img->Data = NULL; + img->TexFormat = &_mesa_null_texformat; + img->FetchTexelc = NULL; + img->FetchTexelf = NULL; + img->IsCompressed = 0; + img->CompressedSize = 0; +} + + +/** + * Initialize basic fields of the gl_texture_image struct. + * + * \param ctx GL context. + * \param target texture target. + * \param img texture image structure to be initialized. + * \param width image width. + * \param height image height. + * \param depth image depth. + * \param border image border. + * \param internalFormat internal format. + * + * Fills in the fields of \p img with the given information. + * Note: width, height and depth include the border. + */ +void +_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, + struct gl_texture_image *img, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum internalFormat) +{ + ASSERT(img); + img->Format = _mesa_base_tex_format( ctx, internalFormat ); + ASSERT(img->Format > 0); + img->IntFormat = internalFormat; + img->Border = border; + img->Width = width; + img->Height = height; + img->Depth = depth; + img->RowStride = width; + img->WidthLog2 = logbase2(width - 2 * border); + if (height == 1) /* 1-D texture */ + img->HeightLog2 = 0; + else + img->HeightLog2 = logbase2(height - 2 * border); + if (depth == 1) /* 2-D texture */ + img->DepthLog2 = 0; + else + img->DepthLog2 = logbase2(depth - 2 * border); + img->Width2 = width - 2 * border; /*1 << img->WidthLog2;*/ + img->Height2 = height - 2 * border; /*1 << img->HeightLog2;*/ + img->Depth2 = depth - 2 * border; /*1 << img->DepthLog2;*/ + img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); + img->IsCompressed = is_compressed_format(ctx, internalFormat); + if (img->IsCompressed) + img->CompressedSize = ctx->Driver.CompressedTextureSize(ctx, width, + height, depth, internalFormat); + else + img->CompressedSize = 0; + + if ((width == 1 || _mesa_bitcount(width - 2 * border) == 1) && + (height == 1 || _mesa_bitcount(height - 2 * border) == 1) && + (depth == 1 || _mesa_bitcount(depth - 2 * border) == 1)) + img->_IsPowerOfTwo = GL_TRUE; + else + img->_IsPowerOfTwo = GL_FALSE; + + /* Compute Width/Height/DepthScale for mipmap lod computation */ + if (target == GL_TEXTURE_RECTANGLE_NV) { + /* scale = 1.0 since texture coords directly map to texels */ + img->WidthScale = 1.0; + img->HeightScale = 1.0; + img->DepthScale = 1.0; + } + else { + img->WidthScale = (GLfloat) img->Width; + img->HeightScale = (GLfloat) img->Height; + img->DepthScale = (GLfloat) img->Depth; + } +} + + +/** + * This is the fallback for Driver.TestProxyTexImage(). Test the texture + * level, width, height and depth against the ctx->Const limits for textures. + * + * A hardware driver might override this function if, for example, the + * max 3D texture size is 512x512x64 (i.e. not a cube). + * + * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, + * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, + * GL_PROXY_TEXTURE_CUBE_MAP_ARB. + * \param level as passed to glTexImage + * \param internalFormat as passed to glTexImage + * \param format as passed to glTexImage + * \param type as passed to glTexImage + * \param width as passed to glTexImage + * \param height as passed to glTexImage + * \param depth as passed to glTexImage + * \param border as passed to glTexImage + * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. + */ +GLboolean +_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border) +{ + GLint maxSize; + + (void) internalFormat; + (void) format; + (void) type; + + switch (target) { + case GL_PROXY_TEXTURE_1D: + maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || + level >= ctx->Const.MaxTextureLevels) { + /* bad width or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_2D: + maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || + height < 2 * border || height > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || + level >= ctx->Const.MaxTextureLevels) { + /* bad width or height or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_3D: + maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || + height < 2 * border || height > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || + depth < 2 * border || depth > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(depth - 2 * border) != 1) || + level >= ctx->Const.Max3DTextureLevels) { + /* bad width or height or depth or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_RECTANGLE_NV: + if (width < 1 || width > ctx->Const.MaxTextureRectSize || + height < 1 || height > ctx->Const.MaxTextureRectSize || + level != 0) { + /* bad width or height or level */ + return GL_FALSE; + } + return GL_TRUE; + case GL_PROXY_TEXTURE_CUBE_MAP_ARB: + maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); + if (width < 2 * border || width > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || + height < 2 * border || height > 2 + maxSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || + level >= ctx->Const.MaxCubeTextureLevels) { + /* bad width or height */ + return GL_FALSE; + } + return GL_TRUE; + default: + _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); + return GL_FALSE; + } +} + + +/** + * Test the glTexImage[123]D() parameters for errors. + * + * \param ctx GL context. + * \param target texture target given by the user. + * \param level image level given by the user. + * \param internalFormat internal format given by the user. + * \param format pixel data format given by the user. + * \param type pixel data type given by the user. + * \param dimensions texture image dimensions (must be 1, 2 or 3). + * \param width image width given by the user. + * \param height image height given by the user. + * \param depth image depth given by the user. + * \param border image border given by the user. + * + * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. + * + * Verifies each of the parameters against the constants specified in + * __GLcontextRec::Const and the supported extensions, and according to the + * OpenGL specification. + */ +static GLboolean +texture_error_check( GLcontext *ctx, GLenum target, + GLint level, GLint internalFormat, + GLenum format, GLenum type, + GLuint dimensions, + GLint width, GLint height, + GLint depth, GLint border ) +{ + const GLboolean isProxy = is_proxy_target(target); + GLboolean sizeOK; + GLboolean colorFormat, indexFormat; + + /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(level=%d)", dimensions, level); + } + return GL_TRUE; + } + + /* Check border */ + if (border < 0 || border > 1 || + ((target == GL_TEXTURE_RECTANGLE_NV || + target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(border=%d)", dimensions, border); + } + return GL_TRUE; + } + + if (width < 0 || height < 0 || depth < 0) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(width, height or depth < 0)", dimensions); + } + return GL_TRUE; + } + + /* Check target and call ctx->Driver.TestProxyTexImage() to check the + * level, width, height and depth. + */ + if (dimensions == 1) { + if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, + level, internalFormat, + format, type, + width, 1, 1, border); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 2) { + if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, + level, internalFormat, + format, type, + width, height, 1, border); + } + else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || + (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); + return GL_TRUE; + } + sizeOK = (width == height) && + ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, + level, internalFormat, format, type, + width, height, 1, border); + } + else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || + target == GL_TEXTURE_RECTANGLE_NV) { + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); + return GL_TRUE; + } + sizeOK = ctx->Driver.TestProxyTexImage(ctx, + GL_PROXY_TEXTURE_RECTANGLE_NV, + level, internalFormat, + format, type, + width, height, 1, border); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); + return GL_TRUE; + } + } + else if (dimensions == 3) { + if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_3D, + level, internalFormat, + format, type, + width, height, depth, border); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); + return GL_TRUE; + } + } + else { + _mesa_problem( ctx, "bad dims in texture_error_check" ); + return GL_TRUE; + } + + if (!sizeOK) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", + dimensions, level, width, height, depth); + } + return GL_TRUE; + } + + /* Check internalFormat */ + if (_mesa_base_tex_format(ctx, internalFormat) < 0) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexImage%dD(internalFormat=0x%x)", + dimensions, internalFormat); + } + return GL_TRUE; + } + + /* Check incoming image format and type */ + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there + * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. + */ + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%dD(format or type)", dimensions); + } + return GL_TRUE; + } + + /* make sure internal format and format basically agree */ + colorFormat = is_color_format(format); + indexFormat = is_index_format(format); + if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) || + (is_index_format(internalFormat) && !indexFormat) || + (is_depth_format(internalFormat) != is_depth_format(format)) || + (is_ycbcr_format(internalFormat) != is_ycbcr_format(format))) { + if (!isProxy) + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage(internalFormat/format)"); + return GL_TRUE; + } + + /* additional checks for ycbcr textures */ + if (internalFormat == GL_YCBCR_MESA) { + ASSERT(ctx->Extensions.MESA_ycbcr_texture); + if (type != GL_UNSIGNED_SHORT_8_8_MESA && + type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { + char message[100]; + _mesa_sprintf(message, + "glTexImage%d(format/type YCBCR mismatch", dimensions); + _mesa_error(ctx, GL_INVALID_ENUM, message); + return GL_TRUE; /* error */ + } + if (target != GL_TEXTURE_2D && + target != GL_PROXY_TEXTURE_2D && + target != GL_TEXTURE_RECTANGLE_NV && + target != GL_PROXY_TEXTURE_RECTANGLE_NV) { + if (!isProxy) + _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); + return GL_TRUE; + } + if (border != 0) { + if (!isProxy) { + char message[100]; + _mesa_sprintf(message, + "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", + dimensions, border); + _mesa_error(ctx, GL_INVALID_VALUE, message); + } + return GL_TRUE; + } + } + + /* additional checks for depth textures */ + if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { + /* Only 1D and 2D textures supported */ + if (target != GL_TEXTURE_1D && + target != GL_PROXY_TEXTURE_1D && + target != GL_TEXTURE_2D && + target != GL_PROXY_TEXTURE_2D) { + if (!isProxy) + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexImage(target/internalFormat)"); + return GL_TRUE; + } + } + + /* additional checks for compressed textures */ + if (is_compressed_format(ctx, internalFormat)) { + if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) { + /* OK */ + } + else if (ctx->Extensions.ARB_texture_cube_map && + (target == GL_PROXY_TEXTURE_CUBE_MAP || + (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) { + /* OK */ + } + else { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexImage%d(target)", dimensions); + return GL_TRUE; + } + } + if (border != 0) { + if (!isProxy) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexImage%D(border!=0)", dimensions); + } + return GL_TRUE; + } + } + + /* if we get here, the parameters are OK */ + return GL_FALSE; +} + + +/** + * Test glTexSubImage[123]D() parameters for errors. + * + * \param ctx GL context. + * \param dimensions texture image dimensions (must be 1, 2 or 3). + * \param target texture target given by the user. + * \param level image level given by the user. + * \param xoffset sub-image x offset given by the user. + * \param yoffset sub-image y offset given by the user. + * \param zoffset sub-image z offset given by the user. + * \param format pixel data format given by the user. + * \param type pixel data type given by the user. + * \param width image width given by the user. + * \param height image height given by the user. + * \param depth image depth given by the user. + * + * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. + * + * Verifies each of the parameters against the constants specified in + * __GLcontextRec::Const and the supported extensions, and according to the + * OpenGL specification. + */ +static GLboolean +subtexture_error_check( GLcontext *ctx, GLuint dimensions, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *destTex; + + /* Check target */ + if (dimensions == 1) { + if (target != GL_TEXTURE_1D) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 2) { + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <=GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (ctx->Extensions.NV_texture_rectangle && + target == GL_TEXTURE_RECTANGLE_NV) { + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (target != GL_TEXTURE_2D) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 3) { + if (target != GL_TEXTURE_3D) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); + return GL_TRUE; + } + } + else { + _mesa_problem( ctx, "invalid dims in texture_error_check" ); + return GL_TRUE; + } + + /* Basic level check */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); + return GL_TRUE; + } + + if (width < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexSubImage%dD(width=%d)", dimensions, width); + return GL_TRUE; + } + if (height < 0 && dimensions > 1) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexSubImage%dD(height=%d)", dimensions, height); + return GL_TRUE; + } + if (depth < 0 && dimensions > 2) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glTexSubImage%dD(depth=%d)", dimensions, depth); + return GL_TRUE; + } + + destTex = _mesa_select_tex_image(ctx, texUnit, target, level); + + if (!destTex) { + /* undefined image level */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); + return GL_TRUE; + } + + if (xoffset < -((GLint)destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", + dimensions); + return GL_TRUE; + } + if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", + dimensions); + return GL_TRUE; + } + if (dimensions > 1) { + if (yoffset < -((GLint)destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", + dimensions); + return GL_TRUE; + } + if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", + dimensions); + return GL_TRUE; + } + } + if (dimensions > 2) { + if (zoffset < -((GLint)destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); + return GL_TRUE; + } + if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); + return GL_TRUE; + } + } + + if (!_mesa_is_legal_format_and_type(ctx, format, type)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexSubImage%dD(format or type)", dimensions); + return GL_TRUE; + } + + if (destTex->IsCompressed) { + const struct gl_texture_unit *texUnit; + const struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + + if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) { + /* OK */ + } + else if (ctx->Extensions.ARB_texture_cube_map && + (target == GL_PROXY_TEXTURE_CUBE_MAP || + (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) { + /* OK */ + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexSubImage%D(target)", dimensions); + return GL_TRUE; + } + /* offset must be multiple of 4 */ + if ((xoffset & 3) || (yoffset & 3)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%D(xoffset or yoffset)", dimensions); + return GL_TRUE; + } + /* size must be multiple of 4 or equal to whole texture size */ + if ((width & 3) && (GLuint) width != texImage->Width) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%D(width)", dimensions); + return GL_TRUE; + } + if ((height & 3) && (GLuint) height != texImage->Height) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glTexSubImage%D(width)", dimensions); + return GL_TRUE; + } + } + + return GL_FALSE; +} + + +/** + * Test glCopyTexImage[12]D() parameters for errors. + * + * \param ctx GL context. + * \param dimensions texture image dimensions (must be 1, 2 or 3). + * \param target texture target given by the user. + * \param level image level given by the user. + * \param internalFormat internal format given by the user. + * \param width image width given by the user. + * \param height image height given by the user. + * \param depth image depth given by the user. + * \param border texture border. + * + * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. + * + * Verifies each of the parameters against the constants specified in + * __GLcontextRec::Const and the supported extensions, and according to the + * OpenGL specification. + */ +static GLboolean +copytexture_error_check( GLcontext *ctx, GLuint dimensions, + GLenum target, GLint level, GLint internalFormat, + GLint width, GLint height, GLint border ) +{ + GLenum format, type; + GLboolean sizeOK; + + /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexImage%dD(level=%d)", dimensions, level); + return GL_TRUE; + } + + /* Check border */ + if (border < 0 || border > 1 || + ((target == GL_TEXTURE_RECTANGLE_NV || + target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { + return GL_TRUE; + } + + /* The format and type aren't really significant here, but we need to pass + * something to TestProxyTexImage(). + */ + format = _mesa_base_tex_format(ctx, internalFormat); + type = GL_FLOAT; + + /* Check target and call ctx->Driver.TestProxyTexImage() to check the + * level, width, height and depth. + */ + if (dimensions == 1) { + if (target == GL_TEXTURE_1D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, + level, internalFormat, + format, type, + width, 1, 1, border); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 2) { + if (target == GL_TEXTURE_2D) { + sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, + level, internalFormat, + format, type, + width, height, 1, border); + } + else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return GL_TRUE; + } + sizeOK = (width == height) && + ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, + level, internalFormat, format, type, + width, height, 1, border); + } + else if (target == GL_TEXTURE_RECTANGLE_NV) { + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return GL_TRUE; + } + sizeOK = ctx->Driver.TestProxyTexImage(ctx, + GL_PROXY_TEXTURE_RECTANGLE_NV, + level, internalFormat, + format, type, + width, height, 1, border); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); + return GL_TRUE; + } + } + else { + _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); + return GL_TRUE; + } + + if (!sizeOK) { + if (dimensions == 1) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexImage1D(width=%d)", width); + } + else { + ASSERT(dimensions == 2); + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexImage2D(width=%d, height=%d)", width, height); + } + return GL_TRUE; + } + + if (_mesa_base_tex_format(ctx, internalFormat) < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexImage%dD(internalFormat)", dimensions); + return GL_TRUE; + } + + if (is_compressed_format(ctx, internalFormat)) { + if (target != GL_TEXTURE_2D) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glCopyTexImage%d(target)", dimensions); + return GL_TRUE; + } + if (border != 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexImage%D(border!=0)", dimensions); + return GL_TRUE; + } + } + + /* if we get here, the parameters are OK */ + return GL_FALSE; +} + + +/** + * Test glCopyTexImage[12]D() parameters for errors. + * + * \param ctx GL context. + * \param dimensions texture image dimensions (must be 1, 2 or 3). + * \param target texture target given by the user. + * \param level image level given by the user. + * \param xoffset sub-image x offset given by the user. + * \param yoffset sub-image y offset given by the user. + * \param zoffset sub-image z offset given by the user. + * \param width image width given by the user. + * \param height image height given by the user. + * + * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. + * + * Verifies each of the parameters against the constants specified in + * __GLcontextRec::Const and the supported extensions, and according to the + * OpenGL specification. + */ +static GLboolean +copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_image *teximage; + + /* Check target */ + if (dimensions == 1) { + if (target != GL_TEXTURE_1D) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 2) { + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (target == GL_TEXTURE_RECTANGLE_NV) { + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (target != GL_TEXTURE_2D) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); + return GL_TRUE; + } + } + else if (dimensions == 3) { + if (target != GL_TEXTURE_3D) { + _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); + return GL_TRUE; + } + } + + /* Check level */ + if (level < 0 || level >= MAX_TEXTURE_LEVELS) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(level=%d)", dimensions, level); + return GL_TRUE; + } + + /* Check size */ + if (width < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(width=%d)", dimensions, width); + return GL_TRUE; + } + if (dimensions > 1 && height < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(height=%d)", dimensions, height); + return GL_TRUE; + } + + teximage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!teximage) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCopyTexSubImage%dD(undefined texture level: %d)", + dimensions, level); + return GL_TRUE; + } + + if (xoffset < -((GLint)teximage->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); + return GL_TRUE; + } + if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(xoffset+width)", dimensions); + return GL_TRUE; + } + if (dimensions > 1) { + if (yoffset < -((GLint)teximage->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); + return GL_TRUE; + } + /* NOTE: we're adding the border here, not subtracting! */ + if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(yoffset+height)", dimensions); + return GL_TRUE; + } + } + + if (dimensions > 2) { + if (zoffset < -((GLint)teximage->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(zoffset)", dimensions); + return GL_TRUE; + } + if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%dD(zoffset+depth)", dimensions); + return GL_TRUE; + } + } + + if (teximage->IsCompressed) { + if (target != GL_TEXTURE_2D) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glCopyTexSubImage%d(target)", dimensions); + return GL_TRUE; + } + /* offset must be multiple of 4 */ + if ((xoffset & 3) || (yoffset & 3)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); + return GL_TRUE; + } + /* size must be multiple of 4 */ + if ((width & 3) != 0 && (GLuint) width != teximage->Width) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%D(width)", dimensions); + return GL_TRUE; + } + if ((height & 3) != 0 && (GLuint) height != teximage->Height) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glCopyTexSubImage%D(height)", dimensions); + return GL_TRUE; + } + } + + if (teximage->IntFormat == GL_YCBCR_MESA) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); + return GL_TRUE; + } + + /* if we get here, the parameters are OK */ + return GL_FALSE; +} + + +/** + * Get texture image. Called by glGetTexImage. + * + * \param target texture target. + * \param level image level. + * \param format pixel data format for returned image. + * \param type pixel data type for returned image. + * \param pixels returned pixel data. + */ +void GLAPIENTRY +_mesa_GetTexImage( GLenum target, GLint level, GLenum format, + GLenum type, GLvoid *pixels ) +{ + const struct gl_texture_unit *texUnit; + const struct gl_texture_object *texObj; + const struct gl_texture_image *texImage; + GLint maxLevels = 0; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); + texObj = _mesa_select_tex_object(ctx, texUnit, target); + if (!texObj || is_proxy_target(target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); + return; + } + + maxLevels = _mesa_max_texture_levels(ctx, target); + ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ + + if (level < 0 || level >= maxLevels) { + _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); + return; + } + + if (_mesa_sizeof_packed_type(type) <= 0) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); + return; + } + + if (_mesa_components_in_format(format) <= 0 || + format == GL_STENCIL_INDEX) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); + return; + } + + if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + } + + if (!ctx->Extensions.SGIX_depth_texture && + !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + } + + if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); + } + + if (!pixels) + return; + + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!texImage) { + /* invalid mipmap level, not an error */ + return; + } + + /* Make sure the requested image format is compatible with the + * texture's format. We let the colorformat-indexformat go through, + * because the texelfetcher will dequantize to full rgba. + */ + if (is_color_format(format) + && !is_color_format(texImage->TexFormat->BaseFormat) + && !is_index_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return; + } + else if (is_index_format(format) + && !is_index_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return; + } + else if (is_depth_format(format) + && !is_depth_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return; + } + else if (is_ycbcr_format(format) + && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); + return; + } + + /* typically, this will call _mesa_get_teximage() */ + ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, + texObj, texImage); +} + + + +/* + * Called from the API. Note that width includes the border. + */ +void GLAPIENTRY +_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLint border, GLenum format, + GLenum type, const GLvoid *pixels ) +{ + GLsizei postConvWidth = width; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } + + if (target == GL_TEXTURE_1D) { + /* non-proxy target */ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 1, postConvWidth, 1, 1, border)) { + return; /* error was recorded */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, 1, 1, + border, internalFormat); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + ASSERT(ctx->Driver.TexImage1D); + + /* Give the texture to the driver! <pixels> may be null! */ + (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, + width, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); + + ASSERT(texImage->TexFormat); + + /* If driver didn't explicitly set this, use the defaults */ + if (!texImage->FetchTexelc) + texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; + if (!texImage->FetchTexelf) + texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else if (target == GL_PROXY_TEXTURE_1D) { + /* Proxy texture: check for errors and update proxy state */ + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 1, postConvWidth, 1, 1, border)) { + /* when error, clear all proxy texture image parameters */ + if (texImage) + clear_teximage_fields(texImage); + } + else { + /* no error, set the tex image parameters */ + ASSERT(texImage); + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, 1, 1, + border, internalFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); + return; + } +} + + +void GLAPIENTRY +_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GLsizei postConvWidth = width, postConvHeight = height; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } + + if (target == GL_TEXTURE_2D || + (ctx->Extensions.ARB_texture_cube_map && + target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || + (ctx->Extensions.NV_texture_rectangle && + target == GL_TEXTURE_RECTANGLE_NV)) { + /* non-proxy target */ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 2, postConvWidth, postConvHeight, + 1, border)) { + return; /* error was recorded */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, postConvHeight, 1, + border, internalFormat); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + ASSERT(ctx->Driver.TexImage2D); + + /* Give the texture to the driver! <pixels> may be null! */ + (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, + width, height, border, format, type, pixels, + &ctx->Unpack, texObj, texImage); + + ASSERT(texImage->TexFormat); + + /* If driver didn't explicitly set these, use the defaults */ + if (!texImage->FetchTexelc) + texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; + if (!texImage->FetchTexelf) + texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else if (target == GL_PROXY_TEXTURE_2D || + (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && + ctx->Extensions.ARB_texture_cube_map) || + (target == GL_PROXY_TEXTURE_RECTANGLE_NV && + ctx->Extensions.NV_texture_rectangle)) { + /* Proxy texture: check for errors and update proxy state */ + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 2, postConvWidth, postConvHeight, + 1, border)) { + /* when error, clear all proxy texture image parameters */ + if (texImage) + clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]); + } + else { + /* no error, set the tex image parameters */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, postConvHeight, 1, + border, internalFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); + return; + } +} + + +/* + * Called by the API or display list executor. + * Note that width and height include the border. + */ +void GLAPIENTRY +_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target == GL_TEXTURE_3D) { + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + /* non-proxy target */ + + if (texture_error_check(ctx, target, level, (GLint) internalFormat, + format, type, 3, width, height, depth, border)) { + return; /* error was recorded */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + width, height, depth, + border, internalFormat); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + ASSERT(ctx->Driver.TexImage3D); + + /* Give the texture to the driver! <pixels> may be null! */ + (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, + width, height, depth, border, format, type, + pixels, &ctx->Unpack, texObj, texImage); + + ASSERT(texImage->TexFormat); + + /* If driver didn't explicitly set these, use the defaults */ + if (!texImage->FetchTexelc) + texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; + if (!texImage->FetchTexelf) + texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else if (target == GL_PROXY_TEXTURE_3D) { + /* Proxy texture: check for errors and update proxy state */ + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texture_error_check(ctx, target, level, internalFormat, + format, type, 3, width, height, depth, border)) { + /* when error, clear all proxy texture image parameters */ + if (texImage) + clear_teximage_fields(texImage); + } + else { + /* no error, set the tex image parameters */ + _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, + border, internalFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); + return; + } +} + + +void GLAPIENTRY +_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ) +{ + _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, + depth, border, format, type, pixels); +} + + + +void GLAPIENTRY +_mesa_TexSubImage1D( GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GLsizei postConvWidth = width; + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + /* XXX should test internal format */ + if (is_color_format(format)) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } + + if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, + postConvWidth, 1, 1, format, type)) { + return; /* error was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + assert(texImage); + + if (width == 0) + return; /* no-op, not an error */ + + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + + ASSERT(ctx->Driver.TexSubImage1D); + (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, + format, type, pixels, &ctx->Unpack, + texObj, texImage); + ctx->NewState |= _NEW_TEXTURE; +} + + +void GLAPIENTRY +_mesa_TexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + GLsizei postConvWidth = width, postConvHeight = height; + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + /* XXX should test internal format */ + if (is_color_format(format)) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } + + if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, + postConvWidth, postConvHeight, 1, format, type)) { + return; /* error was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + assert(texImage); + + if (width == 0 || height == 0) + return; /* no-op, not an error */ + + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + + ASSERT(ctx->Driver.TexSubImage2D); + (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, + width, height, format, type, pixels, + &ctx->Unpack, texObj, texImage); + ctx->NewState |= _NEW_TEXTURE; +} + + + +void GLAPIENTRY +_mesa_TexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, type)) { + return; /* error was detected */ + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + assert(texImage); + + if (width == 0 || height == 0 || height == 0) + return; /* no-op, not an error */ + + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + zoffset += texImage->Border; + + ASSERT(ctx->Driver.TexSubImage3D); + (*ctx->Driver.TexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, + &ctx->Unpack, texObj, texImage ); + ctx->NewState |= _NEW_TEXTURE; +} + + + +void GLAPIENTRY +_mesa_CopyTexImage1D( GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLint border ) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } + + if (copytexture_error_check(ctx, 1, target, level, internalFormat, + postConvWidth, 1, border)) + return; + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, + border, internalFormat); + + + ASSERT(ctx->Driver.CopyTexImage1D); + (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, + x, y, width, border); + + ASSERT(texImage->TexFormat); + + /* If driver didn't explicitly set these, use the defaults */ + if (!texImage->FetchTexelc) + texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; + if (!texImage->FetchTexelf) + texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; +} + + + +void GLAPIENTRY +_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border ) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width, postConvHeight = height; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + if (is_color_format(internalFormat)) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } + + if (copytexture_error_check(ctx, 2, target, level, internalFormat, + postConvWidth, postConvHeight, border)) + return; + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + clear_teximage_fields(texImage); /* not really needed, but helpful */ + _mesa_init_teximage_fields(ctx, target, texImage, + postConvWidth, postConvHeight, 1, + border, internalFormat); + + ASSERT(ctx->Driver.CopyTexImage2D); + (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, + x, y, width, height, border); + + ASSERT(texImage->TexFormat); + + /* If driver didn't explicitly set these, use the defaults */ + if (!texImage->FetchTexelc) + texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; + if (!texImage->FetchTexelf) + texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; +} + + + +void GLAPIENTRY +_mesa_CopyTexSubImage1D( GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + /* XXX should test internal format */ + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + + if (copytexsubimage_error_check(ctx, 1, target, level, + xoffset, 0, 0, postConvWidth, 1)) + return; + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + ASSERT(texImage); + + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + + ASSERT(ctx->Driver.CopyTexSubImage1D); + (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width); + ctx->NewState |= _NEW_TEXTURE; +} + + + +void GLAPIENTRY +_mesa_CopyTexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width, postConvHeight = height; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + /* XXX should test internal format */ + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); + + if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0, + postConvWidth, postConvHeight)) + return; + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + ASSERT(texImage); + + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + + ASSERT(ctx->Driver.CopyTexSubImage2D); + (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, + xoffset, yoffset, x, y, width, height); + ctx->NewState |= _NEW_TEXTURE; +} + + + +void GLAPIENTRY +_mesa_CopyTexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height ) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + GLsizei postConvWidth = width, postConvHeight = height; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) + _mesa_update_state(ctx); + + /* XXX should test internal format */ + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); + + if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset, + zoffset, postConvWidth, postConvHeight)) + return; + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + ASSERT(texImage); + + /* If we have a border, xoffset=-1 is legal. Bias by border width */ + xoffset += texImage->Border; + yoffset += texImage->Border; + zoffset += texImage->Border; + + ASSERT(ctx->Driver.CopyTexSubImage3D); + (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, + x, y, width, height); + ctx->NewState |= _NEW_TEXTURE; +} + + + + +/**********************************************************************/ +/****** Compressed Textures ******/ +/**********************************************************************/ + + +/** + * Error checking for glCompressedTexImage[123]D(). + * \return error code or GL_NO_ERROR. + */ +static GLenum +compressed_texture_error_check(GLcontext *ctx, GLint dimensions, + GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize) +{ + GLint expectedSize, maxLevels = 0, maxTextureSize; + + if (dimensions == 1) { + /* 1D compressed textures not allowed */ + return GL_INVALID_ENUM; + } + else if (dimensions == 2) { + if (target == GL_PROXY_TEXTURE_2D) { + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (target == GL_TEXTURE_2D) { + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) + return GL_INVALID_ENUM; /*target*/ + maxLevels = ctx->Const.MaxCubeTextureLevels; + } + else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) + return GL_INVALID_ENUM; /*target*/ + maxLevels = ctx->Const.MaxCubeTextureLevels; + } + else { + return GL_INVALID_ENUM; /*target*/ + } + } + else if (dimensions == 3) { + /* 3D compressed textures not allowed */ + return GL_INVALID_ENUM; + } + + maxTextureSize = 1 << (maxLevels - 1); + + if (!is_compressed_format(ctx, internalFormat)) + return GL_INVALID_ENUM; + + if (_mesa_base_tex_format(ctx, internalFormat) < 0) + return GL_INVALID_ENUM; + + if (border != 0) + return GL_INVALID_VALUE; + + /* + * XXX We should probably use the proxy texture error check function here. + */ + if (width < 1 || width > maxTextureSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1)) + return GL_INVALID_VALUE; + + if ((height < 1 || height > maxTextureSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1)) + && dimensions > 1) + return GL_INVALID_VALUE; + + if ((depth < 1 || depth > maxTextureSize || + (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1)) + && dimensions > 2) + return GL_INVALID_VALUE; + + /* For cube map, width must equal height */ + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) + return GL_INVALID_VALUE; + + if (level < 0 || level >= maxLevels) + return GL_INVALID_VALUE; + + expectedSize = ctx->Driver.CompressedTextureSize(ctx, width, height, depth, + internalFormat); + if (expectedSize != imageSize) + return GL_INVALID_VALUE; + + return GL_NO_ERROR; +} + + +/** + * Error checking for glCompressedTexSubImage[123]D(). + * \warning There are some bad assumptions here about the size of compressed + * texture tiles (multiple of 4) used to test the validity of the + * offset and size parameters. + * \return error code or GL_NO_ERROR. + */ +static GLenum +compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize) +{ + GLint expectedSize, maxLevels = 0, maxTextureSize; + (void) zoffset; + + if (dimensions == 1) { + /* 1D compressed textures not allowed */ + return GL_INVALID_ENUM; + } + else if (dimensions == 2) { + if (target == GL_PROXY_TEXTURE_2D) { + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (target == GL_TEXTURE_2D) { + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) + return GL_INVALID_ENUM; /*target*/ + maxLevels = ctx->Const.MaxCubeTextureLevels; + } + else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { + if (!ctx->Extensions.ARB_texture_cube_map) + return GL_INVALID_ENUM; /*target*/ + maxLevels = ctx->Const.MaxCubeTextureLevels; + } + else { + return GL_INVALID_ENUM; /*target*/ + } + } + else if (dimensions == 3) { + /* 3D compressed textures not allowed */ + return GL_INVALID_ENUM; + } + + maxTextureSize = 1 << (maxLevels - 1); + + if (!is_compressed_format(ctx, format)) + return GL_INVALID_ENUM; + + if (width < 1 || width > maxTextureSize) + return GL_INVALID_VALUE; + + if ((height < 1 || height > maxTextureSize) + && dimensions > 1) + return GL_INVALID_VALUE; + + if (level < 0 || level >= maxLevels) + return GL_INVALID_VALUE; + + /* XXX these tests are specific to the compressed format. + * this code should be generalized in some way. + */ + if ((xoffset & 3) != 0 || (yoffset & 3) != 0) + return GL_INVALID_VALUE; + + if ((width & 3) != 0 && width != 2 && width != 1) + return GL_INVALID_VALUE; + + if ((height & 3) != 0 && height != 2 && height != 1) + return GL_INVALID_VALUE; + + expectedSize = ctx->Driver.CompressedTextureSize(ctx, width, height, depth, + format); + if (expectedSize != imageSize) + return GL_INVALID_VALUE; + + return GL_NO_ERROR; +} + + + +void GLAPIENTRY +_mesa_CompressedTexImage1DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLint border, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target == GL_TEXTURE_1D) { + /* non-proxy target */ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLenum error = compressed_texture_error_check(ctx, 1, target, level, + internalFormat, width, 1, 1, border, imageSize); + if (error) { + _mesa_error(ctx, error, "glCompressedTexImage1D"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, + border, internalFormat); + + ASSERT(ctx->Driver.CompressedTexImage1D); + (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, + internalFormat, width, border, + imageSize, data, + texObj, texImage); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else if (target == GL_PROXY_TEXTURE_1D) { + /* Proxy texture: check for errors and update proxy state */ + GLenum error = compressed_texture_error_check(ctx, 1, target, level, + internalFormat, width, 1, 1, border, imageSize); + if (!error) { + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, GL_NONE, GL_NONE, + width, 1, 1, border); + } + if (error) { + /* if error, clear all proxy texture image parameters */ + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texImage) + clear_teximage_fields(texImage); + } + else { + /* store the teximage parameters */ + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, + border, internalFormat); + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_CompressedTexImage2DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, + const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target == GL_TEXTURE_2D || + (ctx->Extensions.ARB_texture_cube_map && + target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && + target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { + /* non-proxy target */ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLenum error = compressed_texture_error_check(ctx, 2, target, level, + internalFormat, width, height, 1, border, imageSize); + if (error) { + _mesa_error(ctx, error, "glCompressedTexImage2D"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, + border, internalFormat); + + ASSERT(ctx->Driver.CompressedTexImage2D); + (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, + internalFormat, width, height, + border, imageSize, data, + texObj, texImage); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else if (target == GL_PROXY_TEXTURE_2D || + (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && + ctx->Extensions.ARB_texture_cube_map)) { + /* Proxy texture: check for errors and update proxy state */ + GLenum error = compressed_texture_error_check(ctx, 2, target, level, + internalFormat, width, height, 1, border, imageSize); + if (!error) { + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, GL_NONE, GL_NONE, + width, height, 1, border); + } + if (error) { + /* if error, clear all proxy texture image parameters */ + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texImage) + clear_teximage_fields(texImage); + } + else { + /* store the teximage parameters */ + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, + border, internalFormat); + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_CompressedTexImage3DARB(GLenum target, GLint level, + GLenum internalFormat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid *data) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (target == GL_TEXTURE_3D) { + /* non-proxy target */ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLenum error = compressed_texture_error_check(ctx, 3, target, level, + internalFormat, width, height, depth, border, imageSize); + if (error) { + _mesa_error(ctx, error, "glCompressedTexImage3D"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_get_tex_image(ctx, texUnit, target, level); + if (!texImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); + return; + } + else if (texImage->Data) { + ctx->Driver.FreeTexImageData( ctx, texImage ); + } + ASSERT(texImage->Data == NULL); + + _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, + border, internalFormat); + + ASSERT(ctx->Driver.CompressedTexImage3D); + (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, + internalFormat, + width, height, depth, + border, imageSize, data, + texObj, texImage); + + /* state update */ + texObj->Complete = GL_FALSE; + ctx->NewState |= _NEW_TEXTURE; + } + else if (target == GL_PROXY_TEXTURE_3D) { + /* Proxy texture: check for errors and update proxy state */ + GLenum error = compressed_texture_error_check(ctx, 3, target, level, + internalFormat, width, height, depth, border, imageSize); + if (!error) { + ASSERT(ctx->Driver.TestProxyTexImage); + error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, + internalFormat, GL_NONE, GL_NONE, + width, height, depth, border); + } + if (error) { + /* if error, clear all proxy texture image parameters */ + struct gl_texture_image *texImage; + texImage = _mesa_get_proxy_tex_image(ctx, target, level); + if (texImage) + clear_teximage_fields(texImage); + } + else { + /* store the teximage parameters */ + struct gl_texture_unit *texUnit; + struct gl_texture_image *texImage; + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + _mesa_init_teximage_fields(ctx, target, texImage, width, height, + depth, border, internalFormat); + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLenum error; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + error = compressed_subtexture_error_check(ctx, 1, target, level, + xoffset, 0, 0, width, 1, 1, format, imageSize); + if (error) { + _mesa_error(ctx, error, "glCompressedTexSubImage1D"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + assert(texImage); + + if ((GLint) format != texImage->IntFormat) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTexSubImage1D(format)"); + return; + } + + if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); + return; + } + + if (width == 0) + return; /* no-op, not an error */ + + if (ctx->Driver.CompressedTexSubImage1D) { + (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, + xoffset, width, + format, imageSize, data, + texObj, texImage); + } + ctx->NewState |= _NEW_TEXTURE; +} + + +void GLAPIENTRY +_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLenum error; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + error = compressed_subtexture_error_check(ctx, 2, target, level, + xoffset, yoffset, 0, width, height, 1, format, imageSize); + if (error) { + /* XXX proxy target? */ + _mesa_error(ctx, error, "glCompressedTexSubImage2D"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + assert(texImage); + + if ((GLint) format != texImage->IntFormat) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTexSubImage2D(format)"); + return; + } + + if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || + ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); + return; + } + + if (width == 0 || height == 0) + return; /* no-op, not an error */ + + if (ctx->Driver.CompressedTexSubImage2D) { + (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, + xoffset, yoffset, width, height, + format, imageSize, data, + texObj, texImage); + } + ctx->NewState |= _NEW_TEXTURE; +} + + +void GLAPIENTRY +_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + struct gl_texture_unit *texUnit; + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLenum error; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + error = compressed_subtexture_error_check(ctx, 3, target, level, + xoffset, yoffset, zoffset, width, height, depth, format, imageSize); + if (error) { + _mesa_error(ctx, error, "glCompressedTexSubImage2D"); + return; + } + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + assert(texImage); + + if ((GLint) format != texImage->IntFormat) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCompressedTexSubImage3D(format)"); + return; + } + + if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || + ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || + ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); + return; + } + + if (width == 0 || height == 0 || depth == 0) + return; /* no-op, not an error */ + + if (ctx->Driver.CompressedTexSubImage3D) { + (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, imageSize, data, + texObj, texImage); + } + ctx->NewState |= _NEW_TEXTURE; +} + + +void GLAPIENTRY +_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) +{ + const struct gl_texture_unit *texUnit; + const struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + GLint maxLevels; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + texObj = _mesa_select_tex_object(ctx, texUnit, target); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); + return; + } + + maxLevels = _mesa_max_texture_levels(ctx, target); + ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ + + if (level < 0 || level >= maxLevels) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); + return; + } + + if (is_proxy_target(target)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); + return; + } + + texImage = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!texImage) { + /* probably invalid mipmap level */ + _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); + return; + } + + if (!texImage->IsCompressed) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); + return; + } + + /* this typically calls _mesa_get_compressed_teximage() */ + ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage); +} diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h new file mode 100644 index 00000000000..45c851e5c88 --- /dev/null +++ b/src/mesa/main/teximage.h @@ -0,0 +1,239 @@ +/** + * \file teximage.h + * Texture images manipulation functions. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef TEXIMAGE_H +#define TEXIMAGE_H + + +#include "mtypes.h" + + +extern void * +_mesa_alloc_texmemory(GLsizei bytes); + +extern void +_mesa_free_texmemory(void *m); + + +/** \name Internal functions */ +/*@{*/ + +extern GLint +_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ); + + +extern struct gl_texture_image * +_mesa_new_texture_image( GLcontext *ctx ); + + +extern void +_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *teximage ); + + +extern void +_mesa_free_texture_image_data( GLcontext *ctx, + struct gl_texture_image *texImage ); + + +extern void +_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, + struct gl_texture_image *img, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum internalFormat); + + +extern void +_mesa_set_tex_image(struct gl_texture_object *tObj, + GLenum target, GLint level, + struct gl_texture_image *texImage); + + +extern struct gl_texture_object * +_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target); + + +extern struct gl_texture_image * +_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target, GLint level); + + +extern struct gl_texture_image * +_mesa_get_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, + GLenum target, GLint level); + + +extern struct gl_texture_image * +_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level); + + +extern GLint +_mesa_max_texture_levels(GLcontext *ctx, GLenum target); + + +extern GLboolean +_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border); + +/*@}*/ + + +/** \name API entry point functions */ +/*@{*/ + +extern void GLAPIENTRY +_mesa_TexImage1D( GLenum target, GLint level, GLint internalformat, + GLsizei width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexImage2D( GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexImage3D( GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLsizei depth, GLint border, + GLenum format, GLenum type, const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_GetTexImage( GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexSubImage1D( GLenum target, GLint level, GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_TexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid *pixels ); + + +extern void GLAPIENTRY +_mesa_CopyTexImage1D( GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLint border ); + + +extern void GLAPIENTRY +_mesa_CopyTexImage2D( GLenum target, GLint level, + GLenum internalformat, GLint x, GLint y, + GLsizei width, GLsizei height, GLint border ); + + +extern void GLAPIENTRY +_mesa_CopyTexSubImage1D( GLenum target, GLint level, GLint xoffset, + GLint x, GLint y, GLsizei width ); + + +extern void GLAPIENTRY +_mesa_CopyTexSubImage2D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height ); + + +extern void GLAPIENTRY +_mesa_CopyTexSubImage3D( GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height ); + + + +extern void GLAPIENTRY +_mesa_CompressedTexImage1DARB(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLint border, GLsizei imageSize, + const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexImage2DARB(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLint border, GLsizei imageSize, + const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexImage3DARB(GLenum target, GLint level, + GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, GLint border, + GLsizei imageSize, const GLvoid *data); + +#ifdef VMS +#define _mesa_CompressedTexSubImage1DARB _mesa_CompressedTexSubImage1DAR +#define _mesa_CompressedTexSubImage2DARB _mesa_CompressedTexSubImage2DAR +#define _mesa_CompressedTexSubImage3DARB _mesa_CompressedTexSubImage3DAR +#endif +extern void GLAPIENTRY +_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, + GLsizei width, GLenum format, + GLsizei imageSize, const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, + const GLvoid *data); + +extern void GLAPIENTRY +_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const GLvoid *data); + +extern void GLAPIENTRY +_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img); + +/*@}*/ + +#endif diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c new file mode 100644 index 00000000000..5594cd9382b --- /dev/null +++ b/src/mesa/main/texobj.c @@ -0,0 +1,1000 @@ +/** + * \file texobj.c + * Texture object management. + */ + +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "colortab.h" +#include "context.h" +#include "enums.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "teximage.h" +#include "texstate.h" +#include "texobj.h" +#include "mtypes.h" + + +/**********************************************************************/ +/** \name Internal functions */ +/*@{*/ + +/** + * Allocate and initialize a new texture object. But don't put it into the + * texture object hash table. + * + * Called via ctx->Driver.NewTextureObject, unless overridden by a device + * driver. + * + * \param shared the shared GL state structure to contain the texture object + * \param name integer name for the texture object + * \param target either GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, + * GL_TEXTURE_CUBE_MAP_ARB or GL_TEXTURE_RECTANGLE_NV. zero is ok for the sake + * of GenTextures() + * + * \return pointer to new texture object. + */ +struct gl_texture_object * +_mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target ) +{ + struct gl_texture_object *obj; + (void) ctx; + obj = MALLOC_STRUCT(gl_texture_object); + _mesa_initialize_texture_object(obj, name, target); + return obj; +} + + +/** + * Initialize a new texture object to default values. + * \param obj the texture object + * \param name the texture name + * \param target the texture target + */ +void +_mesa_initialize_texture_object( struct gl_texture_object *obj, + GLuint name, GLenum target ) +{ + ASSERT(target == 0 || + target == GL_TEXTURE_1D || + target == GL_TEXTURE_2D || + target == GL_TEXTURE_3D || + target == GL_TEXTURE_CUBE_MAP_ARB || + target == GL_TEXTURE_RECTANGLE_NV); + + _mesa_bzero(obj, sizeof(*obj)); + /* init the non-zero fields */ + _glthread_INIT_MUTEX(obj->Mutex); + obj->RefCount = 1; + obj->Name = name; + obj->Target = target; + obj->Priority = 1.0F; + if (target == GL_TEXTURE_RECTANGLE_NV) { + obj->WrapS = GL_CLAMP_TO_EDGE; + obj->WrapT = GL_CLAMP_TO_EDGE; + obj->WrapR = GL_CLAMP_TO_EDGE; + obj->MinFilter = GL_LINEAR; + } + else { + obj->WrapS = GL_REPEAT; + obj->WrapT = GL_REPEAT; + obj->WrapR = GL_REPEAT; + obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR; + } + obj->MagFilter = GL_LINEAR; + obj->MinLod = -1000.0; + obj->MaxLod = 1000.0; + obj->LodBias = 0.0; + obj->BaseLevel = 0; + obj->MaxLevel = 1000; + obj->MaxAnisotropy = 1.0; + obj->CompareFlag = GL_FALSE; /* SGIX_shadow */ + obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX; /* SGIX_shadow */ + obj->CompareMode = GL_NONE; /* ARB_shadow */ + obj->CompareFunc = GL_LEQUAL; /* ARB_shadow */ + obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */ + obj->ShadowAmbient = 0.0F; /* ARB/SGIX_shadow_ambient */ + _mesa_init_colortable(&obj->Palette); +} + + +/** + * Deallocate a texture object struct. It should have already been + * removed from the texture object pool. + * + * \param shared the shared GL state to which the object belongs. + * \param texOjb the texture object to delete. + */ +void +_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *texObj ) +{ + GLuint i, face; + + (void) ctx; + + _mesa_free_colortable_data(&texObj->Palette); + + /* free the texture images */ + for (face = 0; face < 6; face++) { + for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { + if (texObj->Image[face][i]) { + _mesa_delete_texture_image( ctx, texObj->Image[face][i] ); + } + } + } + + /* destroy the mutex -- it may have allocated memory (eg on bsd) */ + _glthread_DESTROY_MUTEX(texObj->Mutex); + + /* free this object */ + _mesa_free(texObj); +} + + + + +/** + * Copy texture object state from one texture object to another. + * Use for glPush/PopAttrib. + * + * \param dest destination texture object. + * \param src source texture object. + */ +void +_mesa_copy_texture_object( struct gl_texture_object *dest, + const struct gl_texture_object *src ) +{ + dest->Name = src->Name; + dest->Priority = src->Priority; + dest->BorderColor[0] = src->BorderColor[0]; + dest->BorderColor[1] = src->BorderColor[1]; + dest->BorderColor[2] = src->BorderColor[2]; + dest->BorderColor[3] = src->BorderColor[3]; + dest->WrapS = src->WrapS; + dest->WrapT = src->WrapT; + dest->WrapR = src->WrapR; + dest->MinFilter = src->MinFilter; + dest->MagFilter = src->MagFilter; + dest->MinLod = src->MinLod; + dest->MaxLod = src->MaxLod; + dest->LodBias = src->LodBias; + dest->BaseLevel = src->BaseLevel; + dest->MaxLevel = src->MaxLevel; + dest->MaxAnisotropy = src->MaxAnisotropy; + dest->CompareFlag = src->CompareFlag; + dest->CompareOperator = src->CompareOperator; + dest->ShadowAmbient = src->ShadowAmbient; + dest->CompareMode = src->CompareMode; + dest->CompareFunc = src->CompareFunc; + dest->DepthMode = src->DepthMode; + dest->_MaxLevel = src->_MaxLevel; + dest->_MaxLambda = src->_MaxLambda; + dest->GenerateMipmap = src->GenerateMipmap; + dest->Palette = src->Palette; + dest->Complete = src->Complete; + dest->_IsPowerOfTwo = src->_IsPowerOfTwo; +} + + +/** + * Report why a texture object is incomplete. + * + * \param t texture object. + * \param why string describing why it's incomplete. + * + * \note For debug purposes only. + */ +#if 0 +static void +incomplete(const struct gl_texture_object *t, const char *why) +{ + _mesa_printf("Texture Obj %d incomplete because: %s\n", t->Name, why); +} +#else +#define incomplete(t, why) +#endif + + +/** + * Examine a texture object to determine if it is complete. + * + * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE + * accordingly. + * + * \param ctx GL context. + * \param t texture object. + * + * According to the texture target, verifies that each of the mipmaps is + * present and has the expected size. + */ +void +_mesa_test_texobj_completeness( const GLcontext *ctx, + struct gl_texture_object *t ) +{ + const GLint baseLevel = t->BaseLevel; + GLint maxLog2 = 0, maxLevels = 0; + + t->Complete = GL_TRUE; /* be optimistic */ + t->_IsPowerOfTwo = GL_TRUE; /* may be set FALSE below */ + + /* Always need the base level image */ + if (!t->Image[0][baseLevel]) { + char s[100]; + sprintf(s, "obj %p (%d) Image[baseLevel=%d] == NULL", + (void *) t, t->Name, baseLevel); + incomplete(t, s); + t->Complete = GL_FALSE; + return; + } + + /* Check width/height/depth for zero */ + if (t->Image[0][baseLevel]->Width == 0 || + t->Image[0][baseLevel]->Height == 0 || + t->Image[0][baseLevel]->Depth == 0) { + incomplete(t, "texture width = 0"); + t->Complete = GL_FALSE; + return; + } + + /* Compute _MaxLevel */ + if (t->Target == GL_TEXTURE_1D) { + maxLog2 = t->Image[0][baseLevel]->WidthLog2; + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (t->Target == GL_TEXTURE_2D) { + maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2, + t->Image[0][baseLevel]->HeightLog2); + maxLevels = ctx->Const.MaxTextureLevels; + } + else if (t->Target == GL_TEXTURE_3D) { + GLint max = MAX2(t->Image[0][baseLevel]->WidthLog2, + t->Image[0][baseLevel]->HeightLog2); + maxLog2 = MAX2(max, (GLint)(t->Image[0][baseLevel]->DepthLog2)); + maxLevels = ctx->Const.Max3DTextureLevels; + } + else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { + maxLog2 = MAX2(t->Image[0][baseLevel]->WidthLog2, + t->Image[0][baseLevel]->HeightLog2); + maxLevels = ctx->Const.MaxCubeTextureLevels; + } + else if (t->Target == GL_TEXTURE_RECTANGLE_NV) { + maxLog2 = 0; /* not applicable */ + maxLevels = 1; /* no mipmapping */ + } + else { + _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness"); + return; + } + + ASSERT(maxLevels > 0); + + t->_MaxLevel = baseLevel + maxLog2; + t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel); + t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); + + /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */ + t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel); + + if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { + /* make sure that all six cube map level 0 images are the same size */ + const GLuint w = t->Image[0][baseLevel]->Width2; + const GLuint h = t->Image[0][baseLevel]->Height2; + GLuint face; + for (face = 1; face < 6; face++) { + if (t->Image[face][baseLevel] == NULL || + t->Image[face][baseLevel]->Width2 != w || + t->Image[face][baseLevel]->Height2 != h) { + t->Complete = GL_FALSE; + incomplete(t, "Non-quare cubemap image"); + return; + } + } + } + + /* check for non power of two */ + if (!t->Image[0][baseLevel]->_IsPowerOfTwo) { + t->_IsPowerOfTwo = GL_FALSE; + } + + /* extra checking for mipmaps */ + if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) { + /* + * Mipmapping: determine if we have a complete set of mipmaps + */ + GLint i; + GLint minLevel = baseLevel; + GLint maxLevel = t->_MaxLevel; + + if (minLevel > maxLevel) { + t->Complete = GL_FALSE; + incomplete(t, "minLevel > maxLevel"); + return; + } + + /* Test dimension-independent attributes */ + for (i = minLevel; i <= maxLevel; i++) { + if (t->Image[0][i]) { + if (t->Image[0][i]->TexFormat != t->Image[0][baseLevel]->TexFormat) { + t->Complete = GL_FALSE; + incomplete(t, "Format[i] != Format[baseLevel]"); + return; + } + if (t->Image[0][i]->Border != t->Image[0][baseLevel]->Border) { + t->Complete = GL_FALSE; + incomplete(t, "Border[i] != Border[baseLevel]"); + return; + } + } + } + + /* Test things which depend on number of texture image dimensions */ + if (t->Target == GL_TEXTURE_1D) { + /* Test 1-D mipmaps */ + GLuint width = t->Image[0][baseLevel]->Width2; + for (i = baseLevel + 1; i < maxLevels; i++) { + if (width > 1) { + width /= 2; + } + if (i >= minLevel && i <= maxLevel) { + if (!t->Image[0][i]) { + t->Complete = GL_FALSE; + incomplete(t, "1D Image[0][i] == NULL"); + return; + } + if (t->Image[0][i]->Width2 != width ) { + t->Complete = GL_FALSE; + incomplete(t, "1D Image[0][i] bad width"); + return; + } + } + if (width == 1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + else if (t->Target == GL_TEXTURE_2D) { + /* Test 2-D mipmaps */ + GLuint width = t->Image[0][baseLevel]->Width2; + GLuint height = t->Image[0][baseLevel]->Height2; + for (i = baseLevel + 1; i < maxLevels; i++) { + if (width > 1) { + width /= 2; + } + if (height > 1) { + height /= 2; + } + if (i >= minLevel && i <= maxLevel) { + if (!t->Image[0][i]) { + t->Complete = GL_FALSE; + incomplete(t, "2D Image[0][i] == NULL"); + return; + } + if (t->Image[0][i]->Width2 != width) { + t->Complete = GL_FALSE; + incomplete(t, "2D Image[0][i] bad width"); + return; + } + if (t->Image[0][i]->Height2 != height) { + t->Complete = GL_FALSE; + incomplete(t, "2D Image[0][i] bad height"); + return; + } + if (width==1 && height==1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + } + else if (t->Target == GL_TEXTURE_3D) { + /* Test 3-D mipmaps */ + GLuint width = t->Image[0][baseLevel]->Width2; + GLuint height = t->Image[0][baseLevel]->Height2; + GLuint depth = t->Image[0][baseLevel]->Depth2; + for (i = baseLevel + 1; i < maxLevels; i++) { + if (width > 1) { + width /= 2; + } + if (height > 1) { + height /= 2; + } + if (depth > 1) { + depth /= 2; + } + if (i >= minLevel && i <= maxLevel) { + if (!t->Image[0][i]) { + incomplete(t, "3D Image[0][i] == NULL"); + t->Complete = GL_FALSE; + return; + } + if (t->Image[0][i]->Format == GL_DEPTH_COMPONENT) { + t->Complete = GL_FALSE; + incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); + return; + } + if (t->Image[0][i]->Width2 != width) { + t->Complete = GL_FALSE; + incomplete(t, "3D Image[0][i] bad width"); + return; + } + if (t->Image[0][i]->Height2 != height) { + t->Complete = GL_FALSE; + incomplete(t, "3D Image[0][i] bad height"); + return; + } + if (t->Image[0][i]->Depth2 != depth) { + t->Complete = GL_FALSE; + incomplete(t, "3D Image[0][i] bad depth"); + return; + } + } + if (width == 1 && height == 1 && depth == 1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { + /* make sure 6 cube faces are consistant */ + GLuint width = t->Image[0][baseLevel]->Width2; + GLuint height = t->Image[0][baseLevel]->Height2; + for (i = baseLevel + 1; i < maxLevels; i++) { + if (width > 1) { + width /= 2; + } + if (height > 1) { + height /= 2; + } + if (i >= minLevel && i <= maxLevel) { + GLuint face; + for (face = 0; face < 6; face++) { + /* check that we have images defined */ + if (!t->Image[face][i]) { + t->Complete = GL_FALSE; + incomplete(t, "CubeMap Image[n][i] == NULL"); + return; + } + /* Don't support GL_DEPTH_COMPONENT for cube maps */ + if (t->Image[face][i]->Format == GL_DEPTH_COMPONENT) { + t->Complete = GL_FALSE; + incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); + return; + } + /* check that all six images have same size */ + if (t->Image[face][i]->Width2!=width || + t->Image[face][i]->Height2!=height) { + t->Complete = GL_FALSE; + incomplete(t, "CubeMap Image[n][i] bad size"); + return; + } + } + } + if (width == 1 && height == 1) { + return; /* found smallest needed mipmap, all done! */ + } + } + } + else if (t->Target == GL_TEXTURE_RECTANGLE_NV) { + /* XXX special checking? */ + } + else { + /* Target = ??? */ + _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n"); + } + } +} + +/*@}*/ + + +/***********************************************************************/ +/** \name API functions */ +/*@{*/ + +/** + * Texture name generation lock. + * + * Used by _mesa_GenTextures() to guarantee that the generation and allocation + * of texture IDs is atomic. + */ +_glthread_DECLARE_STATIC_MUTEX(GenTexturesLock); + +/** + * Generate texture names. + * + * \param n number of texture names to be generated. + * \param textures an array in which will hold the generated texture names. + * + * \sa glGenTextures(). + * + * While holding the GenTexturesLock lock, calls _mesa_HashFindFreeKeyBlock() + * to find a block of free texture IDs which are stored in \p textures. + * Corresponding empty texture objects are also generated. + */ +void GLAPIENTRY +_mesa_GenTextures( GLsizei n, GLuint *textures ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + GLint i; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glGenTextures" ); + return; + } + + if (!textures) + return; + + /* + * This must be atomic (generation and allocation of texture IDs) + */ + _glthread_LOCK_MUTEX(GenTexturesLock); + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->TexObjects, n); + + /* Allocate new, empty texture objects */ + for (i = 0; i < n; i++) { + struct gl_texture_object *texObj; + GLuint name = first + i; + GLenum target = 0; + texObj = (*ctx->Driver.NewTextureObject)( ctx, name, target); + if (!texObj) { + _glthread_UNLOCK_MUTEX(GenTexturesLock); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenTextures"); + return; + } + + /* insert into hash table */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + textures[i] = name; + } + + _glthread_UNLOCK_MUTEX(GenTexturesLock); +} + + +/** + * Delete named textures. + * + * \param n number of textures to be deleted. + * \param textures array of texture IDs to be deleted. + * + * \sa glDeleteTextures(). + * + * If we're about to delete a texture that's currently bound to any + * texture unit, unbind the texture first. Decrement the reference + * count on the texture object and delete it if it's zero. + * Recall that texture objects can be shared among several rendering + * contexts. + */ +void GLAPIENTRY +_mesa_DeleteTextures( GLsizei n, const GLuint *textures) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); /* too complex */ + + if (!textures) + return; + + for (i = 0; i < n; i++) { + if (textures[i] > 0) { + struct gl_texture_object *delObj = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, textures[i]); + if (delObj) { + /* First check if this texture is currently bound. + * If so, unbind it and decrement the reference count. + * XXX all RefCount accesses should be protected by a mutex. + */ + GLuint u; + for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) { + struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; + if (delObj == unit->Current1D) { + unit->Current1D = ctx->Shared->Default1D; + ctx->Shared->Default1D->RefCount++; + delObj->RefCount--; + if (delObj == unit->_Current) + unit->_Current = unit->Current1D; + } + else if (delObj == unit->Current2D) { + unit->Current2D = ctx->Shared->Default2D; + ctx->Shared->Default2D->RefCount++; + delObj->RefCount--; + if (delObj == unit->_Current) + unit->_Current = unit->Current2D; + } + else if (delObj == unit->Current3D) { + unit->Current3D = ctx->Shared->Default3D; + ctx->Shared->Default3D->RefCount++; + delObj->RefCount--; + if (delObj == unit->_Current) + unit->_Current = unit->Current3D; + } + else if (delObj == unit->CurrentCubeMap) { + unit->CurrentCubeMap = ctx->Shared->DefaultCubeMap; + ctx->Shared->DefaultCubeMap->RefCount++; + delObj->RefCount--; + if (delObj == unit->_Current) + unit->_Current = unit->CurrentCubeMap; + } + else if (delObj == unit->CurrentRect) { + unit->CurrentRect = ctx->Shared->DefaultRect; + ctx->Shared->DefaultRect->RefCount++; + delObj->RefCount--; + if (delObj == unit->_Current) + unit->_Current = unit->CurrentRect; + } + } + ctx->NewState |= _NEW_TEXTURE; + + /* The texture _name_ is now free for re-use. + * Remove it from the hash table now. + */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashRemove(ctx->Shared->TexObjects, delObj->Name); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + /* The actual texture object will not be freed until it's no + * longer bound in any context. + * XXX all RefCount accesses should be protected by a mutex. + */ + delObj->RefCount--; + if (delObj->RefCount == 0) { + ASSERT(delObj->Name != 0); /* Never delete default tex objs */ + ASSERT(ctx->Driver.DeleteTexture); + (*ctx->Driver.DeleteTexture)(ctx, delObj); + } + } + } + } +} + + +/** + * Bind a named texture to a texturing target. + * + * \param target texture target. + * \param texName texture name. + * + * \sa glBindTexture(). + * + * Determines the old texture object bound and returns immediately if rebinding + * the same texture. Get the current texture which is either a default texture + * if name is null, a named texture from the hash, or a new texture if the + * given texture name is new. Increments its reference count, binds it, and + * calls dd_function_table::BindTexture. Decrements the old texture reference + * count and deletes it if it reaches zero. + */ +void GLAPIENTRY +_mesa_BindTexture( GLenum target, GLuint texName ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *oldTexObj; + struct gl_texture_object *newTexObj = NULL; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glBindTexture %s %d\n", + _mesa_lookup_enum_by_nr(target), (GLint) texName); + + /* + * Get pointer to currently bound texture object (oldTexObj) + */ + switch (target) { + case GL_TEXTURE_1D: + oldTexObj = texUnit->Current1D; + break; + case GL_TEXTURE_2D: + oldTexObj = texUnit->Current2D; + break; + case GL_TEXTURE_3D: + oldTexObj = texUnit->Current3D; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" ); + return; + } + oldTexObj = texUnit->CurrentCubeMap; + break; + case GL_TEXTURE_RECTANGLE_NV: + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" ); + return; + } + oldTexObj = texUnit->CurrentRect; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glBindTexture(target)" ); + return; + } + + if (oldTexObj->Name == texName) + /* XXX this might be wrong. If the texobj is in use by another + * context and a texobj parameter was changed, this might be our + * only chance to update this context's hardware state. + */ + return; /* rebinding the same texture- no change */ + + /* + * Get pointer to new texture object (newTexObj) + */ + if (texName == 0) { + /* newTexObj = a default texture object */ + switch (target) { + case GL_TEXTURE_1D: + newTexObj = ctx->Shared->Default1D; + break; + case GL_TEXTURE_2D: + newTexObj = ctx->Shared->Default2D; + break; + case GL_TEXTURE_3D: + newTexObj = ctx->Shared->Default3D; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + newTexObj = ctx->Shared->DefaultCubeMap; + break; + case GL_TEXTURE_RECTANGLE_NV: + newTexObj = ctx->Shared->DefaultRect; + break; + default: + ; /* Bad targets are caught above */ + } + } + else { + /* non-default texture object */ + const struct _mesa_HashTable *hash = ctx->Shared->TexObjects; + newTexObj = (struct gl_texture_object *) _mesa_HashLookup(hash, texName); + if (newTexObj) { + /* error checking */ + if (newTexObj->Target != 0 && newTexObj->Target != target) { + /* the named texture object's dimensions don't match the target */ + _mesa_error( ctx, GL_INVALID_OPERATION, + "glBindTexture(wrong dimensionality)" ); + return; + } + if (newTexObj->Target == 0 && target == GL_TEXTURE_RECTANGLE_NV) { + /* have to init wrap and filter state here - kind of klunky */ + newTexObj->WrapS = GL_CLAMP_TO_EDGE; + newTexObj->WrapT = GL_CLAMP_TO_EDGE; + newTexObj->WrapR = GL_CLAMP_TO_EDGE; + newTexObj->MinFilter = GL_LINEAR; + if (ctx->Driver.TexParameter) { + static const GLfloat fparam_wrap[1] = {(GLfloat) GL_CLAMP_TO_EDGE}; + static const GLfloat fparam_filter[1] = {(GLfloat) GL_LINEAR}; + (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_S, fparam_wrap ); + (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_T, fparam_wrap ); + (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_WRAP_R, fparam_wrap ); + (*ctx->Driver.TexParameter)( ctx, target, newTexObj, GL_TEXTURE_MIN_FILTER, fparam_filter ); + } + } + } + else { + /* if this is a new texture id, allocate a texture object now */ + newTexObj = (*ctx->Driver.NewTextureObject)(ctx, texName, target); + if (!newTexObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindTexture"); + return; + } + + /* and insert it into hash table */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->TexObjects, texName, newTexObj); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } + newTexObj->Target = target; + } + + /* XXX all RefCount accesses should be protected by a mutex. */ + newTexObj->RefCount++; + + /* do the actual binding, but first flush outstanding vertices: + */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + + switch (target) { + case GL_TEXTURE_1D: + texUnit->Current1D = newTexObj; + break; + case GL_TEXTURE_2D: + texUnit->Current2D = newTexObj; + break; + case GL_TEXTURE_3D: + texUnit->Current3D = newTexObj; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + texUnit->CurrentCubeMap = newTexObj; + break; + case GL_TEXTURE_RECTANGLE_NV: + texUnit->CurrentRect = newTexObj; + break; + default: + _mesa_problem(ctx, "bad target in BindTexture"); + return; + } + + /* Pass BindTexture call to device driver */ + if (ctx->Driver.BindTexture) + (*ctx->Driver.BindTexture)( ctx, target, newTexObj ); + + /* Decrement the reference count on the old texture and check if it's + * time to delete it. + */ + /* XXX all RefCount accesses should be protected by a mutex. */ + oldTexObj->RefCount--; + ASSERT(oldTexObj->RefCount >= 0); + if (oldTexObj->RefCount == 0) { + ASSERT(oldTexObj->Name != 0); + ASSERT(ctx->Driver.DeleteTexture); + (*ctx->Driver.DeleteTexture)( ctx, oldTexObj ); + } +} + + +/** + * Set texture priorities. + * + * \param n number of textures. + * \param texName texture names. + * \param priorities corresponding texture priorities. + * + * \sa glPrioritizeTextures(). + * + * Looks up each texture in the hash, clamps the corresponding priority between + * 0.0 and 1.0, and calls dd_function_table::PrioritizeTexture. + */ +void GLAPIENTRY +_mesa_PrioritizeTextures( GLsizei n, const GLuint *texName, + const GLclampf *priorities ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (n < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" ); + return; + } + + if (!priorities) + return; + + for (i = 0; i < n; i++) { + if (texName[i] > 0) { + struct gl_texture_object *t = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]); + if (t) { + t->Priority = CLAMP( priorities[i], 0.0F, 1.0F ); + if (ctx->Driver.PrioritizeTexture) + ctx->Driver.PrioritizeTexture( ctx, t, t->Priority ); + } + } + } + + ctx->NewState |= _NEW_TEXTURE; +} + +/** + * See if textures are loaded in texture memory. + * + * \param n number of textures to query. + * \param texName array with the texture names. + * \param residences array which will hold the residence status. + * + * \return GL_TRUE if all textures are resident and \p residences is left unchanged, + * + * \sa glAreTexturesResident(). + * + * Looks up each texture in the hash and calls + * dd_function_table::IsTextureResident. + */ +GLboolean GLAPIENTRY +_mesa_AreTexturesResident(GLsizei n, const GLuint *texName, + GLboolean *residences) +{ + GET_CURRENT_CONTEXT(ctx); + GLboolean allResident = GL_TRUE; + GLint i, j; + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)"); + return GL_FALSE; + } + + if (!texName || !residences) + return GL_FALSE; + + for (i = 0; i < n; i++) { + struct gl_texture_object *t; + if (texName[i] == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); + return GL_FALSE; + } + t = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texName[i]); + if (!t) { + _mesa_error(ctx, GL_INVALID_VALUE, "glAreTexturesResident"); + return GL_FALSE; + } + if (!ctx->Driver.IsTextureResident || + ctx->Driver.IsTextureResident(ctx, t)) { + /* The texture is resident */ + if (!allResident) + residences[i] = GL_TRUE; + } + else { + /* The texture is not resident */ + if (allResident) { + allResident = GL_FALSE; + for (j = 0; j < i; j++) + residences[j] = GL_TRUE; + } + residences[i] = GL_FALSE; + } + } + + return allResident; +} + +/** + * See if a name corresponds to a texture. + * + * \param texture texture name. + * + * \return GL_TRUE if texture name corresponds to a texture, or GL_FALSE + * otherwise. + * + * \sa glIsTexture(). + * + * Calls _mesa_HashLookup(). + */ +GLboolean GLAPIENTRY +_mesa_IsTexture( GLuint texture ) +{ + struct gl_texture_object *t; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (!texture) + return GL_FALSE; + + t = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texture); + + /* IsTexture is true only after object has been bound once. */ + return t && t->Target; +} + +/*@}*/ diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h new file mode 100644 index 00000000000..d00bf70a0d1 --- /dev/null +++ b/src/mesa/main/texobj.h @@ -0,0 +1,95 @@ +/** + * \file texobj.h + * Texture object management. + */ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef TEXTOBJ_H +#define TEXTOBJ_H + + +#include "mtypes.h" + + +/** + * \name Internal functions + */ +/*@{*/ + +extern struct gl_texture_object * +_mesa_new_texture_object( GLcontext *ctx, GLuint name, GLenum target ); + +extern void +_mesa_initialize_texture_object( struct gl_texture_object *obj, + GLuint name, GLenum target ); + +extern void +_mesa_delete_texture_object( GLcontext *ctx, struct gl_texture_object *obj ); + +extern void +_mesa_copy_texture_object( struct gl_texture_object *dest, + const struct gl_texture_object *src ); + +extern void +_mesa_test_texobj_completeness( const GLcontext *ctx, + struct gl_texture_object *obj ); + +/*@}*/ + + +/** + * \name API functions + */ +/*@{*/ + +extern void GLAPIENTRY +_mesa_GenTextures( GLsizei n, GLuint *textures ); + + +extern void GLAPIENTRY +_mesa_DeleteTextures( GLsizei n, const GLuint *textures ); + + +extern void GLAPIENTRY +_mesa_BindTexture( GLenum target, GLuint texture ); + + +extern void GLAPIENTRY +_mesa_PrioritizeTextures( GLsizei n, const GLuint *textures, + const GLclampf *priorities ); + + +extern GLboolean GLAPIENTRY +_mesa_AreTexturesResident( GLsizei n, const GLuint *textures, + GLboolean *residences ); + +extern GLboolean GLAPIENTRY +_mesa_IsTexture( GLuint texture ); + +/*@}*/ + +#endif diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c new file mode 100644 index 00000000000..92f3f7377db --- /dev/null +++ b/src/mesa/main/texrender.c @@ -0,0 +1,226 @@ + +#include "context.h" +#include "fbobject.h" +#include "texrender.h" +#include "renderbuffer.h" + + +/* + * Render-to-texture code for GL_EXT_framebuffer_object + */ + + +/** + * Derived from gl_renderbuffer class + */ +struct texture_renderbuffer +{ + struct gl_renderbuffer Base; /* Base class object */ + struct gl_texture_image *TexImage; + StoreTexelFunc Store; + GLint Zoffset; +}; + + + +static void +texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + GLchan *rgbaOut = (GLchan *) values; + GLuint i; + for (i = 0; i < count; i++) { + trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i); + } +} + +static void +texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + GLchan *rgbaOut = (GLchan *) values; + GLuint i; + for (i = 0; i < count; i++) { + trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i], z, + rgbaOut + 4 * i); + } +} + +static void +texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) values; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, rgba); + } + rgba += 4; + } +} + +static void +texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) value; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, rgba); + } + } +} + +static void +texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) values; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, rgba); + } + rgba += 4; + } +} + +static void +texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) value; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, rgba); + } + } +} + + +static void +delete_texture_wrapper(struct gl_renderbuffer *rb) +{ + _mesa_free(rb); +} + + +/** + * If a render buffer attachment specifies a texture image, we'll use + * this function to make a gl_renderbuffer wrapper around the texture image. + * This allows other parts of Mesa to access the texture image as if it + * was a renderbuffer. + */ +static void +wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) +{ + struct texture_renderbuffer *trb; + const GLuint name = 0; + + ASSERT(att->Type == GL_TEXTURE); + ASSERT(att->Renderbuffer == NULL); + /* + ASSERT(att->Complete); + */ + + trb = CALLOC_STRUCT(texture_renderbuffer); + if (!trb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture"); + return; + } + + _mesa_init_renderbuffer(&trb->Base, name); + + trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + assert(trb->TexImage); + + trb->Store = trb->TexImage->TexFormat->StoreTexel; + assert(trb->Store); + + trb->Zoffset = att->Zoffset; + + trb->Base.Width = trb->TexImage->Width; + trb->Base.Height = trb->TexImage->Height; + trb->Base.InternalFormat = trb->TexImage->IntFormat; /* XXX fix? */ + trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat; +#if 0 + /* fix/avoid this assertion someday */ + assert(trb->Base._BaseFormat == GL_RGB || + trb->Base._BaseFormat == GL_RGBA || + trb->Base._BaseFormat == GL_DEPTH_COMPONENT); +#endif + trb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix! */ + trb->Base.Data = trb->TexImage->Data; + + trb->Base.GetRow = texture_get_row; + trb->Base.GetValues = texture_get_values; + trb->Base.PutRow = texture_put_row; + trb->Base.PutMonoRow = texture_put_mono_row; + trb->Base.PutValues = texture_put_values; + trb->Base.PutMonoValues = texture_put_mono_values; + + trb->Base.Delete = delete_texture_wrapper; + trb->Base.AllocStorage = NULL; /* illegal! */ + + /* XXX fix these */ + if (trb->Base._BaseFormat == GL_DEPTH_COMPONENT) { + trb->Base.ComponentSizes[3] = trb->TexImage->TexFormat->DepthBits; + } + else { + trb->Base.ComponentSizes[0] = trb->TexImage->TexFormat->RedBits; + trb->Base.ComponentSizes[1] = trb->TexImage->TexFormat->GreenBits; + trb->Base.ComponentSizes[2] = trb->TexImage->TexFormat->BlueBits; + trb->Base.ComponentSizes[3] = trb->TexImage->TexFormat->AlphaBits; + } + + att->Renderbuffer = &(trb->Base); +} + + + +/** + * Software fallback for ctx->Driver.RenderbufferTexture. + * This is called via the glRenderbufferTexture1D/2D/3D() functions. + * If we're unbinding a texture, texObj will be NULL. + * The framebuffer of interest is ctx->DrawBuffer. + * \sa _mesa_framebuffer_renderbuffer + */ +void +_mesa_renderbuffer_texture(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset) +{ + if (texObj) { + _mesa_set_texture_attachment(ctx, att, texObj, + texTarget, level, zoffset); + + wrap_texture(ctx, att); + } + else { + _mesa_remove_attachment(ctx, att); + } +} diff --git a/src/mesa/main/texrender.h b/src/mesa/main/texrender.h new file mode 100644 index 00000000000..6d8bc964141 --- /dev/null +++ b/src/mesa/main/texrender.h @@ -0,0 +1,12 @@ +#ifndef TEXRENDER_H +#define TEXRENDER_H + + +extern void +_mesa_renderbuffer_texture(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset); + + +#endif /* TEXRENDER_H */ diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c new file mode 100644 index 00000000000..8ac41a27729 --- /dev/null +++ b/src/mesa/main/texstate.c @@ -0,0 +1,3271 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file texstate.c + * + * Texture state handling. + */ + +#include "glheader.h" +#include "colormac.h" +#include "colortab.h" +#include "context.h" +#include "enums.h" +#include "extensions.h" +#include "macros.h" +#include "nvfragprog.h" +#include "texobj.h" +#include "teximage.h" +#include "texstate.h" +#include "texenvprogram.h" +#include "mtypes.h" +#include "math/m_xform.h" +#include "math/m_matrix.h" + + + +#ifdef SPECIALCAST +/* Needed for an Amiga compiler */ +#define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X)) +#define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X)) +#else +/* all other compilers */ +#define ENUM_TO_FLOAT(X) ((GLfloat)(X)) +#define ENUM_TO_DOUBLE(X) ((GLdouble)(X)) +#endif + +/** + * Default texture combine environment state. This is used to initialize + * a context's texture units and as the basis for converting "classic" + * texture environmnets to ARB_texture_env_combine style values. + */ +static const struct gl_tex_env_combine_state default_combine_state = { + GL_MODULATE, GL_MODULATE, + { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT }, + { GL_TEXTURE, GL_PREVIOUS, GL_CONSTANT }, + { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA }, + { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA }, + 0, 0, + 2, 2 +}; + + +void +_mesa_copy_texture_state( const GLcontext *src, GLcontext *dst ) +{ + GLuint i; + + ASSERT(src); + ASSERT(dst); + + dst->Texture.CurrentUnit = src->Texture.CurrentUnit; + dst->Texture._GenFlags = src->Texture._GenFlags; + dst->Texture._TexGenEnabled = src->Texture._TexGenEnabled; + dst->Texture._TexMatEnabled = src->Texture._TexMatEnabled; + dst->Texture.SharedPalette = src->Texture.SharedPalette; + + /* per-unit state */ + for (i = 0; i < src->Const.MaxTextureUnits; i++) { + dst->Texture.Unit[i].Enabled = src->Texture.Unit[i].Enabled; + dst->Texture.Unit[i].EnvMode = src->Texture.Unit[i].EnvMode; + COPY_4V(dst->Texture.Unit[i].EnvColor, src->Texture.Unit[i].EnvColor); + dst->Texture.Unit[i].TexGenEnabled = src->Texture.Unit[i].TexGenEnabled; + dst->Texture.Unit[i].GenModeS = src->Texture.Unit[i].GenModeS; + dst->Texture.Unit[i].GenModeT = src->Texture.Unit[i].GenModeT; + dst->Texture.Unit[i].GenModeR = src->Texture.Unit[i].GenModeR; + dst->Texture.Unit[i].GenModeQ = src->Texture.Unit[i].GenModeQ; + dst->Texture.Unit[i]._GenBitS = src->Texture.Unit[i]._GenBitS; + dst->Texture.Unit[i]._GenBitT = src->Texture.Unit[i]._GenBitT; + dst->Texture.Unit[i]._GenBitR = src->Texture.Unit[i]._GenBitR; + dst->Texture.Unit[i]._GenBitQ = src->Texture.Unit[i]._GenBitQ; + dst->Texture.Unit[i]._GenFlags = src->Texture.Unit[i]._GenFlags; + COPY_4V(dst->Texture.Unit[i].ObjectPlaneS, src->Texture.Unit[i].ObjectPlaneS); + COPY_4V(dst->Texture.Unit[i].ObjectPlaneT, src->Texture.Unit[i].ObjectPlaneT); + COPY_4V(dst->Texture.Unit[i].ObjectPlaneR, src->Texture.Unit[i].ObjectPlaneR); + COPY_4V(dst->Texture.Unit[i].ObjectPlaneQ, src->Texture.Unit[i].ObjectPlaneQ); + COPY_4V(dst->Texture.Unit[i].EyePlaneS, src->Texture.Unit[i].EyePlaneS); + COPY_4V(dst->Texture.Unit[i].EyePlaneT, src->Texture.Unit[i].EyePlaneT); + COPY_4V(dst->Texture.Unit[i].EyePlaneR, src->Texture.Unit[i].EyePlaneR); + COPY_4V(dst->Texture.Unit[i].EyePlaneQ, src->Texture.Unit[i].EyePlaneQ); + dst->Texture.Unit[i].LodBias = src->Texture.Unit[i].LodBias; + + /* GL_EXT_texture_env_combine */ + dst->Texture.Unit[i].Combine.ModeRGB = src->Texture.Unit[i].Combine.ModeRGB; + dst->Texture.Unit[i].Combine.ModeA = src->Texture.Unit[i].Combine.ModeA; + COPY_3V(dst->Texture.Unit[i].Combine.SourceRGB, src->Texture.Unit[i].Combine.SourceRGB); + COPY_3V(dst->Texture.Unit[i].Combine.SourceA, src->Texture.Unit[i].Combine.SourceA); + COPY_3V(dst->Texture.Unit[i].Combine.OperandRGB, src->Texture.Unit[i].Combine.OperandRGB); + COPY_3V(dst->Texture.Unit[i].Combine.OperandA, src->Texture.Unit[i].Combine.OperandA); + dst->Texture.Unit[i].Combine.ScaleShiftRGB = src->Texture.Unit[i].Combine.ScaleShiftRGB; + dst->Texture.Unit[i].Combine.ScaleShiftA = src->Texture.Unit[i].Combine.ScaleShiftA; + + /* texture object state */ + _mesa_copy_texture_object(dst->Texture.Unit[i].Current1D, + src->Texture.Unit[i].Current1D); + _mesa_copy_texture_object(dst->Texture.Unit[i].Current2D, + src->Texture.Unit[i].Current2D); + _mesa_copy_texture_object(dst->Texture.Unit[i].Current3D, + src->Texture.Unit[i].Current3D); + _mesa_copy_texture_object(dst->Texture.Unit[i].CurrentCubeMap, + src->Texture.Unit[i].CurrentCubeMap); + _mesa_copy_texture_object(dst->Texture.Unit[i].CurrentRect, + src->Texture.Unit[i].CurrentRect); + } +} + + +/* + * For debugging + */ +void +_mesa_print_texunit_state( GLcontext *ctx, GLuint unit ) +{ + const struct gl_texture_unit *texUnit = ctx->Texture.Unit + unit; + _mesa_printf("Texture Unit %d\n", unit); + _mesa_printf(" GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode)); + _mesa_printf(" GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB)); + _mesa_printf(" GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA)); + _mesa_printf(" GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0])); + _mesa_printf(" GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1])); + _mesa_printf(" GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2])); + _mesa_printf(" GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0])); + _mesa_printf(" GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1])); + _mesa_printf(" GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2])); + _mesa_printf(" GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0])); + _mesa_printf(" GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1])); + _mesa_printf(" GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2])); + _mesa_printf(" GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0])); + _mesa_printf(" GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1])); + _mesa_printf(" GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2])); + _mesa_printf(" GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB); + _mesa_printf(" GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA); + _mesa_printf(" GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", texUnit->EnvColor[0], texUnit->EnvColor[1], texUnit->EnvColor[2], texUnit->EnvColor[3]); +} + + + +/**********************************************************************/ +/* Texture Environment */ +/**********************************************************************/ + +/** + * Convert "classic" texture environment to ARB_texture_env_combine style + * environments. + * + * \param state texture_env_combine state vector to be filled-in. + * \param mode Classic texture environment mode (i.e., \c GL_REPLACE, + * \c GL_BLEND, \c GL_DECAL, etc.). + * \param texBaseFormat Base format of the texture associated with the + * texture unit. + */ +static void +calculate_derived_texenv( struct gl_tex_env_combine_state *state, + GLenum mode, GLenum texBaseFormat ) +{ + GLenum mode_rgb; + GLenum mode_a; + + *state = default_combine_state; + + switch (texBaseFormat) { + case GL_ALPHA: + state->SourceRGB[0] = GL_PREVIOUS; + break; + + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_RGBA: + break; + + case GL_LUMINANCE: + case GL_RGB: + case GL_YCBCR_MESA: + state->SourceA[0] = GL_PREVIOUS; + break; + + default: + _mesa_problem(NULL, "Invalid texBaseFormat in calculate_derived_texenv"); + return; + } + + switch (mode) { + case GL_REPLACE: + case GL_MODULATE: + mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : mode; + mode_a = mode; + break; + + case GL_DECAL: + mode_rgb = GL_INTERPOLATE; + mode_a = GL_REPLACE; + + state->SourceA[0] = GL_PREVIOUS; + + /* Having alpha / luminance / intensity textures replace using the + * incoming fragment color matches the definition in NV_texture_shader. + * The 1.5 spec simply marks these as "undefined". + */ + switch (texBaseFormat) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + state->SourceRGB[0] = GL_PREVIOUS; + break; + case GL_RGB: + case GL_YCBCR_MESA: + mode_rgb = GL_REPLACE; + break; + case GL_RGBA: + state->SourceRGB[2] = GL_TEXTURE; + break; + } + break; + + case GL_BLEND: + mode_rgb = GL_INTERPOLATE; + mode_a = GL_MODULATE; + + switch (texBaseFormat) { + case GL_ALPHA: + mode_rgb = GL_REPLACE; + break; + case GL_INTENSITY: + mode_a = GL_INTERPOLATE; + state->SourceA[0] = GL_CONSTANT; + state->OperandA[2] = GL_SRC_ALPHA; + /* FALLTHROUGH */ + case GL_LUMINANCE: + case GL_RGB: + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + case GL_YCBCR_MESA: + state->SourceRGB[2] = GL_TEXTURE; + state->SourceA[2] = GL_TEXTURE; + state->SourceRGB[0] = GL_CONSTANT; + state->OperandRGB[2] = GL_SRC_COLOR; + break; + } + break; + + case GL_ADD: + mode_rgb = (texBaseFormat == GL_ALPHA) ? GL_REPLACE : GL_ADD; + mode_a = (texBaseFormat == GL_INTENSITY) ? GL_ADD : GL_MODULATE; + break; + + default: + _mesa_problem(NULL, + "Invalid texture env mode in calculate_derived_texenv"); + return; + } + + state->ModeRGB = (state->SourceRGB[0] != GL_PREVIOUS) + ? mode_rgb : GL_REPLACE; + state->ModeA = (state->SourceA[0] != GL_PREVIOUS) + ? mode_a : GL_REPLACE; +} + + +void GLAPIENTRY +_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + +#define TE_ERROR(errCode, msg, value) \ + _mesa_error(ctx, errCode, msg, _mesa_lookup_enum_by_nr(value)); + + if (target == GL_TEXTURE_ENV) { + switch (pname) { + case GL_TEXTURE_ENV_MODE: + { + const GLenum mode = (GLenum) (GLint) *param; + if (texUnit->EnvMode == mode) + return; + if (mode == GL_MODULATE || + mode == GL_BLEND || + mode == GL_DECAL || + mode == GL_REPLACE || + (mode == GL_ADD && ctx->Extensions.EXT_texture_env_add) || + (mode == GL_COMBINE && + (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine))) { + /* legal */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->EnvMode = mode; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + } + break; + case GL_TEXTURE_ENV_COLOR: + { + GLfloat tmp[4]; + tmp[0] = CLAMP( param[0], 0.0F, 1.0F ); + tmp[1] = CLAMP( param[1], 0.0F, 1.0F ); + tmp[2] = CLAMP( param[2], 0.0F, 1.0F ); + tmp[3] = CLAMP( param[3], 0.0F, 1.0F ); + if (TEST_EQ_4V(tmp, texUnit->EnvColor)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + COPY_4FV(texUnit->EnvColor, tmp); + } + break; + case GL_COMBINE_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + const GLenum mode = (GLenum) (GLint) *param; + if (texUnit->Combine.ModeRGB == mode) + return; + switch (mode) { + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_INTERPOLATE: + /* OK */ + break; + case GL_SUBTRACT: + if (!ctx->Extensions.ARB_texture_env_combine) { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + break; + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + if (!ctx->Extensions.EXT_texture_env_dot3) { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + break; + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + if (!ctx->Extensions.ARB_texture_env_dot3) { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + break; + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + if (!ctx->Extensions.ATI_texture_env_combine3) { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + break; + default: + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.ModeRGB = mode; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_COMBINE_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + const GLenum mode = (GLenum) (GLint) *param; + if (texUnit->Combine.ModeA == mode) + return; + switch (mode) { + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_INTERPOLATE: + /* OK */ + break; + case GL_SUBTRACT: + if (!ctx->Extensions.ARB_texture_env_combine) { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + break; + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + if (!ctx->Extensions.ATI_texture_env_combine3) { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + break; + default: + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", mode); + return; + } + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.ModeA = mode; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_SOURCE0_RGB: + case GL_SOURCE1_RGB: + case GL_SOURCE2_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + const GLenum source = (GLenum) (GLint) *param; + const GLuint s = pname - GL_SOURCE0_RGB; + if (texUnit->Combine.SourceRGB[s] == source) + return; + if (source == GL_TEXTURE || + source == GL_CONSTANT || + source == GL_PRIMARY_COLOR || + source == GL_PREVIOUS || + (ctx->Extensions.ARB_texture_env_crossbar && + source >= GL_TEXTURE0 && + source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) || + (ctx->Extensions.ATI_texture_env_combine3 && + (source == GL_ZERO || source == GL_ONE))) { + /* legal */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.SourceRGB[s] = source; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source); + return; + } + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_SOURCE0_ALPHA: + case GL_SOURCE1_ALPHA: + case GL_SOURCE2_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + const GLenum source = (GLenum) (GLint) *param; + const GLuint s = pname - GL_SOURCE0_ALPHA; + if (texUnit->Combine.SourceA[s] == source) + return; + if (source == GL_TEXTURE || + source == GL_CONSTANT || + source == GL_PRIMARY_COLOR || + source == GL_PREVIOUS || + (ctx->Extensions.ARB_texture_env_crossbar && + source >= GL_TEXTURE0 && + source < GL_TEXTURE0 + ctx->Const.MaxTextureUnits) || + (ctx->Extensions.ATI_texture_env_combine3 && + (source == GL_ZERO || source == GL_ONE))) { + /* legal */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.SourceA[s] = source; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", source); + return; + } + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_OPERAND0_RGB: + case GL_OPERAND1_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + const GLenum operand = (GLenum) (GLint) *param; + const GLuint s = pname - GL_OPERAND0_RGB; + if (texUnit->Combine.OperandRGB[s] == operand) + return; + switch (operand) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.OperandRGB[s] = operand; + break; + default: + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); + return; + } + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_OPERAND0_ALPHA: + case GL_OPERAND1_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + const GLenum operand = (GLenum) (GLint) *param; + if (texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] == operand) + return; + switch (operand) { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.OperandA[pname-GL_OPERAND0_ALPHA] = operand; + break; + default: + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); + return; + } + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_OPERAND2_RGB: + if (ctx->Extensions.ARB_texture_env_combine) { + const GLenum operand = (GLenum) (GLint) *param; + if (texUnit->Combine.OperandRGB[2] == operand) + return; + switch (operand) { + case GL_SRC_COLOR: /* ARB combine only */ + case GL_ONE_MINUS_SRC_COLOR: /* ARB combine only */ + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.OperandRGB[2] = operand; + break; + default: + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); + return; + } + } + else if (ctx->Extensions.EXT_texture_env_combine) { + const GLenum operand = (GLenum) (GLint) *param; + if (texUnit->Combine.OperandRGB[2] == operand) + return; + /* operand must be GL_SRC_ALPHA which is the initial value - thus + don't need to actually compare the operand to the possible value */ + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); + return; + } + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_OPERAND2_ALPHA: + if (ctx->Extensions.ARB_texture_env_combine) { + const GLenum operand = (GLenum) (GLint) *param; + if (texUnit->Combine.OperandA[2] == operand) + return; + switch (operand) { + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: /* ARB combine only */ + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.OperandA[2] = operand; + break; + default: + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); + return; + } + } + else if (ctx->Extensions.EXT_texture_env_combine) { + const GLenum operand = (GLenum) (GLint) *param; + if (texUnit->Combine.OperandA[2] == operand) + return; + /* operand must be GL_SRC_ALPHA which is the initial value - thus + don't need to actually compare the operand to the possible value */ + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(param=%s)", operand); + return; + } + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_RGB_SCALE: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + GLuint newshift; + if (*param == 1.0) { + newshift = 0; + } + else if (*param == 2.0) { + newshift = 1; + } + else if (*param == 4.0) { + newshift = 2; + } + else { + _mesa_error( ctx, GL_INVALID_VALUE, + "glTexEnv(GL_RGB_SCALE not 1, 2 or 4)" ); + return; + } + if (texUnit->Combine.ScaleShiftRGB == newshift) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.ScaleShiftRGB = newshift; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + case GL_ALPHA_SCALE: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + GLuint newshift; + if (*param == 1.0) { + newshift = 0; + } + else if (*param == 2.0) { + newshift = 1; + } + else if (*param == 4.0) { + newshift = 2; + } + else { + _mesa_error( ctx, GL_INVALID_VALUE, + "glTexEnv(GL_ALPHA_SCALE not 1, 2 or 4)" ); + return; + } + if (texUnit->Combine.ScaleShiftA == newshift) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->Combine.ScaleShiftA = newshift; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); + return; + } + } + else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { + /* GL_EXT_texture_lod_bias */ + if (!ctx->Extensions.EXT_texture_lod_bias) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); + return; + } + if (pname == GL_TEXTURE_LOD_BIAS_EXT) { + if (texUnit->LodBias == param[0]) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->LodBias = param[0]; + } + else { + TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); + return; + } + } + else if (target == GL_POINT_SPRITE_NV) { + /* GL_ARB_point_sprite / GL_NV_point_sprite */ + if (!ctx->Extensions.NV_point_sprite + && !ctx->Extensions.ARB_point_sprite) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)", target ); + return; + } + if (pname == GL_COORD_REPLACE_NV) { + const GLenum value = (GLenum) param[0]; + if (value == GL_TRUE || value == GL_FALSE) { + /* It's kind of weird to set point state via glTexEnv, + * but that's what the spec calls for. + */ + const GLboolean state = (GLboolean) value; + if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state) + return; + FLUSH_VERTICES(ctx, _NEW_POINT); + ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state; + } + else { + _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value); + return; + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname ); + return; + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(target=0x%x)",target ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glTexEnv %s %s %.1f(%s) ...\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(pname), + *param, + _mesa_lookup_enum_by_nr((GLenum) (GLint) *param)); + + /* Tell device driver about the new texture environment */ + if (ctx->Driver.TexEnv) { + (*ctx->Driver.TexEnv)( ctx, target, pname, param ); + } +} + + +void GLAPIENTRY +_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ) +{ + _mesa_TexEnvfv( target, pname, ¶m ); +} + + + +void GLAPIENTRY +_mesa_TexEnvi( GLenum target, GLenum pname, GLint param ) +{ + GLfloat p[4]; + p[0] = (GLfloat) param; + p[1] = p[2] = p[3] = 0.0; + _mesa_TexEnvfv( target, pname, p ); +} + + +void GLAPIENTRY +_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ) +{ + GLfloat p[4]; + if (pname == GL_TEXTURE_ENV_COLOR) { + p[0] = INT_TO_FLOAT( param[0] ); + p[1] = INT_TO_FLOAT( param[1] ); + p[2] = INT_TO_FLOAT( param[2] ); + p[3] = INT_TO_FLOAT( param[3] ); + } + else { + p[0] = (GLfloat) param[0]; + p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */ + } + _mesa_TexEnvfv( target, pname, p ); +} + + +void GLAPIENTRY +_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_TEXTURE_ENV) { + switch (pname) { + case GL_TEXTURE_ENV_MODE: + *params = ENUM_TO_FLOAT(texUnit->EnvMode); + break; + case GL_TEXTURE_ENV_COLOR: + COPY_4FV( params, texUnit->EnvColor ); + break; + case GL_COMBINE_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.ModeRGB; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_COMBINE_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.ModeA; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_SOURCE0_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.SourceRGB[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_SOURCE1_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.SourceRGB[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_SOURCE2_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.SourceRGB[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_SOURCE0_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.SourceA[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_SOURCE1_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.SourceA[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_SOURCE2_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.SourceA[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_OPERAND0_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.OperandRGB[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_OPERAND1_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.OperandRGB[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_OPERAND2_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.OperandRGB[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_OPERAND0_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.OperandA[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_OPERAND1_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.OperandA[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_OPERAND2_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLfloat) texUnit->Combine.OperandA[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + } + break; + case GL_RGB_SCALE: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + if (texUnit->Combine.ScaleShiftRGB == 0) + *params = 1.0; + else if (texUnit->Combine.ScaleShiftRGB == 1) + *params = 2.0; + else + *params = 4.0; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + case GL_ALPHA_SCALE: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + if (texUnit->Combine.ScaleShiftA == 0) + *params = 1.0; + else if (texUnit->Combine.ScaleShiftA == 1) + *params = 2.0; + else + *params = 4.0; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); + return; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname=0x%x)", pname); + } + } + else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { + /* GL_EXT_texture_lod_bias */ + if (!ctx->Extensions.EXT_texture_lod_bias) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); + return; + } + if (pname == GL_TEXTURE_LOD_BIAS_EXT) { + *params = texUnit->LodBias; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); + return; + } + } + else if (target == GL_POINT_SPRITE_NV) { + /* GL_ARB_point_sprite / GL_NV_point_sprite */ + if (!ctx->Extensions.NV_point_sprite + && !ctx->Extensions.ARB_point_sprite) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); + return; + } + if (pname == GL_COORD_REPLACE_NV) { + *params = (GLfloat) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" ); + return; + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" ); + return; + } +} + + +void GLAPIENTRY +_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_TEXTURE_ENV) { + switch (pname) { + case GL_TEXTURE_ENV_MODE: + *params = (GLint) texUnit->EnvMode; + break; + case GL_TEXTURE_ENV_COLOR: + params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] ); + params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] ); + params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] ); + params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] ); + break; + case GL_COMBINE_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.ModeRGB; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_COMBINE_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.ModeA; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_SOURCE0_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.SourceRGB[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_SOURCE1_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.SourceRGB[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_SOURCE2_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.SourceRGB[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_SOURCE0_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.SourceA[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_SOURCE1_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.SourceA[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_SOURCE2_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.SourceA[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_OPERAND0_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.OperandRGB[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_OPERAND1_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.OperandRGB[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_OPERAND2_RGB: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.OperandRGB[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_OPERAND0_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.OperandA[0]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_OPERAND1_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.OperandA[1]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_OPERAND2_ALPHA: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + *params = (GLint) texUnit->Combine.OperandA[2]; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + } + break; + case GL_RGB_SCALE: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + if (texUnit->Combine.ScaleShiftRGB == 0) + *params = 1; + else if (texUnit->Combine.ScaleShiftRGB == 1) + *params = 2; + else + *params = 4; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + case GL_ALPHA_SCALE: + if (ctx->Extensions.EXT_texture_env_combine || + ctx->Extensions.ARB_texture_env_combine) { + if (texUnit->Combine.ScaleShiftA == 0) + *params = 1; + else if (texUnit->Combine.ScaleShiftA == 1) + *params = 2; + else + *params = 4; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); + return; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname=0x%x)", + pname); + } + } + else if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { + /* GL_EXT_texture_lod_bias */ + if (!ctx->Extensions.EXT_texture_lod_bias) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); + return; + } + if (pname == GL_TEXTURE_LOD_BIAS_EXT) { + *params = (GLint) texUnit->LodBias; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); + return; + } + } + else if (target == GL_POINT_SPRITE_NV) { + /* GL_ARB_point_sprite / GL_NV_point_sprite */ + if (!ctx->Extensions.NV_point_sprite + && !ctx->Extensions.ARB_point_sprite) { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); + return; + } + if (pname == GL_COORD_REPLACE_NV) { + *params = (GLint) ctx->Point.CoordReplace[ctx->Texture.CurrentUnit]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" ); + return; + } + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" ); + return; + } +} + + + + +/**********************************************************************/ +/* Texture Parameters */ +/**********************************************************************/ + +static GLboolean +_mesa_validate_texture_wrap_mode(GLcontext * ctx, + GLenum target, GLenum eparam) +{ + const struct gl_extensions * const e = & ctx->Extensions; + + if (eparam == GL_CLAMP || eparam == GL_CLAMP_TO_EDGE || + (eparam == GL_CLAMP_TO_BORDER && e->ARB_texture_border_clamp)) { + /* any texture target */ + return GL_TRUE; + } + else if (target != GL_TEXTURE_RECTANGLE_NV && + (eparam == GL_REPEAT || + (eparam == GL_MIRRORED_REPEAT && + e->ARB_texture_mirrored_repeat) || + (eparam == GL_MIRROR_CLAMP_EXT && + (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) || + (eparam == GL_MIRROR_CLAMP_TO_EDGE_EXT && + (e->ATI_texture_mirror_once || e->EXT_texture_mirror_clamp)) || + (eparam == GL_MIRROR_CLAMP_TO_BORDER_EXT && + (e->EXT_texture_mirror_clamp)))) { + /* non-rectangle texture */ + return GL_TRUE; + } + + _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param ) +{ + _mesa_TexParameterfv(target, pname, ¶m); +} + + +void GLAPIENTRY +_mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + GLenum eparam = (GLenum) (GLint) params[0]; + struct gl_texture_object *texObj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glTexParameter %s %s %.1f(%s)...\n", + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(pname), + *params, + _mesa_lookup_enum_by_nr(eparam)); + + + switch (target) { + case GL_TEXTURE_1D: + texObj = texUnit->Current1D; + break; + case GL_TEXTURE_2D: + texObj = texUnit->Current2D; + break; + case GL_TEXTURE_3D: + texObj = texUnit->Current3D; + break; + case GL_TEXTURE_CUBE_MAP: + if (!ctx->Extensions.ARB_texture_cube_map) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" ); + return; + } + texObj = texUnit->CurrentCubeMap; + break; + case GL_TEXTURE_RECTANGLE_NV: + if (!ctx->Extensions.NV_texture_rectangle) { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" ); + return; + } + texObj = texUnit->CurrentRect; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" ); + return; + } + + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + /* A small optimization */ + if (texObj->MinFilter == eparam) + return; + if (eparam==GL_NEAREST || eparam==GL_LINEAR) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->MinFilter = eparam; + } + else if ((eparam==GL_NEAREST_MIPMAP_NEAREST || + eparam==GL_LINEAR_MIPMAP_NEAREST || + eparam==GL_NEAREST_MIPMAP_LINEAR || + eparam==GL_LINEAR_MIPMAP_LINEAR) && + texObj->Target != GL_TEXTURE_RECTANGLE_NV) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->MinFilter = eparam; + } + else { + _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + break; + case GL_TEXTURE_MAG_FILTER: + /* A small optimization */ + if (texObj->MagFilter == eparam) + return; + + if (eparam==GL_NEAREST || eparam==GL_LINEAR) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->MagFilter = eparam; + } + else { + _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + break; + case GL_TEXTURE_WRAP_S: + if (texObj->WrapS == eparam) + return; + if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->WrapS = eparam; + } + else { + return; + } + break; + case GL_TEXTURE_WRAP_T: + if (texObj->WrapT == eparam) + return; + if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->WrapT = eparam; + } + else { + return; + } + break; + case GL_TEXTURE_WRAP_R: + if (texObj->WrapR == eparam) + return; + if (_mesa_validate_texture_wrap_mode(ctx, texObj->Target, eparam)) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->WrapR = eparam; + } + else { + return; + } + break; + case GL_TEXTURE_BORDER_COLOR: + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->BorderColor[RCOMP] = params[0]; + texObj->BorderColor[GCOMP] = params[1]; + texObj->BorderColor[BCOMP] = params[2]; + texObj->BorderColor[ACOMP] = params[3]; + UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[RCOMP], params[0]); + UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[GCOMP], params[1]); + UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[BCOMP], params[2]); + UNCLAMPED_FLOAT_TO_CHAN(texObj->_BorderChan[ACOMP], params[3]); + break; + case GL_TEXTURE_MIN_LOD: + if (texObj->MinLod == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->MinLod = params[0]; + break; + case GL_TEXTURE_MAX_LOD: + if (texObj->MaxLod == params[0]) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->MaxLod = params[0]; + break; + case GL_TEXTURE_BASE_LEVEL: + if (params[0] < 0.0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + if (target == GL_TEXTURE_RECTANGLE_NV && params[0] != 0.0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->BaseLevel = (GLint) params[0]; + break; + case GL_TEXTURE_MAX_LEVEL: + if (params[0] < 0.0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->MaxLevel = (GLint) params[0]; + break; + case GL_TEXTURE_PRIORITY: + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->Priority = CLAMP( params[0], 0.0F, 1.0F ); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (ctx->Extensions.EXT_texture_filter_anisotropic) { + if (params[0] < 1.0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" ); + return; + } + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + /* clamp to max, that's what NVIDIA does */ + texObj->MaxAnisotropy = MIN2(params[0], + ctx->Const.MaxTextureMaxAnisotropy); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)"); + return; + } + break; + case GL_TEXTURE_COMPARE_SGIX: + if (ctx->Extensions.SGIX_shadow) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->CompareFlag = params[0] ? GL_TRUE : GL_FALSE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_TEXTURE_COMPARE_SGIX)"); + return; + } + break; + case GL_TEXTURE_COMPARE_OPERATOR_SGIX: + if (ctx->Extensions.SGIX_shadow) { + GLenum op = (GLenum) params[0]; + if (op == GL_TEXTURE_LEQUAL_R_SGIX || + op == GL_TEXTURE_GEQUAL_R_SGIX) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->CompareOperator = op; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)"); + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_TEXTURE_COMPARE_OPERATOR_SGIX)"); + return; + } + break; + case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */ + if (ctx->Extensions.SGIX_shadow_ambient) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->ShadowAmbient = CLAMP(params[0], 0.0F, 1.0F); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_SHADOW_AMBIENT_SGIX)"); + return; + } + break; + case GL_GENERATE_MIPMAP_SGIS: + if (ctx->Extensions.SGIS_generate_mipmap) { + texObj->GenerateMipmap = params[0] ? GL_TRUE : GL_FALSE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_GENERATE_MIPMAP_SGIS)"); + return; + } + break; + case GL_TEXTURE_COMPARE_MODE_ARB: + if (ctx->Extensions.ARB_shadow) { + const GLenum mode = (GLenum) params[0]; + if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->CompareMode = mode; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(bad GL_TEXTURE_COMPARE_MODE_ARB: 0x%x)", mode); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_TEXTURE_COMPARE_MODE_ARB)"); + return; + } + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + if (ctx->Extensions.ARB_shadow) { + const GLenum func = (GLenum) params[0]; + if (func == GL_LEQUAL || func == GL_GEQUAL) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->CompareFunc = func; + } + else if (ctx->Extensions.EXT_shadow_funcs && + (func == GL_EQUAL || + func == GL_NOTEQUAL || + func == GL_LESS || + func == GL_GREATER || + func == GL_ALWAYS || + func == GL_NEVER)) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->CompareFunc = func; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(bad GL_TEXTURE_COMPARE_FUNC_ARB)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_TEXTURE_COMPARE_FUNC_ARB)"); + return; + } + break; + case GL_DEPTH_TEXTURE_MODE_ARB: + if (ctx->Extensions.ARB_depth_texture) { + const GLenum result = (GLenum) params[0]; + if (result == GL_LUMINANCE || result == GL_INTENSITY + || result == GL_ALPHA) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->DepthMode = result; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)"); + return; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)"); + return; + } + break; + case GL_TEXTURE_LOD_BIAS: + /* NOTE: this is really part of OpenGL 1.4, not EXT_texture_lod_bias*/ + if (ctx->Extensions.EXT_texture_lod_bias) { + if (texObj->LodBias != params[0]) { + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texObj->LodBias = params[0]; + } + } + break; + + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glTexParameter(pname=0x%x)", pname); + return; + } + + texObj->Complete = GL_FALSE; + + if (ctx->Driver.TexParameter) { + (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params ); + } +} + + +void GLAPIENTRY +_mesa_TexParameteri( GLenum target, GLenum pname, GLint param ) +{ + GLfloat fparam[4]; + if (pname == GL_TEXTURE_PRIORITY) + fparam[0] = INT_TO_FLOAT(param); + else + fparam[0] = (GLfloat) param; + fparam[1] = fparam[2] = fparam[3] = 0.0; + _mesa_TexParameterfv(target, pname, fparam); +} + + +void GLAPIENTRY +_mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params ) +{ + GLfloat fparam[4]; + if (pname == GL_TEXTURE_BORDER_COLOR) { + fparam[0] = INT_TO_FLOAT(params[0]); + fparam[1] = INT_TO_FLOAT(params[1]); + fparam[2] = INT_TO_FLOAT(params[2]); + fparam[3] = INT_TO_FLOAT(params[3]); + } + else { + if (pname == GL_TEXTURE_PRIORITY) + fparam[0] = INT_TO_FLOAT(params[0]); + else + fparam[0] = (GLfloat) params[0]; + fparam[1] = fparam[2] = fparam[3] = 0.0F; + } + _mesa_TexParameterfv(target, pname, fparam); +} + + +void GLAPIENTRY +_mesa_GetTexLevelParameterfv( GLenum target, GLint level, + GLenum pname, GLfloat *params ) +{ + GLint iparam; + _mesa_GetTexLevelParameteriv( target, level, pname, &iparam ); + *params = (GLfloat) iparam; +} + + +static GLuint +tex_image_dimensions(GLcontext *ctx, GLenum target) +{ + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + return 1; + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + return 2; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + return 3; + case GL_TEXTURE_CUBE_MAP: + case GL_PROXY_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + return ctx->Extensions.ARB_texture_cube_map ? 2 : 0; + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + return ctx->Extensions.NV_texture_rectangle ? 2 : 0; + default: + _mesa_problem(ctx, "bad target in _mesa_tex_target_dimensions()"); + return 0; + } +} + + +void GLAPIENTRY +_mesa_GetTexLevelParameteriv( GLenum target, GLint level, + GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + const struct gl_texture_image *img = NULL; + GLuint dimensions; + GLboolean isProxy; + GLint maxLevels; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* this will catch bad target values */ + dimensions = tex_image_dimensions(ctx, target); /* 1, 2 or 3 */ + if (dimensions == 0) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)"); + return; + } + + switch (target) { + case GL_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D: + maxLevels = ctx->Const.MaxTextureLevels; + break; + case GL_TEXTURE_3D: + case GL_PROXY_TEXTURE_3D: + maxLevels = ctx->Const.Max3DTextureLevels; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + case GL_PROXY_TEXTURE_CUBE_MAP: + maxLevels = ctx->Const.MaxCubeTextureLevels; + break; + case GL_TEXTURE_RECTANGLE_NV: + case GL_PROXY_TEXTURE_RECTANGLE_NV: + maxLevels = 1; + break; + default: + _mesa_problem(ctx, "switch in _mesa_GetTexLevelParameter"); + return; + } + + if (level < 0 || level >= maxLevels) { + _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" ); + return; + } + + img = _mesa_select_tex_image(ctx, texUnit, target, level); + if (!img || !img->TexFormat) { + /* undefined texture image */ + if (pname == GL_TEXTURE_COMPONENTS) + *params = 1; + else + *params = 0; + return; + } + + isProxy = (target == GL_PROXY_TEXTURE_1D) || + (target == GL_PROXY_TEXTURE_2D) || + (target == GL_PROXY_TEXTURE_3D) || + (target == GL_PROXY_TEXTURE_CUBE_MAP) || + (target == GL_PROXY_TEXTURE_RECTANGLE_NV); + + switch (pname) { + case GL_TEXTURE_WIDTH: + *params = img->Width; + return; + case GL_TEXTURE_HEIGHT: + *params = img->Height; + return; + case GL_TEXTURE_DEPTH: + *params = img->Depth; + return; + case GL_TEXTURE_INTERNAL_FORMAT: + *params = img->IntFormat; + return; + case GL_TEXTURE_BORDER: + *params = img->Border; + return; + case GL_TEXTURE_RED_SIZE: + if (img->Format == GL_RGB || img->Format == GL_RGBA) + *params = img->TexFormat->RedBits; + else + *params = 0; + return; + case GL_TEXTURE_GREEN_SIZE: + if (img->Format == GL_RGB || img->Format == GL_RGBA) + *params = img->TexFormat->GreenBits; + else + *params = 0; + return; + case GL_TEXTURE_BLUE_SIZE: + if (img->Format == GL_RGB || img->Format == GL_RGBA) + *params = img->TexFormat->BlueBits; + else + *params = 0; + return; + case GL_TEXTURE_ALPHA_SIZE: + if (img->Format == GL_ALPHA || img->Format == GL_LUMINANCE_ALPHA || + img->Format == GL_RGBA) + *params = img->TexFormat->AlphaBits; + else + *params = 0; + return; + case GL_TEXTURE_INTENSITY_SIZE: + if (img->Format != GL_INTENSITY) + *params = 0; + else if (img->TexFormat->IntensityBits > 0) + *params = img->TexFormat->IntensityBits; + else /* intensity probably stored as rgb texture */ + *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits); + return; + case GL_TEXTURE_LUMINANCE_SIZE: + if (img->Format != GL_LUMINANCE && + img->Format != GL_LUMINANCE_ALPHA) + *params = 0; + else if (img->TexFormat->LuminanceBits > 0) + *params = img->TexFormat->LuminanceBits; + else /* luminance probably stored as rgb texture */ + *params = MIN2(img->TexFormat->RedBits, img->TexFormat->GreenBits); + return; + case GL_TEXTURE_INDEX_SIZE_EXT: + if (img->Format == GL_COLOR_INDEX) + *params = img->TexFormat->IndexBits; + else + *params = 0; + return; + case GL_TEXTURE_DEPTH_SIZE_ARB: + if (ctx->Extensions.SGIX_depth_texture || + ctx->Extensions.ARB_depth_texture) + *params = img->TexFormat->DepthBits; + else + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + return; + + /* GL_ARB_texture_compression */ + case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: + if (ctx->Extensions.ARB_texture_compression) { + if (img->IsCompressed && !isProxy) + *params = img->CompressedSize; + else + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTexLevelParameter[if]v(pname)"); + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_COMPRESSED: + if (ctx->Extensions.ARB_texture_compression) { + *params = (GLint) img->IsCompressed; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + + /* GL_ARB_texture_float */ + case GL_TEXTURE_RED_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->RedBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_GREEN_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->GreenBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_BLUE_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->BlueBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_ALPHA_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->AlphaBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_LUMINANCE_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->LuminanceBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_INTENSITY_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->IntensityBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + case GL_TEXTURE_DEPTH_TYPE_ARB: + if (ctx->Extensions.ARB_texture_float) { + *params = img->TexFormat->DepthBits ? img->TexFormat->DataType : GL_NONE; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } +} + + + +void GLAPIENTRY +_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *obj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + obj = _mesa_select_tex_object(ctx, texUnit, target); + if (!obj) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)"); + return; + } + + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + *params = ENUM_TO_FLOAT(obj->MagFilter); + return; + case GL_TEXTURE_MIN_FILTER: + *params = ENUM_TO_FLOAT(obj->MinFilter); + return; + case GL_TEXTURE_WRAP_S: + *params = ENUM_TO_FLOAT(obj->WrapS); + return; + case GL_TEXTURE_WRAP_T: + *params = ENUM_TO_FLOAT(obj->WrapT); + return; + case GL_TEXTURE_WRAP_R: + *params = ENUM_TO_FLOAT(obj->WrapR); + return; + case GL_TEXTURE_BORDER_COLOR: + params[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F); + params[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F); + params[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F); + params[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F); + return; + case GL_TEXTURE_RESIDENT: + { + GLboolean resident; + if (ctx->Driver.IsTextureResident) + resident = ctx->Driver.IsTextureResident(ctx, obj); + else + resident = GL_TRUE; + *params = ENUM_TO_FLOAT(resident); + } + return; + case GL_TEXTURE_PRIORITY: + *params = obj->Priority; + return; + case GL_TEXTURE_MIN_LOD: + *params = obj->MinLod; + return; + case GL_TEXTURE_MAX_LOD: + *params = obj->MaxLod; + return; + case GL_TEXTURE_BASE_LEVEL: + *params = (GLfloat) obj->BaseLevel; + return; + case GL_TEXTURE_MAX_LEVEL: + *params = (GLfloat) obj->MaxLevel; + return; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (ctx->Extensions.EXT_texture_filter_anisotropic) { + *params = obj->MaxAnisotropy; + return; + } + break; + case GL_TEXTURE_COMPARE_SGIX: + if (ctx->Extensions.SGIX_shadow) { + *params = (GLfloat) obj->CompareFlag; + return; + } + break; + case GL_TEXTURE_COMPARE_OPERATOR_SGIX: + if (ctx->Extensions.SGIX_shadow) { + *params = (GLfloat) obj->CompareOperator; + return; + } + break; + case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */ + if (ctx->Extensions.SGIX_shadow_ambient) { + *params = obj->ShadowAmbient; + return; + } + break; + case GL_GENERATE_MIPMAP_SGIS: + if (ctx->Extensions.SGIS_generate_mipmap) { + *params = (GLfloat) obj->GenerateMipmap; + return; + } + break; + case GL_TEXTURE_COMPARE_MODE_ARB: + if (ctx->Extensions.ARB_shadow) { + *params = (GLfloat) obj->CompareMode; + return; + } + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + if (ctx->Extensions.ARB_shadow) { + *params = (GLfloat) obj->CompareFunc; + return; + } + break; + case GL_DEPTH_TEXTURE_MODE_ARB: + if (ctx->Extensions.ARB_depth_texture) { + *params = (GLfloat) obj->DepthMode; + return; + } + break; + case GL_TEXTURE_LOD_BIAS: + if (ctx->Extensions.EXT_texture_lod_bias) { + *params = obj->LodBias; + return; + } + break; + default: + ; /* silence warnings */ + } + /* If we get here, pname was an unrecognized enum */ + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname=0x%x)", + pname); +} + + +void GLAPIENTRY +_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *obj; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + obj = _mesa_select_tex_object(ctx, texUnit, target); + if (!obj) { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(target)"); + return; + } + + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + *params = (GLint) obj->MagFilter; + return; + case GL_TEXTURE_MIN_FILTER: + *params = (GLint) obj->MinFilter; + return; + case GL_TEXTURE_WRAP_S: + *params = (GLint) obj->WrapS; + return; + case GL_TEXTURE_WRAP_T: + *params = (GLint) obj->WrapT; + return; + case GL_TEXTURE_WRAP_R: + *params = (GLint) obj->WrapR; + return; + case GL_TEXTURE_BORDER_COLOR: + { + GLfloat b[4]; + b[0] = CLAMP(obj->BorderColor[0], 0.0F, 1.0F); + b[1] = CLAMP(obj->BorderColor[1], 0.0F, 1.0F); + b[2] = CLAMP(obj->BorderColor[2], 0.0F, 1.0F); + b[3] = CLAMP(obj->BorderColor[3], 0.0F, 1.0F); + params[0] = FLOAT_TO_INT(b[0]); + params[1] = FLOAT_TO_INT(b[1]); + params[2] = FLOAT_TO_INT(b[2]); + params[3] = FLOAT_TO_INT(b[3]); + } + return; + case GL_TEXTURE_RESIDENT: + { + GLboolean resident; + if (ctx->Driver.IsTextureResident) + resident = ctx->Driver.IsTextureResident(ctx, obj); + else + resident = GL_TRUE; + *params = (GLint) resident; + } + return; + case GL_TEXTURE_PRIORITY: + *params = FLOAT_TO_INT(obj->Priority); + return; + case GL_TEXTURE_MIN_LOD: + *params = (GLint) obj->MinLod; + return; + case GL_TEXTURE_MAX_LOD: + *params = (GLint) obj->MaxLod; + return; + case GL_TEXTURE_BASE_LEVEL: + *params = obj->BaseLevel; + return; + case GL_TEXTURE_MAX_LEVEL: + *params = obj->MaxLevel; + return; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (ctx->Extensions.EXT_texture_filter_anisotropic) { + *params = (GLint) obj->MaxAnisotropy; + return; + } + break; + case GL_TEXTURE_COMPARE_SGIX: + if (ctx->Extensions.SGIX_shadow) { + *params = (GLint) obj->CompareFlag; + return; + } + break; + case GL_TEXTURE_COMPARE_OPERATOR_SGIX: + if (ctx->Extensions.SGIX_shadow) { + *params = (GLint) obj->CompareOperator; + return; + } + break; + case GL_SHADOW_AMBIENT_SGIX: /* aka GL_TEXTURE_COMPARE_FAIL_VALUE_ARB */ + if (ctx->Extensions.SGIX_shadow_ambient) { + *params = (GLint) FLOAT_TO_INT(obj->ShadowAmbient); + return; + } + break; + case GL_GENERATE_MIPMAP_SGIS: + if (ctx->Extensions.SGIS_generate_mipmap) { + *params = (GLint) obj->GenerateMipmap; + return; + } + break; + case GL_TEXTURE_COMPARE_MODE_ARB: + if (ctx->Extensions.ARB_shadow) { + *params = (GLint) obj->CompareMode; + return; + } + break; + case GL_TEXTURE_COMPARE_FUNC_ARB: + if (ctx->Extensions.ARB_shadow) { + *params = (GLint) obj->CompareFunc; + return; + } + break; + case GL_DEPTH_TEXTURE_MODE_ARB: + if (ctx->Extensions.ARB_depth_texture) { + *params = (GLint) obj->DepthMode; + return; + } + break; + case GL_TEXTURE_LOD_BIAS: + if (ctx->Extensions.EXT_texture_lod_bias) { + *params = (GLint) obj->LodBias; + return; + } + break; + default: + ; /* silence warnings */ + } + /* If we get here, pname was an unrecognized enum */ + _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname=0x%x)", pname); +} + + + + +/**********************************************************************/ +/* Texture Coord Generation */ +/**********************************************************************/ + +#if FEATURE_texgen +void GLAPIENTRY +_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint tUnit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glTexGen %s %s %.1f(%s)...\n", + _mesa_lookup_enum_by_nr(coord), + _mesa_lookup_enum_by_nr(pname), + *params, + _mesa_lookup_enum_by_nr((GLenum) (GLint) *params)); + + switch (coord) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + GLuint bits; + switch (mode) { + case GL_OBJECT_LINEAR: + bits = TEXGEN_OBJ_LINEAR; + break; + case GL_EYE_LINEAR: + bits = TEXGEN_EYE_LINEAR; + break; + case GL_REFLECTION_MAP_NV: + bits = TEXGEN_REFLECTION_MAP_NV; + break; + case GL_NORMAL_MAP_NV: + bits = TEXGEN_NORMAL_MAP_NV; + break; + case GL_SPHERE_MAP: + bits = TEXGEN_SPHERE_MAP; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + if (texUnit->GenModeS == mode) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->GenModeS = mode; + texUnit->_GenBitS = bits; + } + else if (pname==GL_OBJECT_PLANE) { + if (TEST_EQ_4V(texUnit->ObjectPlaneS, params)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->ObjectPlaneS[0] = params[0]; + texUnit->ObjectPlaneS[1] = params[1]; + texUnit->ObjectPlaneS[2] = params[2]; + texUnit->ObjectPlaneS[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + GLfloat tmp[4]; + + /* Transform plane equation by the inverse modelview matrix */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + } + _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv ); + if (TEST_EQ_4V(texUnit->EyePlaneS, tmp)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + COPY_4FV(texUnit->EyePlaneS, tmp); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + GLuint bitt; + switch (mode) { + case GL_OBJECT_LINEAR: + bitt = TEXGEN_OBJ_LINEAR; + break; + case GL_EYE_LINEAR: + bitt = TEXGEN_EYE_LINEAR; + break; + case GL_REFLECTION_MAP_NV: + bitt = TEXGEN_REFLECTION_MAP_NV; + break; + case GL_NORMAL_MAP_NV: + bitt = TEXGEN_NORMAL_MAP_NV; + break; + case GL_SPHERE_MAP: + bitt = TEXGEN_SPHERE_MAP; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + if (texUnit->GenModeT == mode) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->GenModeT = mode; + texUnit->_GenBitT = bitt; + } + else if (pname==GL_OBJECT_PLANE) { + if (TEST_EQ_4V(texUnit->ObjectPlaneT, params)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->ObjectPlaneT[0] = params[0]; + texUnit->ObjectPlaneT[1] = params[1]; + texUnit->ObjectPlaneT[2] = params[2]; + texUnit->ObjectPlaneT[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + GLfloat tmp[4]; + /* Transform plane equation by the inverse modelview matrix */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + } + _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv ); + if (TEST_EQ_4V(texUnit->EyePlaneT, tmp)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + COPY_4FV(texUnit->EyePlaneT, tmp); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + GLuint bitr; + switch (mode) { + case GL_OBJECT_LINEAR: + bitr = TEXGEN_OBJ_LINEAR; + break; + case GL_REFLECTION_MAP_NV: + bitr = TEXGEN_REFLECTION_MAP_NV; + break; + case GL_NORMAL_MAP_NV: + bitr = TEXGEN_NORMAL_MAP_NV; + break; + case GL_EYE_LINEAR: + bitr = TEXGEN_EYE_LINEAR; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + if (texUnit->GenModeR == mode) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->GenModeR = mode; + texUnit->_GenBitR = bitr; + } + else if (pname==GL_OBJECT_PLANE) { + if (TEST_EQ_4V(texUnit->ObjectPlaneR, params)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->ObjectPlaneR[0] = params[0]; + texUnit->ObjectPlaneR[1] = params[1]; + texUnit->ObjectPlaneR[2] = params[2]; + texUnit->ObjectPlaneR[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + GLfloat tmp[4]; + /* Transform plane equation by the inverse modelview matrix */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + } + _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv ); + if (TEST_EQ_4V(texUnit->EyePlaneR, tmp)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + COPY_4FV(texUnit->EyePlaneR, tmp); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + GLenum mode = (GLenum) (GLint) *params; + GLuint bitq; + switch (mode) { + case GL_OBJECT_LINEAR: + bitq = TEXGEN_OBJ_LINEAR; + break; + case GL_EYE_LINEAR: + bitq = TEXGEN_EYE_LINEAR; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" ); + return; + } + if (texUnit->GenModeQ == mode) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->GenModeQ = mode; + texUnit->_GenBitQ = bitq; + } + else if (pname==GL_OBJECT_PLANE) { + if (TEST_EQ_4V(texUnit->ObjectPlaneQ, params)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + texUnit->ObjectPlaneQ[0] = params[0]; + texUnit->ObjectPlaneQ[1] = params[1]; + texUnit->ObjectPlaneQ[2] = params[2]; + texUnit->ObjectPlaneQ[3] = params[3]; + } + else if (pname==GL_EYE_PLANE) { + GLfloat tmp[4]; + /* Transform plane equation by the inverse modelview matrix */ + if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) { + _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + } + _mesa_transform_vector( tmp, params, ctx->ModelviewMatrixStack.Top->inv ); + if (TEST_EQ_4V(texUnit->EyePlaneQ, tmp)) + return; + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + COPY_4FV(texUnit->EyePlaneQ, tmp); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" ); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexGenfv(coord)" ); + return; + } + + if (ctx->Driver.TexGen) + ctx->Driver.TexGen( ctx, coord, pname, params ); +} + + +void GLAPIENTRY +_mesa_TexGeniv(GLenum coord, GLenum pname, const GLint *params ) +{ + GLfloat p[4]; + p[0] = (GLfloat) params[0]; + if (pname == GL_TEXTURE_GEN_MODE) { + p[1] = p[2] = p[3] = 0.0F; + } + else { + p[1] = (GLfloat) params[1]; + p[2] = (GLfloat) params[2]; + p[3] = (GLfloat) params[3]; + } + _mesa_TexGenfv(coord, pname, p); +} + + +void GLAPIENTRY +_mesa_TexGend(GLenum coord, GLenum pname, GLdouble param ) +{ + GLfloat p = (GLfloat) param; + _mesa_TexGenfv( coord, pname, &p ); +} + + +void GLAPIENTRY +_mesa_TexGendv(GLenum coord, GLenum pname, const GLdouble *params ) +{ + GLfloat p[4]; + p[0] = (GLfloat) params[0]; + if (pname == GL_TEXTURE_GEN_MODE) { + p[1] = p[2] = p[3] = 0.0F; + } + else { + p[1] = (GLfloat) params[1]; + p[2] = (GLfloat) params[2]; + p[3] = (GLfloat) params[3]; + } + _mesa_TexGenfv( coord, pname, p ); +} + + +void GLAPIENTRY +_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param ) +{ + _mesa_TexGenfv(coord, pname, ¶m); +} + + +void GLAPIENTRY +_mesa_TexGeni( GLenum coord, GLenum pname, GLint param ) +{ + _mesa_TexGeniv( coord, pname, ¶m ); +} + + + +void GLAPIENTRY +_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint tUnit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (coord) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeS); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneS ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneS ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeT); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneT ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneT ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeR); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneR ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneR ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_DOUBLE(texUnit->GenModeQ); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneQ ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneQ ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" ); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)" ); + return; + } +} + + + +void GLAPIENTRY +_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint tUnit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (coord) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeS); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneS ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneS ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeT); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneT ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneT ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeR); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneR ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneR ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = ENUM_TO_FLOAT(texUnit->GenModeQ); + } + else if (pname==GL_OBJECT_PLANE) { + COPY_4V( params, texUnit->ObjectPlaneQ ); + } + else if (pname==GL_EYE_PLANE) { + COPY_4V( params, texUnit->EyePlaneQ ); + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" ); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)" ); + return; + } +} + + + +void GLAPIENTRY +_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint tUnit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit]; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (coord) { + case GL_S: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeS; + } + else if (pname==GL_OBJECT_PLANE) { + params[0] = (GLint) texUnit->ObjectPlaneS[0]; + params[1] = (GLint) texUnit->ObjectPlaneS[1]; + params[2] = (GLint) texUnit->ObjectPlaneS[2]; + params[3] = (GLint) texUnit->ObjectPlaneS[3]; + } + else if (pname==GL_EYE_PLANE) { + params[0] = (GLint) texUnit->EyePlaneS[0]; + params[1] = (GLint) texUnit->EyePlaneS[1]; + params[2] = (GLint) texUnit->EyePlaneS[2]; + params[3] = (GLint) texUnit->EyePlaneS[3]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + case GL_T: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeT; + } + else if (pname==GL_OBJECT_PLANE) { + params[0] = (GLint) texUnit->ObjectPlaneT[0]; + params[1] = (GLint) texUnit->ObjectPlaneT[1]; + params[2] = (GLint) texUnit->ObjectPlaneT[2]; + params[3] = (GLint) texUnit->ObjectPlaneT[3]; + } + else if (pname==GL_EYE_PLANE) { + params[0] = (GLint) texUnit->EyePlaneT[0]; + params[1] = (GLint) texUnit->EyePlaneT[1]; + params[2] = (GLint) texUnit->EyePlaneT[2]; + params[3] = (GLint) texUnit->EyePlaneT[3]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + case GL_R: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeR; + } + else if (pname==GL_OBJECT_PLANE) { + params[0] = (GLint) texUnit->ObjectPlaneR[0]; + params[1] = (GLint) texUnit->ObjectPlaneR[1]; + params[2] = (GLint) texUnit->ObjectPlaneR[2]; + params[3] = (GLint) texUnit->ObjectPlaneR[3]; + } + else if (pname==GL_EYE_PLANE) { + params[0] = (GLint) texUnit->EyePlaneR[0]; + params[1] = (GLint) texUnit->EyePlaneR[1]; + params[2] = (GLint) texUnit->EyePlaneR[2]; + params[3] = (GLint) texUnit->EyePlaneR[3]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + case GL_Q: + if (pname==GL_TEXTURE_GEN_MODE) { + params[0] = texUnit->GenModeQ; + } + else if (pname==GL_OBJECT_PLANE) { + params[0] = (GLint) texUnit->ObjectPlaneQ[0]; + params[1] = (GLint) texUnit->ObjectPlaneQ[1]; + params[2] = (GLint) texUnit->ObjectPlaneQ[2]; + params[3] = (GLint) texUnit->ObjectPlaneQ[3]; + } + else if (pname==GL_EYE_PLANE) { + params[0] = (GLint) texUnit->EyePlaneQ[0]; + params[1] = (GLint) texUnit->EyePlaneQ[1]; + params[2] = (GLint) texUnit->EyePlaneQ[2]; + params[3] = (GLint) texUnit->EyePlaneQ[3]; + } + else { + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" ); + return; + } + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)" ); + return; + } +} +#endif + +/* GL_ARB_multitexture */ +void GLAPIENTRY +_mesa_ActiveTextureARB( GLenum target ) +{ + GET_CURRENT_CONTEXT(ctx); + const GLuint texUnit = target - GL_TEXTURE0; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) + _mesa_debug(ctx, "glActiveTexture %s\n", + _mesa_lookup_enum_by_nr(target)); + + /* Cater for texture unit 0 is first, therefore use >= */ + if (texUnit >= ctx->Const.MaxTextureUnits) { + _mesa_error(ctx, GL_INVALID_ENUM, "glActiveTexture(target)"); + return; + } + + if (ctx->Texture.CurrentUnit == texUnit) + return; + + FLUSH_VERTICES(ctx, _NEW_TEXTURE); + + ctx->Texture.CurrentUnit = texUnit; + if (ctx->Transform.MatrixMode == GL_TEXTURE) { + /* update current stack pointer */ + ctx->CurrentStack = &ctx->TextureMatrixStack[texUnit]; + } + + if (ctx->Driver.ActiveTexture) { + (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit ); + } +} + + +/* GL_ARB_multitexture */ +void GLAPIENTRY +_mesa_ClientActiveTextureARB( GLenum target ) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint texUnit = target - GL_TEXTURE0; + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (texUnit > ctx->Const.MaxTextureUnits) { + _mesa_error(ctx, GL_INVALID_ENUM, "glClientActiveTexture(target)"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + ctx->Array.ActiveTexture = texUnit; +} + + + +/**********************************************************************/ +/* Pixel Texgen Extensions */ +/**********************************************************************/ + +void GLAPIENTRY +_mesa_PixelTexGenSGIX(GLenum mode) +{ + GLenum newRgbSource, newAlphaSource; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (mode) { + case GL_NONE: + newRgbSource = GL_PIXEL_GROUP_COLOR_SGIS; + newAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS; + break; + case GL_ALPHA: + newRgbSource = GL_PIXEL_GROUP_COLOR_SGIS; + newAlphaSource = GL_CURRENT_RASTER_COLOR; + break; + case GL_RGB: + newRgbSource = GL_CURRENT_RASTER_COLOR; + newAlphaSource = GL_PIXEL_GROUP_COLOR_SGIS; + break; + case GL_RGBA: + newRgbSource = GL_CURRENT_RASTER_COLOR; + newAlphaSource = GL_CURRENT_RASTER_COLOR; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenSGIX(mode)"); + return; + } + + if (newRgbSource == ctx->Pixel.FragmentRgbSource && + newAlphaSource == ctx->Pixel.FragmentAlphaSource) + return; + + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.FragmentRgbSource = newRgbSource; + ctx->Pixel.FragmentAlphaSource = newAlphaSource; +} + + +void GLAPIENTRY +_mesa_PixelTexGenParameterfSGIS(GLenum target, GLfloat value) +{ + _mesa_PixelTexGenParameteriSGIS(target, (GLint) value); +} + + +void GLAPIENTRY +_mesa_PixelTexGenParameterfvSGIS(GLenum target, const GLfloat *value) +{ + _mesa_PixelTexGenParameteriSGIS(target, (GLint) *value); +} + + +void GLAPIENTRY +_mesa_PixelTexGenParameteriSGIS(GLenum target, GLint value) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (value != GL_CURRENT_RASTER_COLOR && value != GL_PIXEL_GROUP_COLOR_SGIS) { + _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenParameterSGIS(value)"); + return; + } + + switch (target) { + case GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS: + if (ctx->Pixel.FragmentRgbSource == (GLenum) value) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.FragmentRgbSource = (GLenum) value; + break; + case GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS: + if (ctx->Pixel.FragmentAlphaSource == (GLenum) value) + return; + FLUSH_VERTICES(ctx, _NEW_PIXEL); + ctx->Pixel.FragmentAlphaSource = (GLenum) value; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glPixelTexGenParameterSGIS(target)"); + return; + } +} + + +void GLAPIENTRY +_mesa_PixelTexGenParameterivSGIS(GLenum target, const GLint *value) +{ + _mesa_PixelTexGenParameteriSGIS(target, *value); +} + + +void GLAPIENTRY +_mesa_GetPixelTexGenParameterfvSGIS(GLenum target, GLfloat *value) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS) { + *value = (GLfloat) ctx->Pixel.FragmentRgbSource; + } + else if (target == GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS) { + *value = (GLfloat) ctx->Pixel.FragmentAlphaSource; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterfvSGIS(target)"); + } +} + + +void GLAPIENTRY +_mesa_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target == GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS) { + *value = (GLint) ctx->Pixel.FragmentRgbSource; + } + else if (target == GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS) { + *value = (GLint) ctx->Pixel.FragmentAlphaSource; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, "glGetPixelTexGenParameterivSGIS(target)"); + } +} + + + +/**********************************************************************/ +/***** State management *****/ +/**********************************************************************/ + + +/** + * \note This routine refers to derived texture attribute values to + * compute the ENABLE_TEXMAT flags, but is only called on + * _NEW_TEXTURE_MATRIX. On changes to _NEW_TEXTURE, the ENABLE_TEXMAT + * flags are updated by _mesa_update_textures(), below. + * + * \param ctx GL context. + */ +static void +update_texture_matrices( GLcontext *ctx ) +{ + GLuint i; + + ctx->Texture._TexMatEnabled = 0; + + for (i=0; i < ctx->Const.MaxTextureUnits; i++) { + if (_math_matrix_is_dirty(ctx->TextureMatrixStack[i].Top)) { + _math_matrix_analyse( ctx->TextureMatrixStack[i].Top ); + + if (ctx->Texture.Unit[i]._ReallyEnabled && + ctx->TextureMatrixStack[i].Top->type != MATRIX_IDENTITY) + ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(i); + + if (ctx->Driver.TextureMatrix) + ctx->Driver.TextureMatrix( ctx, i, ctx->TextureMatrixStack[i].Top); + } + } +} + + + + +/** + * \note This routine refers to derived texture matrix values to + * compute the ENABLE_TEXMAT flags, but is only called on + * _NEW_TEXTURE. On changes to _NEW_TEXTURE_MATRIX, the ENABLE_TEXMAT + * flags are updated by _mesa_update_texture_matrices, above. + * + * \param ctx GL context. + */ +static void +update_texture_state( GLcontext *ctx ) +{ + GLuint unit; + + ctx->NewState |= _NEW_TEXTURE; /* TODO: only set this if there are + * actual changes. + */ + + ctx->Texture._EnabledUnits = 0; + ctx->Texture._GenFlags = 0; + ctx->Texture._TexMatEnabled = 0; + ctx->Texture._TexGenEnabled = 0; + + /* Update texture unit state. + * XXX this loop should probably be broken into separate loops for + * texture coord units and texture image units. + */ + for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint enableBits; + + texUnit->_Current = NULL; + texUnit->_ReallyEnabled = 0; + texUnit->_GenFlags = 0; + + /* Get the bitmask of texture enables */ + if (ctx->FragmentProgram._Enabled) { + enableBits = ctx->FragmentProgram.Current->TexturesUsed[unit]; + } + else { + if (!texUnit->Enabled) + continue; + enableBits = texUnit->Enabled; + } + + /* Look for the highest-priority texture target that's enabled and + * complete. That's the one we'll use for texturing. If we're using + * a fragment program we're guaranteed that bitcount(enabledBits) <= 1. + */ + if (enableBits & TEXTURE_CUBE_BIT) { + struct gl_texture_object *texObj = texUnit->CurrentCubeMap; + if (!texObj->Complete) { + _mesa_test_texobj_completeness(ctx, texObj); + } + if (texObj->Complete) { + texUnit->_ReallyEnabled = TEXTURE_CUBE_BIT; + texUnit->_Current = texObj; + } + } + + if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_3D_BIT)) { + struct gl_texture_object *texObj = texUnit->Current3D; + if (!texObj->Complete) { + _mesa_test_texobj_completeness(ctx, texObj); + } + if (texObj->Complete) { + texUnit->_ReallyEnabled = TEXTURE_3D_BIT; + texUnit->_Current = texObj; + } + } + + if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_RECT_BIT)) { + struct gl_texture_object *texObj = texUnit->CurrentRect; + if (!texObj->Complete) { + _mesa_test_texobj_completeness(ctx, texObj); + } + if (texObj->Complete) { + texUnit->_ReallyEnabled = TEXTURE_RECT_BIT; + texUnit->_Current = texObj; + } + } + + if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_2D_BIT)) { + struct gl_texture_object *texObj = texUnit->Current2D; + if (!texObj->Complete) { + _mesa_test_texobj_completeness(ctx, texObj); + } + if (texObj->Complete) { + texUnit->_ReallyEnabled = TEXTURE_2D_BIT; + texUnit->_Current = texObj; + } + } + + if (!texUnit->_ReallyEnabled && (enableBits & TEXTURE_1D_BIT)) { + struct gl_texture_object *texObj = texUnit->Current1D; + if (!texObj->Complete) { + _mesa_test_texobj_completeness(ctx, texObj); + } + if (texObj->Complete) { + texUnit->_ReallyEnabled = TEXTURE_1D_BIT; + texUnit->_Current = texObj; + } + } + + if (!texUnit->_ReallyEnabled) { + continue; + } + + if (texUnit->_ReallyEnabled) + ctx->Texture._EnabledUnits |= (1 << unit); + + if (texUnit->EnvMode == GL_COMBINE) { + texUnit->_CurrentCombine = & texUnit->Combine; + } + else { + GLenum format = texUnit->_Current->Image[0][0]->Format; + if (format == GL_COLOR_INDEX) { + format = GL_RGBA; /* a bit of a hack */ + } + else if (format == GL_DEPTH_COMPONENT) { + format = texUnit->_Current->DepthMode; + } + calculate_derived_texenv(&texUnit->_EnvMode, texUnit->EnvMode, format); + texUnit->_CurrentCombine = & texUnit->_EnvMode; + } + + switch (texUnit->_CurrentCombine->ModeRGB) { + case GL_REPLACE: + texUnit->_CurrentCombine->_NumArgsRGB = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + texUnit->_CurrentCombine->_NumArgsRGB = 2; + break; + case GL_INTERPOLATE: + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + texUnit->_CurrentCombine->_NumArgsRGB = 3; + break; + default: + texUnit->_CurrentCombine->_NumArgsRGB = 0; + _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state"); + return; + } + + switch (texUnit->_CurrentCombine->ModeA) { + case GL_REPLACE: + texUnit->_CurrentCombine->_NumArgsA = 1; + break; + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + texUnit->_CurrentCombine->_NumArgsA = 2; + break; + case GL_INTERPOLATE: + case GL_MODULATE_ADD_ATI: + case GL_MODULATE_SIGNED_ADD_ATI: + case GL_MODULATE_SUBTRACT_ATI: + texUnit->_CurrentCombine->_NumArgsA = 3; + break; + default: + texUnit->_CurrentCombine->_NumArgsA = 0; + _mesa_problem(ctx, "invalid Alpha combine mode in update_texture_state"); + break; + } + + if (texUnit->TexGenEnabled) { + if (texUnit->TexGenEnabled & S_BIT) { + texUnit->_GenFlags |= texUnit->_GenBitS; + } + if (texUnit->TexGenEnabled & T_BIT) { + texUnit->_GenFlags |= texUnit->_GenBitT; + } + if (texUnit->TexGenEnabled & Q_BIT) { + texUnit->_GenFlags |= texUnit->_GenBitQ; + } + if (texUnit->TexGenEnabled & R_BIT) { + texUnit->_GenFlags |= texUnit->_GenBitR; + } + + ctx->Texture._TexGenEnabled |= ENABLE_TEXGEN(unit); + ctx->Texture._GenFlags |= texUnit->_GenFlags; + } + + if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) + ctx->Texture._TexMatEnabled |= ENABLE_TEXMAT(unit); + } + + ctx->Texture._EnabledCoordUnits = ctx->Texture._EnabledUnits; + /* Fragment programs may need texture coordinates but not the + * corresponding texture images. + */ + if (ctx->FragmentProgram._Enabled) { + ctx->Texture._EnabledCoordUnits |= + (ctx->FragmentProgram.Current->InputsRead >> FRAG_ATTRIB_TEX0); + } +} + + +void _mesa_update_texture( GLcontext *ctx, GLuint new_state ) +{ + if (new_state & _NEW_TEXTURE_MATRIX) + update_texture_matrices( ctx ); + + if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) + update_texture_state( ctx ); +} + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +/** + * Allocate the proxy textures for the given context. + * + * \param ctx the context to allocate proxies for. + * + * \return GL_TRUE on success, or GL_FALSE on failure + * + * If run out of memory part way through the allocations, clean up and return + * GL_FALSE. + */ +static GLboolean +alloc_proxy_textures( GLcontext *ctx ) +{ + ctx->Texture.Proxy1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D); + if (!ctx->Texture.Proxy1D) + goto cleanup; + + ctx->Texture.Proxy2D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_2D); + if (!ctx->Texture.Proxy2D) + goto cleanup; + + ctx->Texture.Proxy3D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_3D); + if (!ctx->Texture.Proxy3D) + goto cleanup; + + ctx->Texture.ProxyCubeMap = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_CUBE_MAP_ARB); + if (!ctx->Texture.ProxyCubeMap) + goto cleanup; + + ctx->Texture.ProxyRect = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_RECTANGLE_NV); + if (!ctx->Texture.ProxyRect) + goto cleanup; + + return GL_TRUE; + + cleanup: + if (ctx->Texture.Proxy1D) + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D); + if (ctx->Texture.Proxy2D) + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D); + if (ctx->Texture.Proxy3D) + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D); + if (ctx->Texture.ProxyCubeMap) + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap); + if (ctx->Texture.ProxyRect) + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect); + return GL_FALSE; +} + + +/** + * Initialize a texture unit. + * + * \param ctx GL context. + * \param unit texture unit number to be initialized. + */ +static void +init_texture_unit( GLcontext *ctx, GLuint unit ) +{ + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + texUnit->EnvMode = GL_MODULATE; + ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 ); + + texUnit->Combine = default_combine_state; + texUnit->_EnvMode = default_combine_state; + texUnit->_CurrentCombine = & texUnit->_EnvMode; + + texUnit->TexGenEnabled = 0; + texUnit->GenModeS = GL_EYE_LINEAR; + texUnit->GenModeT = GL_EYE_LINEAR; + texUnit->GenModeR = GL_EYE_LINEAR; + texUnit->GenModeQ = GL_EYE_LINEAR; + texUnit->_GenBitS = TEXGEN_EYE_LINEAR; + texUnit->_GenBitT = TEXGEN_EYE_LINEAR; + texUnit->_GenBitR = TEXGEN_EYE_LINEAR; + texUnit->_GenBitQ = TEXGEN_EYE_LINEAR; + + /* Yes, these plane coefficients are correct! */ + ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 ); + ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 ); + + texUnit->Current1D = ctx->Shared->Default1D; + texUnit->Current2D = ctx->Shared->Default2D; + texUnit->Current3D = ctx->Shared->Default3D; + texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap; + texUnit->CurrentRect = ctx->Shared->DefaultRect; +} + + +GLboolean _mesa_init_texture( GLcontext * ctx ) +{ + int i; + + assert(MAX_TEXTURE_LEVELS >= MAX_3D_TEXTURE_LEVELS); + assert(MAX_TEXTURE_LEVELS >= MAX_CUBE_TEXTURE_LEVELS); + + /* Effectively bind the default textures to all texture units */ + ctx->Shared->Default1D->RefCount += MAX_TEXTURE_UNITS; + ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS; + ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS; + ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS; + ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS; + + /* Texture group */ + ctx->Texture.CurrentUnit = 0; /* multitexture */ + ctx->Texture._EnabledUnits = 0; + for (i=0; i<MAX_TEXTURE_UNITS; i++) + init_texture_unit( ctx, i ); + ctx->Texture.SharedPalette = GL_FALSE; + _mesa_init_colortable(&ctx->Texture.Palette); + + /* Allocate proxy textures */ + if (!alloc_proxy_textures( ctx )) + return GL_FALSE; + + return GL_TRUE; +} + +void _mesa_free_texture_data( GLcontext *ctx ) +{ + int i; + + /* Free proxy texture objects */ + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy1D ); + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy2D ); + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.Proxy3D ); + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyCubeMap ); + (ctx->Driver.DeleteTexture)(ctx, ctx->Texture.ProxyRect ); + + for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) + _mesa_free_colortable_data( &ctx->Texture.Unit[i].ColorTable ); + + _mesa_TexEnvProgramCacheDestroy( ctx ); +} diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h new file mode 100644 index 00000000000..7cc3d2c19ce --- /dev/null +++ b/src/mesa/main/texstate.h @@ -0,0 +1,192 @@ +/** + * \file texstate.h + * Texture state management. + */ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef TEXSTATE_H +#define TEXSTATE_H + + +#include "mtypes.h" + + +extern void +_mesa_copy_texture_state( const GLcontext *src, GLcontext *dst ); + +extern void +_mesa_print_texunit_state( GLcontext *ctx, GLuint unit ); + + +/** + * \name Called from API + */ +/*@{*/ + +extern void GLAPIENTRY +_mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ); + +extern void GLAPIENTRY +_mesa_GetTexGendv( GLenum coord, GLenum pname, GLdouble *params ); + +extern void GLAPIENTRY +_mesa_GetTexGenfv( GLenum coord, GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetTexGeniv( GLenum coord, GLenum pname, GLint *params ); + +extern void GLAPIENTRY +_mesa_GetTexLevelParameterfv( GLenum target, GLint level, + GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetTexLevelParameteriv( GLenum target, GLint level, + GLenum pname, GLint *params ); + +extern void GLAPIENTRY +_mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ); + +extern void GLAPIENTRY +_mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ); + + +extern void GLAPIENTRY +_mesa_TexEnvf( GLenum target, GLenum pname, GLfloat param ); + +extern void GLAPIENTRY +_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ); + +extern void GLAPIENTRY +_mesa_TexEnvi( GLenum target, GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ); + + +extern void GLAPIENTRY +_mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params ); + +extern void GLAPIENTRY +_mesa_TexParameterf( GLenum target, GLenum pname, GLfloat param ); + + +extern void GLAPIENTRY +_mesa_TexParameteri( GLenum target, GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_TexParameteriv( GLenum target, GLenum pname, const GLint *params ); + + +extern void GLAPIENTRY +_mesa_TexGend( GLenum coord, GLenum pname, GLdouble param ); + +extern void GLAPIENTRY +_mesa_TexGendv( GLenum coord, GLenum pname, const GLdouble *params ); + +extern void GLAPIENTRY +_mesa_TexGenf( GLenum coord, GLenum pname, GLfloat param ); + +extern void GLAPIENTRY +_mesa_TexGenfv( GLenum coord, GLenum pname, const GLfloat *params ); + +extern void GLAPIENTRY +_mesa_TexGeni( GLenum coord, GLenum pname, GLint param ); + +extern void GLAPIENTRY +_mesa_TexGeniv( GLenum coord, GLenum pname, const GLint *params ); + + +/* + * GL_ARB_multitexture + */ +extern void GLAPIENTRY +_mesa_ActiveTextureARB( GLenum target ); + +extern void GLAPIENTRY +_mesa_ClientActiveTextureARB( GLenum target ); + + +/* + * Pixel Texture Extensions + */ + +extern void GLAPIENTRY +_mesa_PixelTexGenSGIX(GLenum mode); + +extern void GLAPIENTRY +_mesa_PixelTexGenParameterfSGIS(GLenum target, GLfloat value); + +#ifdef VMS +#define _mesa_PixelTexGenParameterfvSGIS _mesa_PixelTexGenParameterfv +#endif +extern void GLAPIENTRY +_mesa_PixelTexGenParameterfvSGIS(GLenum target, const GLfloat *value); + +extern void GLAPIENTRY +_mesa_PixelTexGenParameteriSGIS(GLenum target, GLint value); + +#ifdef VMS +#define _mesa_PixelTexGenParameterivSGIS _mesa_PixelTexGenParameteriv +#endif +extern void GLAPIENTRY +_mesa_PixelTexGenParameterivSGIS(GLenum target, const GLint *value); + +#ifdef VMS +#define _mesa_GetPixelTexGenParameterfvSGIS _mesa_GetPixelTexGenParameterfv +#endif +extern void GLAPIENTRY +_mesa_GetPixelTexGenParameterfvSGIS(GLenum target, GLfloat *value); + +#ifdef VMS +#define _mesa_GetPixelTexGenParameterivSGIS _mesa_GetPixelTexGenParameteriv +#endif +extern void GLAPIENTRY +_mesa_GetPixelTexGenParameterivSGIS(GLenum target, GLint *value); + +/*@}*/ + + +/** + * \name Initialization, state maintenance + */ +/*@{*/ + +extern void +_mesa_update_texture( GLcontext *ctx, GLuint new_state ); + +extern GLboolean +_mesa_init_texture( GLcontext *ctx ); + +extern void +_mesa_free_texture_data( GLcontext *ctx ); + +/*@}*/ + +#endif diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c new file mode 100644 index 00000000000..af1bbf57e0c --- /dev/null +++ b/src/mesa/main/texstore.c @@ -0,0 +1,4055 @@ +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Authors: + * Brian Paul + */ + +/* + * The GL texture image functions in teximage.c basically just do + * error checking and data structure allocation. They in turn call + * device driver functions which actually copy/convert/store the user's + * texture image data. + * + * However, most device drivers will be able to use the fallback functions + * in this file. That is, most drivers will have the following bit of + * code: + * ctx->Driver.TexImage1D = _mesa_store_teximage1d; + * ctx->Driver.TexImage2D = _mesa_store_teximage2d; + * ctx->Driver.TexImage3D = _mesa_store_teximage3d; + * etc... + * + * Texture image processing is actually kind of complicated. We have to do: + * Format/type conversions + * pixel unpacking + * pixel transfer (scale, bais, lookup, convolution!, etc) + * + * These functions can handle most everything, including processing full + * images and sub-images. + */ + + +#include "glheader.h" +#include "bufferobj.h" +#include "colormac.h" +#include "context.h" +#include "convolve.h" +#include "image.h" +#include "macros.h" +#include "imports.h" +#include "texcompress.h" +#include "texformat.h" +#include "teximage.h" +#include "texstore.h" + + +static const GLint ZERO = 4, ONE = 5; + +static GLboolean can_swizzle(GLenum logicalBaseFormat) +{ + switch (logicalBaseFormat) { + case GL_RGBA: + case GL_RGB: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_ALPHA: + case GL_LUMINANCE: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * When promoting texture formats (see below) we need to compute the + * mapping of dest components back to source components. + * This function does that. + * \param logicalBaseFormat the logical format of the texture + * \param textureBaseFormat the final texture format + * \return map[4] the four mapping values + */ +static void +compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, + GLubyte map[6]) +{ + map[ZERO] = ZERO; + map[ONE] = ONE; + + /* compute mapping from dest components back to src components */ + switch (textureBaseFormat) { + case GL_RGB: + case GL_RGBA: + switch (logicalBaseFormat) { + case GL_LUMINANCE: + map[0] = map[1] = map[2] = 0; + if (textureBaseFormat == GL_RGBA) + map[3] = ONE; + break; + case GL_ALPHA: + ASSERT(textureBaseFormat == GL_RGBA); + map[0] = map[1] = map[2] = ZERO; + map[3] = 0; + break; + case GL_INTENSITY: + map[0] = map[1] = map[2] = 0; + if (textureBaseFormat == GL_RGBA) + map[3] = 0; + break; + case GL_LUMINANCE_ALPHA: + ASSERT(textureBaseFormat == GL_RGBA); + map[0] = map[1] = map[2] = 0; + map[3] = 1; + break; + case GL_RGB: + ASSERT(textureBaseFormat == GL_RGBA); + map[0] = 0; + map[1] = 1; + map[2] = 2; + map[3] = ONE; + break; + case GL_RGBA: + ASSERT(textureBaseFormat == GL_RGBA); + map[0] = 0; + map[1] = 1; + map[2] = 2; + map[3] = 3; + break; + default: + _mesa_problem(NULL, "Unexpected logicalBaseFormat"); + map[0] = map[1] = map[2] = map[3] = 0; + } + break; + case GL_LUMINANCE_ALPHA: + switch (logicalBaseFormat) { + case GL_LUMINANCE: + map[0] = 0; + map[1] = ONE; + break; + case GL_ALPHA: + map[0] = ZERO; + map[1] = 0; + break; + case GL_INTENSITY: + map[0] = 0; + map[1] = 0; + break; + default: + _mesa_problem(NULL, "Unexpected logicalBaseFormat"); + map[0] = map[1] = 0; + } + break; + default: + _mesa_problem(NULL, "Unexpected logicalBaseFormat"); + map[0] = map[1] = 0; + break; + } +} + + +/** + * Make a temporary (color) texture image with GLfloat components. + * Apply all needed pixel unpacking and pixel transfer operations. + * Note that there are both logicalBaseFormat and textureBaseFormat parameters. + * Suppose the user specifies GL_LUMINANCE as the internal texture format + * but the graphics hardware doesn't support luminance textures. So, might + * use an RGB hardware format instead. + * If logicalBaseFormat != textureBaseFormat we have some extra work to do. + * + * \param ctx the rendering context + * \param dims image dimensions: 1, 2 or 3 + * \param logicalBaseFormat basic texture derived from the user's + * internal texture format value + * \param textureBaseFormat the actual basic format of the texture + * \param srcWidth source image width + * \param srcHeight source image height + * \param srcDepth source image depth + * \param srcFormat source image format + * \param srcType source image type + * \param srcAddr source image address + * \param srcPacking source image pixel packing + * \return resulting image with format = textureBaseFormat and type = GLfloat. + */ +static GLfloat * +make_temp_float_image(GLcontext *ctx, GLuint dims, + GLenum logicalBaseFormat, + GLenum textureBaseFormat, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) +{ + GLuint transferOps = ctx->_ImageTransferState; + GLfloat *tempImage; + + ASSERT(dims >= 1 && dims <= 3); + + ASSERT(logicalBaseFormat == GL_RGBA || + logicalBaseFormat == GL_RGB || + logicalBaseFormat == GL_LUMINANCE_ALPHA || + logicalBaseFormat == GL_LUMINANCE || + logicalBaseFormat == GL_ALPHA || + logicalBaseFormat == GL_INTENSITY || + logicalBaseFormat == GL_COLOR_INDEX || + logicalBaseFormat == GL_DEPTH_COMPONENT); + + ASSERT(textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_RGB || + textureBaseFormat == GL_LUMINANCE_ALPHA || + textureBaseFormat == GL_LUMINANCE || + textureBaseFormat == GL_ALPHA || + textureBaseFormat == GL_INTENSITY || + textureBaseFormat == GL_COLOR_INDEX || + textureBaseFormat == GL_DEPTH_COMPONENT); + + /* conventional color image */ + + if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) || + (dims >= 2 && ctx->Pixel.Convolution2DEnabled) || + (dims >= 2 && ctx->Pixel.Separable2DEnabled)) { + /* need image convolution */ + const GLuint preConvTransferOps + = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT; + const GLuint postConvTransferOps + = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT; + GLint img, row; + GLint convWidth, convHeight; + GLfloat *convImage; + + /* pre-convolution image buffer (3D) */ + tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * 4 * sizeof(GLfloat)); + if (!tempImage) + return NULL; + + /* post-convolution image buffer (2D) */ + convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight + * 4 * sizeof(GLfloat)); + if (!convImage) { + _mesa_free(tempImage); + return NULL; + } + + /* loop over 3D image slices */ + for (img = 0; img < srcDepth; img++) { + GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4); + + /* unpack and do transfer ops up to convolution */ + for (row = 0; row < srcHeight; row++) { + const GLvoid *src = _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, + srcFormat, srcType, img, row, 0); + _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst, + srcFormat, srcType, src, + srcPacking, + preConvTransferOps); + dst += srcWidth * 4; + } + + /* do convolution */ + { + GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4); + convWidth = srcWidth; + convHeight = srcHeight; + if (dims == 1) { + ASSERT(ctx->Pixel.Convolution1DEnabled); + _mesa_convolve_1d_image(ctx, &convWidth, src, convImage); + } + else { + if (ctx->Pixel.Convolution2DEnabled) { + _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, + src, convImage); + } + else { + ASSERT(ctx->Pixel.Separable2DEnabled); + _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, + src, convImage); + } + } + } + + /* do post-convolution transfer and pack into tempImage */ + { + const GLint logComponents + = _mesa_components_in_format(logicalBaseFormat); + const GLfloat *src = convImage; + GLfloat *dst = tempImage + img * (convWidth * convHeight * 4); + for (row = 0; row < convHeight; row++) { + _mesa_pack_rgba_span_float(ctx, convWidth, + (const GLfloat (*)[4]) src, + logicalBaseFormat, GL_FLOAT, + dst, &ctx->DefaultPacking, + postConvTransferOps); + src += convWidth * 4; + dst += convWidth * logComponents; + } + } + } /* loop over 3D image slices */ + + _mesa_free(convImage); + + /* might need these below */ + srcWidth = convWidth; + srcHeight = convHeight; + } + else { + /* no convolution */ + const GLint components = _mesa_components_in_format(logicalBaseFormat); + const GLint srcStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLfloat *dst; + GLint img, row; + + tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * components * sizeof(GLfloat)); + if (!tempImage) + return NULL; + + dst = tempImage; + for (img = 0; img < srcDepth; img++) { + const GLubyte *src + = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat, + dst, srcFormat, srcType, src, + srcPacking, transferOps); + dst += srcWidth * components; + src += srcStride; + } + } + } + + if (logicalBaseFormat != textureBaseFormat) { + /* more work */ + GLint texComponents = _mesa_components_in_format(textureBaseFormat); + GLint logComponents = _mesa_components_in_format(logicalBaseFormat); + GLfloat *newImage; + GLint i, n; + GLubyte map[6]; + + /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */ + ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_LUMINANCE_ALPHA); + + /* The actual texture format should have at least as many components + * as the logical texture format. + */ + ASSERT(texComponents >= logComponents); + + newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * texComponents * sizeof(GLfloat)); + if (!newImage) { + _mesa_free(tempImage); + return NULL; + } + + compute_component_mapping(logicalBaseFormat, textureBaseFormat, map); + + n = srcWidth * srcHeight * srcDepth; + for (i = 0; i < n; i++) { + GLint k; + for (k = 0; k < texComponents; k++) { + GLint j = map[k]; + if (j == ZERO) + newImage[i * texComponents + k] = 0.0F; + else if (j == ONE) + newImage[i * texComponents + k] = 1.0F; + else + newImage[i * texComponents + k] = tempImage[i * logComponents + j]; + } + } + + _mesa_free(tempImage); + tempImage = newImage; + } + + return tempImage; +} + + +/** + * Make a temporary (color) texture image with GLchan components. + * Apply all needed pixel unpacking and pixel transfer operations. + * Note that there are both logicalBaseFormat and textureBaseFormat parameters. + * Suppose the user specifies GL_LUMINANCE as the internal texture format + * but the graphics hardware doesn't support luminance textures. So, might + * use an RGB hardware format instead. + * If logicalBaseFormat != textureBaseFormat we have some extra work to do. + * + * \param ctx the rendering context + * \param dims image dimensions: 1, 2 or 3 + * \param logicalBaseFormat basic texture derived from the user's + * internal texture format value + * \param textureBaseFormat the actual basic format of the texture + * \param srcWidth source image width + * \param srcHeight source image height + * \param srcDepth source image depth + * \param srcFormat source image format + * \param srcType source image type + * \param srcAddr source image address + * \param srcPacking source image pixel packing + * \return resulting image with format = textureBaseFormat and type = GLchan. + */ +GLchan * +_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, + GLenum logicalBaseFormat, + GLenum textureBaseFormat, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) +{ + GLuint transferOps = ctx->_ImageTransferState; + const GLint components = _mesa_components_in_format(logicalBaseFormat); + GLboolean freeSrcImage = GL_FALSE; + GLint img, row; + GLchan *tempImage, *dst; + + ASSERT(dims >= 1 && dims <= 3); + + ASSERT(logicalBaseFormat == GL_RGBA || + logicalBaseFormat == GL_RGB || + logicalBaseFormat == GL_LUMINANCE_ALPHA || + logicalBaseFormat == GL_LUMINANCE || + logicalBaseFormat == GL_ALPHA || + logicalBaseFormat == GL_INTENSITY); + + ASSERT(textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_RGB || + textureBaseFormat == GL_LUMINANCE_ALPHA || + textureBaseFormat == GL_LUMINANCE || + textureBaseFormat == GL_ALPHA || + textureBaseFormat == GL_INTENSITY); + + if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) || + (dims >= 2 && ctx->Pixel.Convolution2DEnabled) || + (dims >= 2 && ctx->Pixel.Separable2DEnabled)) { + /* get convolved image */ + GLfloat *convImage = make_temp_float_image(ctx, dims, + logicalBaseFormat, + logicalBaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, + srcAddr, srcPacking); + if (!convImage) + return NULL; + /* the convolved image is our new source image */ + srcAddr = convImage; + srcFormat = logicalBaseFormat; + srcType = GL_FLOAT; + srcPacking = &ctx->DefaultPacking; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + transferOps = 0; + freeSrcImage = GL_TRUE; + } + + /* unpack and transfer the source image */ + tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * components * sizeof(GLchan)); + if (!tempImage) + return NULL; + + dst = tempImage; + for (img = 0; img < srcDepth; img++) { + const GLint srcStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, + srcType); + const GLubyte *src + = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst, + srcFormat, srcType, src, srcPacking, + transferOps); + dst += srcWidth * components; + src += srcStride; + } + } + + /* If we made a temporary image for convolution, free it here */ + if (freeSrcImage) { + _mesa_free((void *) srcAddr); + } + + if (logicalBaseFormat != textureBaseFormat) { + /* one more conversion step */ + GLint texComponents = _mesa_components_in_format(textureBaseFormat); + GLint logComponents = _mesa_components_in_format(logicalBaseFormat); + GLchan *newImage; + GLint i, n; + GLubyte map[6]; + + /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */ + ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA || + textureBaseFormat == GL_LUMINANCE_ALPHA); + + /* The actual texture format should have at least as many components + * as the logical texture format. + */ + ASSERT(texComponents >= logComponents); + + newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth + * texComponents * sizeof(GLchan)); + if (!newImage) { + _mesa_free(tempImage); + return NULL; + } + + compute_component_mapping(logicalBaseFormat, textureBaseFormat, map); + + n = srcWidth * srcHeight * srcDepth; + for (i = 0; i < n; i++) { + GLint k; + for (k = 0; k < texComponents; k++) { + GLint j = map[k]; + if (j == ZERO) + newImage[i * texComponents + k] = 0; + else if (j == ONE) + newImage[i * texComponents + k] = CHAN_MAX; + else + newImage[i * texComponents + k] = tempImage[i * logComponents + j]; + } + } + + _mesa_free(tempImage); + tempImage = newImage; + } + + return tempImage; +} + + +/** + * Copy GLubyte pixels from <src> to <dst> with swizzling. + * \param dst destination pixels + * \param dstComponents number of color components in destination pixels + * \param src source pixels + * \param srcComponents number of color components in source pixels + * \param map the swizzle mapping + * \param count number of pixels to copy/swizzle. + */ +static void +swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, + GLuint srcComponents, const GLubyte *map, GLuint count) +{ + GLubyte tmp[8]; + GLint i; + + tmp[ZERO] = 0x0; + tmp[ONE] = 0xff; + + switch (dstComponents) { + case 4: + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst[1] = tmp[map[1]]; + dst[2] = tmp[map[2]]; + dst[3] = tmp[map[3]]; + dst += 4; + } + break; + case 3: + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst[1] = tmp[map[1]]; + dst[2] = tmp[map[2]]; + dst += 3; + } + break; + case 2: + for (i = 0; i < count; i++) { + COPY_4UBV(tmp, src); + src += srcComponents; + dst[0] = tmp[map[0]]; + dst[1] = tmp[map[1]]; + dst += 2; + } + break; + } +} + + +/** + * Transfer a GLubyte texture image with component swizzling. + */ +static void +_mesa_swizzle_ubyte_image(GLcontext *ctx, + GLuint dimensions, + GLenum srcFormat, + const GLubyte *dstmap, GLint dstComponents, + + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + + GLint srcWidth, GLint srcHeight, GLint srcDepth, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking ) +{ + GLint srcComponents = _mesa_components_in_format(srcFormat); + GLubyte srcmap[6], map[4]; + GLint i; + + const GLint srcRowStride = + _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, GL_UNSIGNED_BYTE); + const GLint srcImageStride + = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat, + GL_UNSIGNED_BYTE); + const GLubyte *srcImage + = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr, + srcWidth, srcHeight, srcFormat, + GL_UNSIGNED_BYTE, 0, 0, 0); + + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstComponents; + + compute_component_mapping(srcFormat, GL_RGBA, srcmap); + + for (i = 0; i < 4; i++) + map[i] = srcmap[dstmap[i]]; + + if (srcRowStride == srcWidth * srcComponents && + (srcImageStride == srcWidth * srcHeight * srcComponents || + srcDepth == 1)) { + swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, + srcWidth * srcHeight * srcDepth); + } + else { + GLint img, row; + for (img = 0; img < srcDepth; img++) { + const GLubyte *srcRow = srcImage; + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth); + dstRow += dstRowStride; + srcRow += srcRowStride; + } + srcImage += srcImageStride; + dstImage += dstImageStride; + } + } +} + + +/** + * Teximage storage routine for when a simple memcpy will do. + * No pixel transfer operations or special texel encodings allowed. + * 1D, 2D and 3D images supported. + */ +static void +memcpy_texture(GLcontext *ctx, + GLuint dimensions, + const struct gl_texture_format *dstFormat, + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) +{ + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, srcType); + const GLint srcImageStride = _mesa_image_image_stride(srcPacking, + srcWidth, srcHeight, srcFormat, srcType); + const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions, + srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); + const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes; + const GLint bytesPerImage = srcHeight * bytesPerRow; + const GLint bytesPerTexture = srcDepth * bytesPerImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + + if (dstRowStride == srcRowStride && + dstRowStride == bytesPerRow && + ((dstImageStride == srcImageStride && + dstImageStride == bytesPerImage) || + (srcDepth == 1))) { + /* one big memcpy */ + ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture); + } + else { + GLint img, row; + for (img = 0; img < srcDepth; img++) { + const GLubyte *srcRow = srcImage; + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow); + dstRow += dstRowStride; + srcRow += srcRowStride; + } + srcImage += srcImageStride; + dstImage += dstImageStride; + } + } +} + + + +/** + * Store an image in any of the formats: + * _mesa_texformat_rgba + * _mesa_texformat_rgb + * _mesa_texformat_alpha + * _mesa_texformat_luminance + * _mesa_texformat_luminance_alpha + * _mesa_texformat_intensity + * + * \param dims either 1 or 2 or 3 + * \param baseInternalFormat user-specified base internal format + * \param dstFormat destination Mesa texture format + * \param dstAddr destination image address + * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels + * \param dstRowStride destination image row stride, in bytes + * \param dstImageStride destination image layer stride, in bytes + * \param srcWidth/Height/Depth source image size, in pixels + * \param srcFormat incoming image format + * \param srcType incoming image data type + * \param srcAddr source image address + * \param srcPacking source image packing parameters + */ +GLboolean +_mesa_texstore_rgba(GLcontext *ctx, GLuint dims, + GLenum baseInternalFormat, + const struct gl_texture_format *dstFormat, + GLvoid *dstAddr, + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, + GLint dstRowStride, GLint dstImageStride, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking) +{ + const GLint components = _mesa_components_in_format(baseInternalFormat); + + ASSERT(dstFormat == &_mesa_texformat_rgba || + dstFormat == &_mesa_texformat_rgb || + dstFormat == &_mesa_texformat_alpha || + dstFormat == &_mesa_texformat_luminance || + dstFormat == &_mesa_texformat_luminance_alpha || + dstFormat == &_mesa_texformat_intensity); + ASSERT(baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_LUMINANCE || + baseInternalFormat == GL_LUMINANCE_ALPHA || + baseInternalFormat == GL_INTENSITY); + ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == CHAN_TYPE) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_rgb && + srcFormat == GL_RGBA && + srcType == CHAN_TYPE) { + /* extract RGB from RGBA */ + int img, row, col; + GLchan *dstImage = (GLchan *) (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLchan *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP]; + dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP]; + dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP]; + } + dstRow += dstRowStride; + srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride); + } + dstImage += dstImageStride; + } + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLint bytesPerRow; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + bytesPerRow = srcWidth * components * sizeof(GLchan); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + _mesa_memcpy(dstRow, src, bytesPerRow); + dstRow += dstRowStride; + src += srcWidth * components; + } + dstImage += dstImageStride; + } + + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +/** + * Store a floating point depth component texture image. + */ +GLboolean +_mesa_texstore_depth_component_float32(STORE_PARAMS) +{ + (void) dims; + ASSERT(dstFormat == &_mesa_texformat_depth_component_float32); + ASSERT(dstFormat->TexelBytes == sizeof(GLfloat)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_DEPTH_COMPONENT && + srcFormat == GL_DEPTH_COMPONENT && + srcType == GL_FLOAT) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + const GLvoid *src = _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); + _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) dstRow, + srcType, src, srcPacking); + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + } + return GL_TRUE; +} + + +/** + * Store a 16-bit integer depth component texture image. + */ +GLboolean +_mesa_texstore_depth_component16(STORE_PARAMS) +{ + (void) dims; + ASSERT(dstFormat == &_mesa_texformat_depth_component16); + ASSERT(dstFormat->TexelBytes == sizeof(GLushort)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_DEPTH_COMPONENT && + srcFormat == GL_DEPTH_COMPONENT && + srcType == GL_UNSIGNED_SHORT) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLfloat depthTemp[MAX_WIDTH]; + const GLvoid *src = _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); + GLushort *dst16 = (GLushort *) dstRow; + _mesa_unpack_depth_span(ctx, srcWidth, depthTemp, + srcType, src, srcPacking); + for (col = 0; col < srcWidth; col++) { + dst16[col] = (GLushort) (depthTemp[col] * 65535.0F); + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + } + return GL_TRUE; +} + + +/** + * Store an rgb565 or rgb565_rev texture image. + */ +GLboolean +_mesa_texstore_rgb565(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_rgb565 || + dstFormat == &_mesa_texformat_rgb565_rev); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_rgb565 && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_SHORT_5_6_5) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_BYTE && + dims == 2) { + /* do optimized tex store */ + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, + srcFormat, srcType); + const GLubyte *src = (const GLubyte *) + _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, + srcFormat, srcType, 0, 0, 0); + GLubyte *dst = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint row, col; + for (row = 0; row < srcHeight; row++) { + const GLubyte *srcUB = (const GLubyte *) src; + GLushort *dstUS = (GLushort *) dst; + /* check for byteswapped format */ + if (dstFormat == &_mesa_texformat_rgb565) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] ); + srcUB += 3; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] ); + srcUB += 3; + } + } + dst += dstRowStride; + src += srcRowStride; + } + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLushort *dstUS = (GLushort *) dstRow; + /* check for byteswapped format */ + if (dstFormat == &_mesa_texformat_rgb565) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 3; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 3; + } + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_rgba8888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + (void)littleEndian; + ASSERT(dstFormat == &_mesa_texformat_rgba8888 || + dstFormat == &_mesa_texformat_rgba8888_rev); + ASSERT(dstFormat->TexelBytes == 4); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_rgba8888 && + baseInternalFormat == GL_RGBA && + ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || + (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } +#if 0 + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcType == GL_UNSIGNED_BYTE && + dstFormat == &_mesa_texformat_rgba8888 && + littleEndian && + /* Three texture formats involved: srcFormat, + * baseInternalFormat and destFormat (GL_RGBA). Only two + * may differ. _mesa_swizzle_ubyte_image can't handle two + * propagations at once correctly. */ + (srcFormat == baseInternalFormat || + baseInternalFormat == GL_RGBA) && + can_swizzle(srcFormat)) { + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from GL_RGBA to dst format: + * + * FIXME - add !litteEndian and _rev varients: + */ + dstmap[3] = 0; + dstmap[2] = 1; + dstmap[1] = 2; + dstmap[0] = 3; + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + dstmap, 4, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } +#endif + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLuint *dstUI = (GLuint *) dstRow; + if (dstFormat == &_mesa_texformat_rgba8888) { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]), + CHAN_TO_UBYTE(src[ACOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]), + CHAN_TO_UBYTE(src[ACOMP]) ); + src += 4; + } + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_argb8888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_argb8888 || + dstFormat == &_mesa_texformat_argb8888_rev); + ASSERT(dstFormat->TexelBytes == 4); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + baseInternalFormat == GL_RGBA && + srcFormat == GL_BGRA && + ((srcType == GL_UNSIGNED_BYTE && littleEndian) || + srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) { + /* simple memcpy path (little endian) */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888_rev && + baseInternalFormat == GL_RGBA && + srcFormat == GL_BGRA && + ((srcType == GL_UNSIGNED_BYTE && !littleEndian) || + srcType == GL_UNSIGNED_INT_8_8_8_8)) { + /* simple memcpy path (big endian) */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_BYTE) { + + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP]; + dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP]; + dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP]; + dstRow[col * 4 + 3] = 0xff; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcFormat == GL_RGBA && + srcType == GL_UNSIGNED_BYTE) { + + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP]; + dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP]; + dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP]; + dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP]; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb8888 && + srcType == GL_UNSIGNED_BYTE && + littleEndian && + /* Three texture formats involved: srcFormat, + * baseInternalFormat and destFormat (GL_RGBA). Only two + * may differ. _mesa_swizzle_ubyte_image can't handle two + * propagations at once correctly. */ + (srcFormat == baseInternalFormat || + baseInternalFormat == GL_RGBA) && + can_swizzle(srcFormat)) { + + GLubyte dstmap[4]; + + /* dstmap - how to swizzle from GL_RGBA to dst format: + */ + dstmap[3] = 3; /* alpha */ + dstmap[2] = 0; /* red */ + dstmap[1] = 1; /* green */ + dstmap[0] = 2; /* blue */ + + _mesa_swizzle_ubyte_image(ctx, dims, + srcFormat, + dstmap, 4, + dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcAddr, + srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLuint *dstUI = (GLuint *) dstRow; + if (dstFormat == &_mesa_texformat_argb8888) { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_rgb888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_rgb888); + ASSERT(dstFormat->TexelBytes == 3); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_BGR && + srcType == GL_UNSIGNED_BYTE && + littleEndian) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcFormat == GL_RGBA && + srcType == GL_UNSIGNED_BYTE) { + /* extract RGB from RGBA */ + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP]; + dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; + dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP]; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = (const GLchan *) tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { +#if 0 + if (littleEndian) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); + dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); + dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); + srcUB += 3; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = srcUB[BCOMP]; + dstRow[col * 3 + 1] = srcUB[GCOMP]; + dstRow[col * 3 + 2] = srcUB[RCOMP]; + srcUB += 3; + } + } +#else + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]); + dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); + dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]); + src += 3; + } +#endif + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_bgr888(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_bgr888); + ASSERT(dstFormat->TexelBytes == 3); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_BYTE && + littleEndian) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcFormat == GL_RGBA && + srcType == GL_UNSIGNED_BYTE) { + /* extract BGR from RGBA */ + int img, row, col; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + for (img = 0; img < srcDepth; img++) { + const GLint srcRowStride = _mesa_image_row_stride(srcPacking, + srcWidth, srcFormat, srcType); + GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP]; + dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; + dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP]; + } + dstRow += dstRowStride; + srcRow += srcRowStride; + } + dstImage += dstImageStride; + } + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = (const GLchan *) tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); + dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); + dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); + src += 3; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_argb4444(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_argb4444 || + dstFormat == &_mesa_texformat_argb4444_rev); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb4444 && + baseInternalFormat == GL_RGBA && + srcFormat == GL_BGRA && + srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLushort *dstUS = (GLushort *) dstRow; + if (dstFormat == &_mesa_texformat_argb4444) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + + +GLboolean +_mesa_texstore_argb1555(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_argb1555 || + dstFormat == &_mesa_texformat_argb1555_rev); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_argb1555 && + baseInternalFormat == GL_RGBA && + srcFormat == GL_BGRA && + srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src =tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLushort *dstUS = (GLushort *) dstRow; + if (dstFormat == &_mesa_texformat_argb1555) { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + else { + for (col = 0; col < srcWidth; col++) { + dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]), + CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 4; + } + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_al88(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + + ASSERT(dstFormat == &_mesa_texformat_al88 || + dstFormat == &_mesa_texformat_al88_rev); + ASSERT(dstFormat->TexelBytes == 2); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + dstFormat == &_mesa_texformat_al88 && + baseInternalFormat == GL_LUMINANCE_ALPHA && + srcFormat == GL_LUMINANCE_ALPHA && + srcType == GL_UNSIGNED_BYTE && + littleEndian) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLushort *dstUS = (GLushort *) dstRow; + if (dstFormat == &_mesa_texformat_al88) { + for (col = 0; col < srcWidth; col++) { + /* src[0] is luminance, src[1] is alpha */ + dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]), + CHAN_TO_UBYTE(src[0]) ); + src += 2; + } + } + else { + for (col = 0; col < srcWidth; col++) { + /* src[0] is luminance, src[1] is alpha */ + dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]), + CHAN_TO_UBYTE(src[0]) ); + src += 2; + } + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +GLboolean +_mesa_texstore_rgb332(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_rgb332); + ASSERT(dstFormat->TexelBytes == 1); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == GL_RGB && + srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]), + CHAN_TO_UBYTE(src[GCOMP]), + CHAN_TO_UBYTE(src[BCOMP]) ); + src += 3; + } + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +/** + * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. + */ +GLboolean +_mesa_texstore_a8(STORE_PARAMS) +{ + ASSERT(dstFormat == &_mesa_texformat_a8 || + dstFormat == &_mesa_texformat_l8 || + dstFormat == &_mesa_texformat_i8); + ASSERT(dstFormat->TexelBytes == 1); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == GL_UNSIGNED_BYTE) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLchan *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + for (col = 0; col < srcWidth; col++) { + dstRow[col] = CHAN_TO_UBYTE(src[col]); + } + dstRow += dstRowStride; + src += srcWidth; + } + dstImage += dstImageStride; + } + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + + +GLboolean +_mesa_texstore_ci8(STORE_PARAMS) +{ + (void) dims; (void) baseInternalFormat; + ASSERT(dstFormat == &_mesa_texformat_ci8); + ASSERT(dstFormat->TexelBytes == 1); + ASSERT(baseInternalFormat == GL_COLOR_INDEX); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcFormat == GL_COLOR_INDEX && + srcType == GL_UNSIGNED_BYTE) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + const GLvoid *src = _mesa_image_address(dims, srcPacking, + srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); + _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow, + srcType, src, srcPacking, + ctx->_ImageTransferState); + dstRow += dstRowStride; + } + dstImage += dstImageStride; + } + } + return GL_TRUE; +} + + +/** + * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev. + */ +GLboolean +_mesa_texstore_ycbcr(STORE_PARAMS) +{ + const GLuint ui = 1; + const GLubyte littleEndian = *((const GLubyte *) &ui); + (void) ctx; (void) dims; (void) baseInternalFormat; + + ASSERT((dstFormat == &_mesa_texformat_ycbcr) || + (dstFormat == &_mesa_texformat_ycbcr_rev)); + ASSERT(dstFormat->TexelBytes == 2); + ASSERT(ctx->Extensions.MESA_ycbcr_texture); + ASSERT(srcFormat == GL_YCBCR_MESA); + ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) || + (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA)); + ASSERT(baseInternalFormat == GL_YCBCR_MESA); + + /* always just memcpy since no pixel transfer ops apply */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + + /* Check if we need byte swapping */ + /* XXX the logic here _might_ be wrong */ + if (srcPacking->SwapBytes ^ + (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^ + (dstFormat == &_mesa_texformat_ycbcr_rev) ^ + !littleEndian) { + GLubyte *pImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + for (img = 0; img < srcDepth; img++) { + GLubyte *pRow = pImage; + for (row = 0; row < srcHeight; row++) { + _mesa_swap2((GLushort *) pRow, srcWidth); + pRow += dstRowStride; + } + pImage += dstImageStride; + } + } + return GL_TRUE; +} + + + + +/** + * Store an image in any of the formats: + * _mesa_texformat_rgba_float32 + * _mesa_texformat_rgb_float32 + * _mesa_texformat_alpha_float32 + * _mesa_texformat_luminance_float32 + * _mesa_texformat_luminance_alpha_float32 + * _mesa_texformat_intensity_float32 + */ +GLboolean +_mesa_texstore_rgba_float32(STORE_PARAMS) +{ + const GLint components = _mesa_components_in_format(baseInternalFormat); + + ASSERT(dstFormat == &_mesa_texformat_rgba_float32 || + dstFormat == &_mesa_texformat_rgb_float32 || + dstFormat == &_mesa_texformat_alpha_float32 || + dstFormat == &_mesa_texformat_luminance_float32 || + dstFormat == &_mesa_texformat_luminance_alpha_float32 || + dstFormat == &_mesa_texformat_intensity_float32); + ASSERT(baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_LUMINANCE || + baseInternalFormat == GL_LUMINANCE_ALPHA || + baseInternalFormat == GL_INTENSITY); + ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == GL_FLOAT) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLfloat *tempImage = make_temp_float_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLfloat *src = tempImage; + GLint bytesPerRow; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + bytesPerRow = srcWidth * components * sizeof(GLfloat); + for (img = 0; img < srcDepth; img++) { + GLubyte *dst = dstImage; + for (row = 0; row < srcHeight; row++) { + _mesa_memcpy(dst, src, bytesPerRow); + dst += dstRowStride; + src += srcWidth * components; + } + dstImage += dstImageStride; + } + + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + +/** + * As above, but store 16-bit floats. + */ +GLboolean +_mesa_texstore_rgba_float16(STORE_PARAMS) +{ + const GLint components = _mesa_components_in_format(baseInternalFormat); + + ASSERT(dstFormat == &_mesa_texformat_rgba_float16 || + dstFormat == &_mesa_texformat_rgb_float16 || + dstFormat == &_mesa_texformat_alpha_float16 || + dstFormat == &_mesa_texformat_luminance_float16 || + dstFormat == &_mesa_texformat_luminance_alpha_float16 || + dstFormat == &_mesa_texformat_intensity_float16); + ASSERT(baseInternalFormat == GL_RGBA || + baseInternalFormat == GL_RGB || + baseInternalFormat == GL_ALPHA || + baseInternalFormat == GL_LUMINANCE || + baseInternalFormat == GL_LUMINANCE_ALPHA || + baseInternalFormat == GL_INTENSITY); + ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB)); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + baseInternalFormat == srcFormat && + srcType == GL_HALF_FLOAT_ARB) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, dstImageStride, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLfloat *tempImage = make_temp_float_image(ctx, dims, + baseInternalFormat, + dstFormat->BaseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking); + const GLfloat *src = tempImage; + GLubyte *dstImage = (GLubyte *) dstAddr + + dstZoffset * dstImageStride + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; + GLint img, row; + if (!tempImage) + return GL_FALSE; + _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = dstImage; + for (row = 0; row < srcHeight; row++) { + GLhalfARB *dstTexel = (GLhalfARB *) dstRow; + GLint i; + for (i = 0; i < srcWidth * components; i++) { + dstTexel[i] = _mesa_float_to_half(src[i]); + } + dstRow += dstRowStride; + src += srcWidth * components; + } + dstImage += dstImageStride; + } + + _mesa_free((void *) tempImage); + } + return GL_TRUE; +} + + + +/** + * Check if an unpack PBO is active prior to fetching a texture image. + * If so, do bounds checking and map the buffer into main memory. + * Any errors detected will be recorded. + * The caller _must_ call _mesa_unmap_teximage_pbo() too! + */ +const GLvoid * +_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack, + const char *funcName) +{ + GLubyte *buf; + + if (unpack->BufferObj->Name == 0) { + /* no PBO */ + return pixels; + } + if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, + format, type, pixels)) { + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); + return NULL; + } + + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, unpack->BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); + return NULL; + } + + return ADD_POINTERS(buf, pixels); +} + + +/** + * Check if an unpack PBO is active prior to fetching a compressed texture + * image. + * If so, do bounds checking and map the buffer into main memory. + * Any errors detected will be recorded. + * The caller _must_ call _mesa_unmap_teximage_pbo() too! + */ +const GLvoid * +_mesa_validate_pbo_compressed_teximage(GLcontext *ctx, + GLsizei imageSize, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + const char *funcName) +{ + GLubyte *buf; + + if (packing->BufferObj->Name == 0) { + /* not using a PBO - return pointer unchanged */ + return pixels; + } + if ((const GLubyte *) pixels + imageSize > + (const GLubyte *)(uintptr_t) packing->BufferObj->Size) { + /* out of bounds read! */ + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); + return NULL; + } + + buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + GL_READ_ONLY_ARB, packing->BufferObj); + if (!buf) { + _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); + return NULL; + } + + return ADD_POINTERS(buf, pixels); +} + + +/** + * This function must be called after either of the validate_pbo_*_teximage() + * functions. It unmaps the PBO buffer if it was mapped earlier. + */ +void +_mesa_unmap_teximage_pbo(GLcontext *ctx, + const struct gl_pixelstore_attrib *unpack) +{ + if (unpack->BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, + unpack->BufferObj); + } +} + + +/* + * This is the software fallback for Driver.TexImage1D() + * and Driver.CopyTexImage1D(). + * \sa _mesa_store_teximage2d() + */ +void +_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + GLint postConvWidth = width; + GLint sizeInBytes; + (void) border; + + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { + _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); + } + + /* choose the texture format */ + assert(ctx->Driver.ChooseTextureFormat); + texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, + format, type); + assert(texImage->TexFormat); + texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; + texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; + + /* allocate memory */ + if (texImage->IsCompressed) + sizeInBytes = texImage->CompressedSize; + else + sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes; + texImage->Data = _mesa_alloc_texmemory(sizeInBytes); + if (!texImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); + return; + } + + pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, + pixels, packing, "glTexImage1D"); + if (!pixels) { + /* Note: we check for a NULL image pointer here, _after_ we allocated + * memory for the texture. That's what the GL spec calls for. + */ + return; + } + else { + const GLint dstRowStride = 0, dstImageStride = 0; + GLboolean success; + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, dstImageStride, + width, 1, 1, + format, type, pixels, packing); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); + } + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + +/** + * This is the software fallback for Driver.TexImage2D() + * and Driver.CopyTexImage2D(). + * We store the image in heap memory. We know nothing about on-board + * VRAM here. But since most DRI drivers rely on keeping a copy of all + * textures in main memory, this routine will typically be used by + * hardware drivers too. + * + * Reasons why a driver might override this function: + * - Special memory allocation needs (VRAM, AGP, etc) + * - Unusual row/image strides or padding + * - Special housekeeping + * - Using VRAM-based Pixel Buffer Objects + */ +void +_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + GLint postConvWidth = width, postConvHeight = height; + GLint texelBytes, sizeInBytes; + (void) border; + + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { + _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, + &postConvHeight); + } + + /* choose the texture format */ + assert(ctx->Driver.ChooseTextureFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); + assert(texImage->TexFormat); + texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; + texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; + + texelBytes = texImage->TexFormat->TexelBytes; + + /* allocate memory */ + if (texImage->IsCompressed) + sizeInBytes = texImage->CompressedSize; + else + sizeInBytes = postConvWidth * postConvHeight * texelBytes; + texImage->Data = _mesa_alloc_texmemory(sizeInBytes); + if (!texImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + return; + } + + pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, + pixels, packing, "glTexImage2D"); + if (!pixels) { + /* Note: we check for a NULL image pointer here, _after_ we allocated + * memory for the texture. That's what the GL spec calls for. + */ + return; + } + else { + GLint dstRowStride, dstImageStride = 0; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width); + } + else { + dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, dstImageStride, + width, height, 1, + format, type, pixels, packing); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + } + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + + +/** + * This is the software fallback for Driver.TexImage3D() + * and Driver.CopyTexImage3D(). + * \sa _mesa_store_teximage2d() + */ +void +_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + GLint texelBytes, sizeInBytes; + (void) border; + + /* choose the texture format */ + assert(ctx->Driver.ChooseTextureFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, format, type); + assert(texImage->TexFormat); + texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; + texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; + + texelBytes = texImage->TexFormat->TexelBytes; + + /* allocate memory */ + if (texImage->IsCompressed) + sizeInBytes = texImage->CompressedSize; + else + sizeInBytes = width * height * depth * texelBytes; + texImage->Data = _mesa_alloc_texmemory(sizeInBytes); + if (!texImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); + return; + } + + pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, + type, pixels, packing, "glTexImage3D"); + if (!pixels) { + /* Note: we check for a NULL image pointer here, _after_ we allocated + * memory for the texture. That's what the GL spec calls for. + */ + return; + } + else { + GLint dstRowStride, dstImageStride; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width); + dstImageStride = 0; + } + else { + dstRowStride = width * texImage->TexFormat->TexelBytes; + dstImageStride = dstRowStride * height; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, dstImageStride, + width, height, depth, + format, type, pixels, packing); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); + } + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + + + +/* + * This is the software fallback for Driver.TexSubImage1D() + * and Driver.CopyTexSubImage1D(). + */ +void +_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint width, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, + pixels, packing, "glTexSubImage1D"); + if (!pixels) + return; + + { + const GLint dstRowStride = 0, dstImageStride = 0; + GLboolean success; + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format, + texImage->TexFormat, + texImage->Data, + xoffset, 0, 0, /* offsets */ + dstRowStride, dstImageStride, + width, 1, 1, + format, type, pixels, packing); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); + } + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + + +/** + * This is the software fallback for Driver.TexSubImage2D() + * and Driver.CopyTexSubImage2D(). + */ +void +_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint width, GLint height, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, + pixels, packing, "glTexSubImage2D"); + if (!pixels) + return; + + { + GLint dstRowStride = 0, dstImageStride = 0; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + } + else { + dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, 0, + dstRowStride, dstImageStride, + width, height, 1, + format, type, pixels, packing); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); + } + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + +/* + * This is the software fallback for Driver.TexSubImage3D(). + * and Driver.CopyTexSubImage3D(). + */ +void +_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, + type, pixels, packing, + "glTexSubImage3D"); + if (!pixels) + return; + + { + GLint dstRowStride, dstImageStride; + GLboolean success; + if (texImage->IsCompressed) { + dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + dstImageStride = 0; /* XXX fix */ + } + else { + dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes; + dstImageStride = dstRowStride * texImage->Height; + } + ASSERT(texImage->TexFormat->StoreImage); + success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, zoffset, + dstRowStride, dstImageStride, + width, height, depth, + format, type, pixels, packing); + if (!success) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); + } + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, packing); +} + + +/* + * Fallback for Driver.CompressedTexImage1D() + */ +void +_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) internalFormat; + (void) width; (void) border; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; +} + + + +/* + * Fallback for Driver.CompressedTexImage2D() + */ +void +_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + (void) width; (void) height; (void) border; + + /* This is pretty simple, basically just do a memcpy without worrying + * about the usual image unpacking or image transfer operations. + */ + ASSERT(texObj); + ASSERT(texImage); + ASSERT(texImage->Width > 0); + ASSERT(texImage->Height > 0); + ASSERT(texImage->Depth == 1); + ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */ + + /* choose the texture format */ + assert(ctx->Driver.ChooseTextureFormat); + texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, + internalFormat, 0, 0); + assert(texImage->TexFormat); + texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; + texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; + + /* allocate storage */ + texImage->Data = _mesa_alloc_texmemory(imageSize); + if (!texImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); + return; + } + + data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, + &ctx->Unpack, + "glCompressedTexImage2D"); + if (!data) + return; + + /* copy the data */ + ASSERT(texImage->CompressedSize == (GLuint) imageSize); + MEMCPY(texImage->Data, data, imageSize); + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); +} + + + +/* + * Fallback for Driver.CompressedTexImage3D() + */ +void +_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, + GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) internalFormat; + (void) width; (void) height; (void) depth; + (void) border; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; +} + + + +/** + * Fallback for Driver.CompressedTexSubImage1D() + */ +void +_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLsizei width, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) xoffset; (void) width; + (void) format; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; +} + + +/** + * Fallback for Driver.CompressedTexSubImage2D() + */ +void +_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + GLint bytesPerRow, destRowStride, srcRowStride; + GLint i, rows; + GLubyte *dest; + const GLubyte *src; + (void) format; + + /* these should have been caught sooner */ + ASSERT((width & 3) == 0 || width == 2 || width == 1); + ASSERT((height & 3) == 0 || height == 2 || height == 1); + ASSERT((xoffset & 3) == 0); + ASSERT((yoffset & 3) == 0); + + data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, + &ctx->Unpack, + "glCompressedTexSubImage2D"); + if (!data) + return; + + srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width); + src = (const GLubyte *) data; + + destRowStride = _mesa_compressed_row_stride(texImage->IntFormat, + texImage->Width); + dest = _mesa_compressed_image_address(xoffset, yoffset, 0, + texImage->IntFormat, + texImage->Width, + (GLubyte*) texImage->Data); + + bytesPerRow = srcRowStride; + rows = height / 4; + + for (i = 0; i < rows; i++) { + MEMCPY(dest, src, bytesPerRow); + dest += destRowStride; + src += srcRowStride; + } + + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } + + _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); +} + + +/** + * Fallback for Driver.CompressedTexSubImage3D() + */ +void +_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + /* this space intentionally left blank */ + (void) ctx; + (void) target; (void) level; + (void) xoffset; (void) yoffset; (void) zoffset; + (void) width; (void) height; (void) depth; + (void) format; + (void) imageSize; (void) data; + (void) texObj; + (void) texImage; +} + + +/* + * Average together two rows of a source image to produce a single new + * row in the dest image. It's legal for the two source rows to point + * to the same data. The source width must be equal to either the + * dest width or two times the dest width. + */ +static void +do_row(const struct gl_texture_format *format, GLint srcWidth, + const GLvoid *srcRowA, const GLvoid *srcRowB, + GLint dstWidth, GLvoid *dstRow) +{ + const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; + const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; + + /* This assertion is no longer valid with non-power-of-2 textures + assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); + */ + + switch (format->MesaFormat) { + case MESA_FORMAT_RGBA: + { + GLuint i, j, k; + const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA; + const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB; + GLchan (*dst)[4] = (GLchan (*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + + rowB[j][3] + rowB[k][3]) / 4; + } + } + return; + case MESA_FORMAT_RGB: + { + GLuint i, j, k; + const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA; + const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB; + GLchan (*dst)[3] = (GLchan (*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) / 4; + } + } + return; + case MESA_FORMAT_ALPHA: + case MESA_FORMAT_LUMINANCE: + case MESA_FORMAT_INTENSITY: + { + GLuint i, j, k; + const GLchan *rowA = (const GLchan *) srcRowA; + const GLchan *rowB = (const GLchan *) srcRowB; + GLchan *dst = (GLchan *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + return; + case MESA_FORMAT_LUMINANCE_ALPHA: + { + GLuint i, j, k; + const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA; + const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB; + GLchan (*dst)[2] = (GLchan (*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) / 4; + } + } + return; + case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32: + { + GLuint i, j, k; + const GLfloat *rowA = (const GLfloat *) srcRowA; + const GLfloat *rowB = (const GLfloat *) srcRowB; + GLfloat *dst = (GLfloat *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; + } + } + return; + case MESA_FORMAT_DEPTH_COMPONENT16: + { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; + } + } + return; + /* Begin hardware formats */ + case MESA_FORMAT_RGBA8888: + case MESA_FORMAT_RGBA8888_REV: + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_ARGB8888_REV: + { + GLuint i, j, k; + const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA; + const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB; + GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) / 4; + dst[i][3] = (rowA[j][3] + rowA[k][3] + + rowB[j][3] + rowB[k][3]) / 4; + } + } + return; + case MESA_FORMAT_RGB888: + case MESA_FORMAT_BGR888: + { + GLuint i, j, k; + const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA; + const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB; + GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) / 4; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) / 4; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) / 4; + } + } + return; + case MESA_FORMAT_RGB565: + case MESA_FORMAT_RGB565_REV: + { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x1f; + const GLint rowAr1 = rowA[k] & 0x1f; + const GLint rowBr0 = rowB[j] & 0x1f; + const GLint rowBr1 = rowB[k] & 0x1f; + const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; + const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; + const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; + const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; + const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + dst[i] = (blue << 11) | (green << 5) | red; + } + } + return; + case MESA_FORMAT_ARGB4444: + case MESA_FORMAT_ARGB4444_REV: + { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0xf; + const GLint rowAr1 = rowA[k] & 0xf; + const GLint rowBr0 = rowB[j] & 0xf; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 4) & 0xf; + const GLint rowAg1 = (rowA[k] >> 4) & 0xf; + const GLint rowBg0 = (rowB[j] >> 4) & 0xf; + const GLint rowBg1 = (rowB[k] >> 4) & 0xf; + const GLint rowAb0 = (rowA[j] >> 8) & 0xf; + const GLint rowAb1 = (rowA[k] >> 8) & 0xf; + const GLint rowBb0 = (rowB[j] >> 8) & 0xf; + const GLint rowBb1 = (rowB[k] >> 8) & 0xf; + const GLint rowAa0 = (rowA[j] >> 12) & 0xf; + const GLint rowAa1 = (rowA[k] >> 12) & 0xf; + const GLint rowBa0 = (rowB[j] >> 12) & 0xf; + const GLint rowBa1 = (rowB[k] >> 12) & 0xf; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; + } + } + return; + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */ + { + GLuint i, j, k; + const GLushort *rowA = (const GLushort *) srcRowA; + const GLushort *rowB = (const GLushort *) srcRowB; + GLushort *dst = (GLushort *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x1f; + const GLint rowAr1 = rowA[k] & 0x1f; + const GLint rowBr0 = rowB[j] & 0x1f; + const GLint rowBr1 = rowB[k] & 0xf; + const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; + const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; + const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; + const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; + const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; + const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; + const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; + const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; + const GLint rowAa0 = (rowA[j] >> 15) & 0x1; + const GLint rowAa1 = (rowA[k] >> 15) & 0x1; + const GLint rowBa0 = (rowB[j] >> 15) & 0x1; + const GLint rowBa1 = (rowB[k] >> 15) & 0x1; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; + dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; + } + } + return; + case MESA_FORMAT_AL88: + case MESA_FORMAT_AL88_REV: + { + GLuint i, j, k; + const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA; + const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB; + GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) >> 2; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) >> 2; + } + } + return; + case MESA_FORMAT_RGB332: + { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + const GLint rowAr0 = rowA[j] & 0x3; + const GLint rowAr1 = rowA[k] & 0x3; + const GLint rowBr0 = rowB[j] & 0x3; + const GLint rowBr1 = rowB[k] & 0x3; + const GLint rowAg0 = (rowA[j] >> 2) & 0x7; + const GLint rowAg1 = (rowA[k] >> 2) & 0x7; + const GLint rowBg0 = (rowB[j] >> 2) & 0x7; + const GLint rowBg1 = (rowB[k] >> 2) & 0x7; + const GLint rowAb0 = (rowA[j] >> 5) & 0x7; + const GLint rowAb1 = (rowA[k] >> 5) & 0x7; + const GLint rowBb0 = (rowB[j] >> 5) & 0x7; + const GLint rowBb1 = (rowB[k] >> 5) & 0x7; + const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; + const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; + const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; + dst[i] = (blue << 5) | (green << 2) | red; + } + } + return; + case MESA_FORMAT_A8: + case MESA_FORMAT_L8: + case MESA_FORMAT_I8: + case MESA_FORMAT_CI8: + { + GLuint i, j, k; + const GLubyte *rowA = (const GLubyte *) srcRowA; + const GLubyte *rowB = (const GLubyte *) srcRowB; + GLubyte *dst = (GLubyte *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; + } + } + return; + case MESA_FORMAT_RGBA_FLOAT32: + { + GLuint i, j, k; + const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA; + const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB; + GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + dst[i][3] = (rowA[j][3] + rowA[k][3] + + rowB[j][3] + rowB[k][3]) * 0.25F; + } + } + return; + case MESA_FORMAT_RGBA_FLOAT16: + { + GLuint i, j, k, comp; + const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA; + const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB; + GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 4; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + return; + case MESA_FORMAT_RGB_FLOAT32: + { + GLuint i, j, k; + const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA; + const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB; + GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + dst[i][2] = (rowA[j][2] + rowA[k][2] + + rowB[j][2] + rowB[k][2]) * 0.25F; + } + } + return; + case MESA_FORMAT_RGB_FLOAT16: + { + GLuint i, j, k, comp; + const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA; + const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB; + GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 3; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + return; + case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32: + { + GLuint i, j, k; + const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA; + const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB; + GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i][0] = (rowA[j][0] + rowA[k][0] + + rowB[j][0] + rowB[k][0]) * 0.25F; + dst[i][1] = (rowA[j][1] + rowA[k][1] + + rowB[j][1] + rowB[k][1]) * 0.25F; + } + } + return; + case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16: + { + GLuint i, j, k, comp; + const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA; + const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB; + GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + for (comp = 0; comp < 2; comp++) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j][comp]); + ak = _mesa_half_to_float(rowA[k][comp]); + bj = _mesa_half_to_float(rowB[j][comp]); + bk = _mesa_half_to_float(rowB[k][comp]); + dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + } + return; + case MESA_FORMAT_ALPHA_FLOAT32: + case MESA_FORMAT_LUMINANCE_FLOAT32: + case MESA_FORMAT_INTENSITY_FLOAT32: + { + GLuint i, j, k; + const GLfloat *rowA = (const GLfloat *) srcRowA; + const GLfloat *rowB = (const GLfloat *) srcRowB; + GLfloat *dst = (GLfloat *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; + } + } + return; + case MESA_FORMAT_ALPHA_FLOAT16: + case MESA_FORMAT_LUMINANCE_FLOAT16: + case MESA_FORMAT_INTENSITY_FLOAT16: + { + GLuint i, j, k; + const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; + const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; + GLhalfARB *dst = (GLhalfARB *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + GLfloat aj, ak, bj, bk; + aj = _mesa_half_to_float(rowA[j]); + ak = _mesa_half_to_float(rowA[k]); + bj = _mesa_half_to_float(rowB[j]); + bk = _mesa_half_to_float(rowB[k]); + dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); + } + } + return; + + default: + _mesa_problem(NULL, "bad format in do_row()"); + } +} + + +/* + * These functions generate a 1/2-size mipmap image from a source image. + * Texture borders are handled by copying or averaging the source image's + * border texels, depending on the scale-down factor. + */ + +static void +make_1d_mipmap(const struct gl_texture_format *format, GLint border, + GLint srcWidth, const GLubyte *srcPtr, + GLint dstWidth, GLubyte *dstPtr) +{ + const GLint bpt = format->TexelBytes; + const GLubyte *src; + GLubyte *dst; + + /* skip the border pixel, if any */ + src = srcPtr + border * bpt; + dst = dstPtr + border * bpt; + + /* we just duplicate the input row, kind of hack, saves code */ + do_row(format, srcWidth - 2 * border, src, src, + dstWidth - 2 * border, dst); + + if (border) { + /* copy left-most pixel from source */ + MEMCPY(dstPtr, srcPtr, bpt); + /* copy right-most pixel from source */ + MEMCPY(dstPtr + (dstWidth - 1) * bpt, + srcPtr + (srcWidth - 1) * bpt, + bpt); + } +} + + +static void +make_2d_mipmap(const struct gl_texture_format *format, GLint border, + GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr, + GLint dstWidth, GLint dstHeight, GLubyte *dstPtr) +{ + const GLint bpt = format->TexelBytes; + const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ + const GLint dstWidthNB = dstWidth - 2 * border; + const GLint dstHeightNB = dstHeight - 2 * border; + const GLint srcRowStride = bpt * srcWidth; + const GLint dstRowStride = bpt * dstWidth; + const GLubyte *srcA, *srcB; + GLubyte *dst; + GLint row; + + /* Compute src and dst pointers, skipping any border */ + srcA = srcPtr + border * ((srcWidth + 1) * bpt); + if (srcHeight > 1) + srcB = srcA + srcRowStride; + else + srcB = srcA; + dst = dstPtr + border * ((dstWidth + 1) * bpt); + + for (row = 0; row < dstHeightNB; row++) { + do_row(format, srcWidthNB, srcA, srcB, + dstWidthNB, dst); + srcA += 2 * srcRowStride; + srcB += 2 * srcRowStride; + dst += dstRowStride; + } + + /* This is ugly but probably won't be used much */ + if (border > 0) { + /* fill in dest border */ + /* lower-left border pixel */ + MEMCPY(dstPtr, srcPtr, bpt); + /* lower-right border pixel */ + MEMCPY(dstPtr + (dstWidth - 1) * bpt, + srcPtr + (srcWidth - 1) * bpt, bpt); + /* upper-left border pixel */ + MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt, + srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); + /* upper-right border pixel */ + MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt, + srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); + /* lower border */ + do_row(format, srcWidthNB, + srcPtr + bpt, + srcPtr + bpt, + dstWidthNB, dstPtr + bpt); + /* upper border */ + do_row(format, srcWidthNB, + srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, + srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, + dstWidthNB, + dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); + /* left and right borders */ + if (srcHeight == dstHeight) { + /* copy border pixel from src to dst */ + for (row = 1; row < srcHeight; row++) { + MEMCPY(dstPtr + dstWidth * row * bpt, + srcPtr + srcWidth * row * bpt, bpt); + MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, + srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); + } + } + else { + /* average two src pixels each dest pixel */ + for (row = 0; row < dstHeightNB; row += 2) { + do_row(format, 1, + srcPtr + (srcWidth * (row * 2 + 1)) * bpt, + srcPtr + (srcWidth * (row * 2 + 2)) * bpt, + 1, dstPtr + (dstWidth * row + 1) * bpt); + do_row(format, 1, + srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, + srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, + 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); + } + } + } +} + + +static void +make_3d_mipmap(const struct gl_texture_format *format, GLint border, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + const GLubyte *srcPtr, + GLint dstWidth, GLint dstHeight, GLint dstDepth, + GLubyte *dstPtr) +{ + const GLint bpt = format->TexelBytes; + const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ + const GLint srcDepthNB = srcDepth - 2 * border; + const GLint dstWidthNB = dstWidth - 2 * border; + const GLint dstHeightNB = dstHeight - 2 * border; + const GLint dstDepthNB = dstDepth - 2 * border; + GLvoid *tmpRowA, *tmpRowB; + GLint img, row; + GLint bytesPerSrcImage, bytesPerDstImage; + GLint bytesPerSrcRow, bytesPerDstRow; + GLint srcImageOffset, srcRowOffset; + + (void) srcDepthNB; /* silence warnings */ + + /* Need two temporary row buffers */ + tmpRowA = _mesa_malloc(srcWidth * bpt); + if (!tmpRowA) + return; + tmpRowB = _mesa_malloc(srcWidth * bpt); + if (!tmpRowB) { + _mesa_free(tmpRowA); + return; + } + + bytesPerSrcImage = srcWidth * srcHeight * bpt; + bytesPerDstImage = dstWidth * dstHeight * bpt; + + bytesPerSrcRow = srcWidth * bpt; + bytesPerDstRow = dstWidth * bpt; + + /* Offset between adjacent src images to be averaged together */ + srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; + + /* Offset between adjacent src rows to be averaged together */ + srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; + + /* + * Need to average together up to 8 src pixels for each dest pixel. + * Break that down into 3 operations: + * 1. take two rows from source image and average them together. + * 2. take two rows from next source image and average them together. + * 3. take the two averaged rows and average them for the final dst row. + */ + + /* + _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n", + srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); + */ + + for (img = 0; img < dstDepthNB; img++) { + /* first source image pointer, skipping border */ + const GLubyte *imgSrcA = srcPtr + + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border + + img * (bytesPerSrcImage + srcImageOffset); + /* second source image pointer, skipping border */ + const GLubyte *imgSrcB = imgSrcA + srcImageOffset; + /* address of the dest image, skipping border */ + GLubyte *imgDst = dstPtr + + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border + + img * bytesPerDstImage; + + /* setup the four source row pointers and the dest row pointer */ + const GLubyte *srcImgARowA = imgSrcA; + const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; + const GLubyte *srcImgBRowA = imgSrcB; + const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; + GLubyte *dstImgRow = imgDst; + + for (row = 0; row < dstHeightNB; row++) { + /* Average together two rows from first src image */ + do_row(format, srcWidthNB, srcImgARowA, srcImgARowB, + srcWidthNB, tmpRowA); + /* Average together two rows from second src image */ + do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB, + srcWidthNB, tmpRowB); + /* Average together the temp rows to make the final row */ + do_row(format, srcWidthNB, tmpRowA, tmpRowB, + dstWidthNB, dstImgRow); + /* advance to next rows */ + srcImgARowA += bytesPerSrcRow + srcRowOffset; + srcImgARowB += bytesPerSrcRow + srcRowOffset; + srcImgBRowA += bytesPerSrcRow + srcRowOffset; + srcImgBRowB += bytesPerSrcRow + srcRowOffset; + dstImgRow += bytesPerDstRow; + } + } + + _mesa_free(tmpRowA); + _mesa_free(tmpRowB); + + /* Luckily we can leverage the make_2d_mipmap() function here! */ + if (border > 0) { + /* do front border image */ + make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr, + dstWidth, dstHeight, dstPtr); + /* do back border image */ + make_2d_mipmap(format, 1, srcWidth, srcHeight, + srcPtr + bytesPerSrcImage * (srcDepth - 1), + dstWidth, dstHeight, + dstPtr + bytesPerDstImage * (dstDepth - 1)); + /* do four remaining border edges that span the image slices */ + if (srcDepth == dstDepth) { + /* just copy border pixels from src to dst */ + for (img = 0; img < dstDepthNB; img++) { + const GLubyte *src; + GLubyte *dst; + + /* do border along [img][row=0][col=0] */ + src = srcPtr + (img + 1) * bytesPerSrcImage; + dst = dstPtr + (img + 1) * bytesPerDstImage; + MEMCPY(dst, src, bpt); + + /* do border along [img][row=dstHeight-1][col=0] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcHeight - 1) * bytesPerSrcRow; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstHeight - 1) * bytesPerDstRow; + MEMCPY(dst, src, bpt); + + /* do border along [img][row=0][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcWidth - 1) * bpt; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstWidth - 1) * bpt; + MEMCPY(dst, src, bpt); + + /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (bytesPerSrcImage - bpt); + dst = dstPtr + (img + 1) * bytesPerDstImage + + (bytesPerDstImage - bpt); + MEMCPY(dst, src, bpt); + } + } + else { + /* average border pixels from adjacent src image pairs */ + ASSERT(srcDepthNB == 2 * dstDepthNB); + for (img = 0; img < dstDepthNB; img++) { + const GLubyte *src; + GLubyte *dst; + + /* do border along [img][row=0][col=0] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; + dst = dstPtr + (img + 1) * bytesPerDstImage; + do_row(format, 1, src, src + srcImageOffset, 1, dst); + + /* do border along [img][row=dstHeight-1][col=0] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcHeight - 1) * bytesPerSrcRow; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstHeight - 1) * bytesPerDstRow; + do_row(format, 1, src, src + srcImageOffset, 1, dst); + + /* do border along [img][row=0][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (srcWidth - 1) * bpt; + dst = dstPtr + (img + 1) * bytesPerDstImage + + (dstWidth - 1) * bpt; + do_row(format, 1, src, src + srcImageOffset, 1, dst); + + /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ + src = srcPtr + (img * 2 + 1) * bytesPerSrcImage + + (bytesPerSrcImage - bpt); + dst = dstPtr + (img + 1) * bytesPerDstImage + + (bytesPerDstImage - bpt); + do_row(format, 1, src, src + srcImageOffset, 1, dst); + } + } + } +} + + +/* + * For GL_SGIX_generate_mipmap: + * Generate a complete set of mipmaps from texObj's base-level image. + * Stop at texObj's MaxLevel or when we get to the 1x1 texture. + */ +void +_mesa_generate_mipmap(GLcontext *ctx, GLenum target, + const struct gl_texture_unit *texUnit, + struct gl_texture_object *texObj) +{ + const struct gl_texture_image *srcImage; + const struct gl_texture_format *convertFormat; + const GLubyte *srcData = NULL; + GLubyte *dstData = NULL; + GLint level, maxLevels; + + ASSERT(texObj); + /* XXX choose cube map face here??? */ + srcImage = texObj->Image[0][texObj->BaseLevel]; + ASSERT(srcImage); + + maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); + ASSERT(maxLevels > 0); /* bad target */ + + /* Find convertFormat - the format that do_row() will process */ + if (srcImage->IsCompressed) { + /* setup for compressed textures */ + GLuint row; + GLint components, size; + GLchan *dst; + + assert(texObj->Target == GL_TEXTURE_2D); + + if (srcImage->Format == GL_RGB) { + convertFormat = &_mesa_texformat_rgb; + components = 3; + } + else if (srcImage->Format == GL_RGBA) { + convertFormat = &_mesa_texformat_rgba; + components = 4; + } + else { + _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps"); + return; + } + + /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ + size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE) + * srcImage->Width * srcImage->Height * srcImage->Depth + 20; + /* 20 extra bytes, just be safe when calling last FetchTexel */ + srcData = (GLubyte *) _mesa_malloc(size); + if (!srcData) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + return; + } + dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */ + if (!dstData) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); + _mesa_free((void *) srcData); + return; + } + + /* decompress base image here */ + dst = (GLchan *) srcData; + for (row = 0; row < srcImage->Height; row++) { + GLuint col; + for (col = 0; col < srcImage->Width; col++) { + srcImage->FetchTexelc(srcImage, col, row, 0, dst); + dst += components; + } + } + } + else { + /* uncompressed */ + convertFormat = srcImage->TexFormat; + } + + for (level = texObj->BaseLevel; level < texObj->MaxLevel + && level < maxLevels - 1; level++) { + /* generate image[level+1] from image[level] */ + const struct gl_texture_image *srcImage; + struct gl_texture_image *dstImage; + GLint srcWidth, srcHeight, srcDepth; + GLint dstWidth, dstHeight, dstDepth; + GLint border, bytesPerTexel; + + /* get src image parameters */ + srcImage = _mesa_select_tex_image(ctx, texUnit, target, level); + ASSERT(srcImage); + srcWidth = srcImage->Width; + srcHeight = srcImage->Height; + srcDepth = srcImage->Depth; + border = srcImage->Border; + + /* compute next (level+1) image size */ + if (srcWidth - 2 * border > 1) { + dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; + } + else { + dstWidth = srcWidth; /* can't go smaller */ + } + if (srcHeight - 2 * border > 1) { + dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; + } + else { + dstHeight = srcHeight; /* can't go smaller */ + } + if (srcDepth - 2 * border > 1) { + dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; + } + else { + dstDepth = srcDepth; /* can't go smaller */ + } + + if (dstWidth == srcWidth && + dstHeight == srcHeight && + dstDepth == srcDepth) { + /* all done */ + if (srcImage->IsCompressed) { + _mesa_free((void *) srcData); + _mesa_free(dstData); + } + return; + } + + /* get dest gl_texture_image */ + dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1); + if (!dstImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + + /* Free old image data */ + if (dstImage->Data) + ctx->Driver.FreeTexImageData(ctx, dstImage); + + /* initialize new image */ + _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, + dstDepth, border, srcImage->IntFormat); + dstImage->DriverData = NULL; + dstImage->TexFormat = srcImage->TexFormat; + dstImage->FetchTexelc = srcImage->FetchTexelc; + dstImage->FetchTexelf = srcImage->FetchTexelf; + ASSERT(dstImage->TexFormat); + ASSERT(dstImage->FetchTexelc); + ASSERT(dstImage->FetchTexelf); + + /* Alloc new teximage data buffer. + * Setup src and dest data pointers. + */ + if (dstImage->IsCompressed) { + ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/ + dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize); + if (!dstImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + /* srcData and dstData are already set */ + ASSERT(srcData); + ASSERT(dstData); + } + else { + bytesPerTexel = srcImage->TexFormat->TexelBytes; + ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0); + dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight + * dstDepth * bytesPerTexel); + if (!dstImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); + return; + } + srcData = (const GLubyte *) srcImage->Data; + dstData = (GLubyte *) dstImage->Data; + } + + /* + * We use simple 2x2 averaging to compute the next mipmap level. + */ + switch (target) { + case GL_TEXTURE_1D: + make_1d_mipmap(convertFormat, border, + srcWidth, srcData, + dstWidth, dstData); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + make_2d_mipmap(convertFormat, border, + srcWidth, srcHeight, srcData, + dstWidth, dstHeight, dstData); + break; + case GL_TEXTURE_3D: + make_3d_mipmap(convertFormat, border, + srcWidth, srcHeight, srcDepth, srcData, + dstWidth, dstHeight, dstDepth, dstData); + break; + case GL_TEXTURE_RECTANGLE_NV: + /* no mipmaps, do nothing */ + break; + default: + _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps"); + return; + } + + if (dstImage->IsCompressed) { + GLubyte *temp; + /* compress image from dstData into dstImage->Data */ + const GLenum srcFormat = convertFormat->BaseFormat; + GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat, + dstWidth); + ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); + dstImage->TexFormat->StoreImage(ctx, 2, dstImage->Format, + dstImage->TexFormat, + dstImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, 0, /* strides */ + dstWidth, dstHeight, 1, /* size */ + srcFormat, CHAN_TYPE, + dstData, /* src data, actually */ + &ctx->DefaultPacking); + /* swap src and dest pointers */ + temp = (GLubyte *) srcData; + srcData = dstData; + dstData = temp; + } + + } /* loop over mipmap levels */ +} + + +/** + * Helper function for drivers which need to rescale texture images to + * certain aspect ratios. + * Nearest filtering only (for broken hardware that can't support + * all aspect ratios). This can be made a lot faster, but I don't + * really care enough... + */ +void +_mesa_rescale_teximage2d (GLuint bytesPerPixel, + GLuint srcStrideInPixels, + GLuint dstRowStride, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage) +{ + GLint row, col; + +#define INNER_LOOP( TYPE, HOP, WOP ) \ + for ( row = 0 ; row < dstHeight ; row++ ) { \ + GLint srcRow = row HOP hScale; \ + for ( col = 0 ; col < dstWidth ; col++ ) { \ + GLint srcCol = col WOP wScale; \ + dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ + } \ + dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ + } \ + +#define RESCALE_IMAGE( TYPE ) \ +do { \ + const TYPE *src = (const TYPE *)srcImage; \ + TYPE *dst = (TYPE *)dstImage; \ + \ + if ( srcHeight < dstHeight ) { \ + const GLint hScale = dstHeight / srcHeight; \ + if ( srcWidth < dstWidth ) { \ + const GLint wScale = dstWidth / srcWidth; \ + INNER_LOOP( TYPE, /, / ); \ + } \ + else { \ + const GLint wScale = srcWidth / dstWidth; \ + INNER_LOOP( TYPE, /, * ); \ + } \ + } \ + else { \ + const GLint hScale = srcHeight / dstHeight; \ + if ( srcWidth < dstWidth ) { \ + const GLint wScale = dstWidth / srcWidth; \ + INNER_LOOP( TYPE, *, / ); \ + } \ + else { \ + const GLint wScale = srcWidth / dstWidth; \ + INNER_LOOP( TYPE, *, * ); \ + } \ + } \ +} while (0) + + switch ( bytesPerPixel ) { + case 4: + RESCALE_IMAGE( GLuint ); + break; + + case 2: + RESCALE_IMAGE( GLushort ); + break; + + case 1: + RESCALE_IMAGE( GLubyte ); + break; + default: + _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); + } +} + + +/** + * Upscale an image by replication, not (typical) stretching. + * We use this when the image width or height is less than a + * certain size (4, 8) and we need to upscale an image. + */ +void +_mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight, + GLsizei outWidth, GLsizei outHeight, + GLint comps, const GLchan *src, GLint srcRowStride, + GLchan *dest ) +{ + GLint i, j, k; + + ASSERT(outWidth >= inWidth); + ASSERT(outHeight >= inHeight); +#if 0 + ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); + ASSERT((outWidth & 3) == 0); + ASSERT((outHeight & 3) == 0); +#endif + + for (i = 0; i < outHeight; i++) { + const GLint ii = i % inHeight; + for (j = 0; j < outWidth; j++) { + const GLint jj = j % inWidth; + for (k = 0; k < comps; k++) { + dest[(i * outWidth + j) * comps + k] + = src[ii * srcRowStride + jj * comps + k]; + } + } + } +} + + + +/** + * This is the software fallback for Driver.GetTexImage(). + * All error checking will have been done before this routine is called. + */ +void +_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage) +{ + GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; + + if (ctx->Pack.BufferObj->Name) { + /* pack texture image into a PBO */ + GLubyte *buf; + if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, + texImage->Height, texImage->Depth, + format, type, pixels)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetTexImage(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)"); + return; + } + pixels = ADD_POINTERS(buf, pixels); + } + else if (!pixels) { + /* not an error */ + return; + } + + { + const GLint width = texImage->Width; + const GLint height = texImage->Height; + const GLint depth = texImage->Depth; + GLint img, row; + for (img = 0; img < depth; img++) { + for (row = 0; row < height; row++) { + /* compute destination address in client memory */ + GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels, + width, height, format, type, + img, row, 0); + assert(dest); + + if (format == GL_COLOR_INDEX) { + GLuint indexRow[MAX_WIDTH]; + GLint col; + /* Can't use FetchTexel here because that returns RGBA */ + if (texImage->TexFormat->IndexBits == 8) { + const GLubyte *src = (const GLubyte *) texImage->Data; + for (col = 0; col < width; col++) { + indexRow[col] = src[texImage->Width * + (img * texImage->Height + row) + col]; + } + } + else if (texImage->TexFormat->IndexBits == 16) { + const GLushort *src = (const GLushort *) texImage->Data; + for (col = 0; col < width; col++) { + indexRow[col] = src[texImage->Width * + (img * texImage->Height + row) + col]; + } + } + else { + _mesa_problem(ctx, + "Color index problem in _mesa_GetTexImage"); + } + _mesa_pack_index_span(ctx, width, type, dest, + indexRow, &ctx->Pack, + 0 /* no image transfer */); + } + else if (format == GL_DEPTH_COMPONENT) { + GLfloat depthRow[MAX_WIDTH]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexelf)(texImage, col, row, img, + depthRow + col); + } + _mesa_pack_depth_span(ctx, width, dest, type, + depthRow, &ctx->Pack); + } + else if (format == GL_YCBCR_MESA) { + /* No pixel transfer */ + const GLint rowstride = texImage->RowStride; + MEMCPY(dest, + (const GLushort *) texImage->Data + row * rowstride, + width * sizeof(GLushort)); + /* check for byte swapping */ + if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR + && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || + (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV + && type == GL_UNSIGNED_SHORT_8_8_MESA)) { + if (!ctx->Pack.SwapBytes) + _mesa_swap2((GLushort *) dest, width); + } + else if (ctx->Pack.SwapBytes) { + _mesa_swap2((GLushort *) dest, width); + } + } + else { + /* general case: convert row to RGBA format */ + GLfloat rgba[MAX_WIDTH][4]; + GLint col; + for (col = 0; col < width; col++) { + (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); + } + _mesa_pack_rgba_span_float(ctx, width, + (const GLfloat (*)[4]) rgba, + format, type, dest, &ctx->Pack, + 0 /* no image transfer */); + } /* format */ + } /* row */ + } /* img */ + } + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} + + + +/** + * This is the software fallback for Driver.GetCompressedTexImage(). + * All error checking will have been done before this routine is called. + */ +void +_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, + GLvoid *img, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage) +{ + if (ctx->Pack.BufferObj->Name) { + /* pack texture image into a PBO */ + GLubyte *buf; + if ((const GLubyte *) img + texImage->CompressedSize > + (const GLubyte *) ctx->Pack.BufferObj->Size) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTexImage(invalid PBO access)"); + return; + } + buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + GL_WRITE_ONLY_ARB, + ctx->Pack.BufferObj); + if (!buf) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetCompressedTexImage(PBO is mapped)"); + return; + } + img = ADD_POINTERS(buf, img); + } + else if (!img) { + /* not an error */ + return; + } + + /* just memcpy, no pixelstore or pixel transfer */ + MEMCPY(img, texImage->Data, texImage->CompressedSize); + + if (ctx->Pack.BufferObj->Name) { + ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, + ctx->Pack.BufferObj); + } +} diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h new file mode 100644 index 00000000000..0b91f20e3a0 --- /dev/null +++ b/src/mesa/main/texstore.h @@ -0,0 +1,261 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file texstore.h + * Texture image storage routines. + * + * \author Brian Paul + */ + + +#ifndef TEXSTORE_H +#define TEXSTORE_H + + +#include "mtypes.h" + +/* Macro just to save some typing */ +#define STORE_PARAMS \ + GLcontext *ctx, GLuint dims, \ + GLenum baseInternalFormat, \ + const struct gl_texture_format *dstFormat, \ + GLvoid *dstAddr, \ + GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, \ + GLint dstRowStride, GLint dstImageStride, \ + GLint srcWidth, GLint srcHeight, GLint srcDepth, \ + GLenum srcFormat, GLenum srcType, \ + const GLvoid *srcAddr, \ + const struct gl_pixelstore_attrib *srcPacking + + +extern GLboolean _mesa_texstore_rgba(STORE_PARAMS); +extern GLboolean _mesa_texstore_color_index(STORE_PARAMS); +extern GLboolean _mesa_texstore_depth_component16(STORE_PARAMS); +extern GLboolean _mesa_texstore_depth_component_float32(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba8888(STORE_PARAMS); +extern GLboolean _mesa_texstore_argb8888(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgb888(STORE_PARAMS); +extern GLboolean _mesa_texstore_bgr888(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgb565(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgb565_rev(STORE_PARAMS); +extern GLboolean _mesa_texstore_argb4444(STORE_PARAMS); +extern GLboolean _mesa_texstore_argb4444_rev(STORE_PARAMS); +extern GLboolean _mesa_texstore_argb1555(STORE_PARAMS); +extern GLboolean _mesa_texstore_argb1555_rev(STORE_PARAMS); +extern GLboolean _mesa_texstore_al88(STORE_PARAMS); +extern GLboolean _mesa_texstore_al88_rev(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgb332(STORE_PARAMS); +extern GLboolean _mesa_texstore_a8(STORE_PARAMS); +extern GLboolean _mesa_texstore_ci8(STORE_PARAMS); +extern GLboolean _mesa_texstore_ycbcr(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba_float32(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba_float16(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgb_fxt1(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba_fxt1(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgb_dxt1(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba_dxt1(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba_dxt3(STORE_PARAMS); +extern GLboolean _mesa_texstore_rgba_dxt5(STORE_PARAMS); + + +extern GLchan * +_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, + GLenum logicalBaseFormat, + GLenum textureBaseFormat, + GLint srcWidth, GLint srcHeight, GLint srcDepth, + GLenum srcFormat, GLenum srcType, + const GLvoid *srcAddr, + const struct gl_pixelstore_attrib *srcPacking); + + +extern void +_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint width, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint width, GLint height, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +extern void +_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +extern void +_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, + GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLsizei width, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +extern void +_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +extern void +_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + + +extern void +_mesa_generate_mipmap(GLcontext *ctx, GLenum target, + const struct gl_texture_unit *texUnit, + struct gl_texture_object *texObj); + + +extern void +_mesa_rescale_teximage2d(GLuint bytesPerPixel, + GLuint srcStrideInPixels, + GLuint dstRowStride, + GLint srcWidth, GLint srcHeight, + GLint dstWidth, GLint dstHeight, + const GLvoid *srcImage, GLvoid *dstImage); + +extern void +_mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, + GLsizei outWidth, GLsizei outHeight, + GLint comps, const GLchan *src, GLint srcRowStride, + GLchan *dest); + + +extern void +_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage); + + +extern void +_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, + GLvoid *img, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage); + +extern const GLvoid * +_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack, + const char *funcName); + +extern const GLvoid * +_mesa_validate_pbo_compressed_teximage(GLcontext *ctx, + GLsizei imageSize, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + const char *funcName); + +extern void +_mesa_unmap_teximage_pbo(GLcontext *ctx, + const struct gl_pixelstore_attrib *unpack); + + +#endif diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c new file mode 100644 index 00000000000..6781b698150 --- /dev/null +++ b/src/mesa/main/varray.c @@ -0,0 +1,994 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "bufferobj.h" +#include "context.h" +#include "enable.h" +#include "enums.h" +#include "dlist.h" +#include "texstate.h" +#include "mtypes.h" +#include "varray.h" +#include "dispatch.h" + +#ifndef GL_BOOLEAN +#define GL_BOOLEAN 0x9999 +#endif + + +/** + * Update the fields of a vertex array structure. + * We need to do a few special things for arrays that live in + * vertex buffer objects. + */ +static void +update_array(GLcontext *ctx, struct gl_client_array *array, + GLuint dirtyFlag, GLsizei elementSize, + GLint size, GLenum type, + GLsizei stride, GLboolean normalized, const GLvoid *ptr) +{ + array->Size = size; + array->Type = type; + array->Stride = stride; + array->StrideB = stride ? stride : elementSize; + array->Normalized = normalized; + array->Ptr = (const GLubyte *) ptr; +#if FEATURE_ARB_vertex_buffer_object + array->BufferObj->RefCount--; + if (array->BufferObj->RefCount <= 0) { + ASSERT(array->BufferObj->Name); + _mesa_remove_buffer_object( ctx, array->BufferObj ); + (*ctx->Driver.DeleteBuffer)( ctx, array->BufferObj ); + } + array->BufferObj = ctx->Array.ArrayBufferObj; + array->BufferObj->RefCount++; + /* Compute the index of the last array element that's inside the buffer. + * Later in glDrawArrays we'll check if start + count > _MaxElement to + * be sure we won't go out of bounds. + */ + if (ctx->Array.ArrayBufferObj->Name) + array->_MaxElement = ((GLsizeiptrARB) ctx->Array.ArrayBufferObj->Size + - (GLsizeiptrARB) array->Ptr) / array->StrideB; + else +#endif + array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */ + + ctx->NewState |= _NEW_ARRAY; + ctx->Array.NewState |= dirtyFlag; +} + + +void GLAPIENTRY +_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (size < 2 || size > 4) { + _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" ); + return; + } + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size, + _mesa_lookup_enum_by_nr( type ), stride); + + /* always need to check that <type> is legal */ + switch (type) { + case GL_SHORT: + elementSize = size * sizeof(GLshort); + break; + case GL_INT: + elementSize = size * sizeof(GLint); + break; + case GL_FLOAT: + elementSize = size * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = size * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.Vertex, _NEW_ARRAY_VERTEX, + elementSize, size, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.VertexPointer) + ctx->Driver.VertexPointer( ctx, size, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr ) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n", + _mesa_lookup_enum_by_nr( type ), stride); + + switch (type) { + case GL_BYTE: + elementSize = 3 * sizeof(GLbyte); + break; + case GL_SHORT: + elementSize = 3 * sizeof(GLshort); + break; + case GL_INT: + elementSize = 3 * sizeof(GLint); + break; + case GL_FLOAT: + elementSize = 3 * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = 3 * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.Normal, _NEW_ARRAY_NORMAL, + elementSize, 3, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.NormalPointer) + ctx->Driver.NormalPointer( ctx, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (size < 3 || size > 4) { + _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" ); + return; + } + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size, + _mesa_lookup_enum_by_nr( type ), stride); + + switch (type) { + case GL_BYTE: + elementSize = size * sizeof(GLbyte); + break; + case GL_UNSIGNED_BYTE: + elementSize = size * sizeof(GLubyte); + break; + case GL_SHORT: + elementSize = size * sizeof(GLshort); + break; + case GL_UNSIGNED_SHORT: + elementSize = size * sizeof(GLushort); + break; + case GL_INT: + elementSize = size * sizeof(GLint); + break; + case GL_UNSIGNED_INT: + elementSize = size * sizeof(GLuint); + break; + case GL_FLOAT: + elementSize = size * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = size * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.Color, _NEW_ARRAY_COLOR0, + elementSize, size, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.ColorPointer) + ctx->Driver.ColorPointer( ctx, size, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr) +{ + GLint elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" ); + return; + } + + switch (type) { + case GL_FLOAT: + elementSize = sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.FogCoord, _NEW_ARRAY_FOGCOORD, + elementSize, 1, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.FogCoordPointer) + ctx->Driver.FogCoordPointer( ctx, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" ); + return; + } + + switch (type) { + case GL_UNSIGNED_BYTE: + elementSize = sizeof(GLubyte); + break; + case GL_SHORT: + elementSize = sizeof(GLshort); + break; + case GL_INT: + elementSize = sizeof(GLint); + break; + case GL_FLOAT: + elementSize = sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.Index, _NEW_ARRAY_INDEX, + elementSize, 1, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.IndexPointer) + ctx->Driver.IndexPointer( ctx, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_SecondaryColorPointerEXT(GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (size != 3 && size != 4) { + _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)" ); + return; + } + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n", + size, _mesa_lookup_enum_by_nr( type ), stride); + + switch (type) { + case GL_BYTE: + elementSize = size * sizeof(GLbyte); + break; + case GL_UNSIGNED_BYTE: + elementSize = size * sizeof(GLubyte); + break; + case GL_SHORT: + elementSize = size * sizeof(GLshort); + break; + case GL_UNSIGNED_SHORT: + elementSize = size * sizeof(GLushort); + break; + case GL_INT: + elementSize = size * sizeof(GLint); + break; + case GL_UNSIGNED_INT: + elementSize = size * sizeof(GLuint); + break; + case GL_FLOAT: + elementSize = size * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = size * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.SecondaryColor, _NEW_ARRAY_COLOR1, + elementSize, size, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.SecondaryColorPointer) + ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr) +{ + GLint elementSize; + GET_CURRENT_CONTEXT(ctx); + const GLuint unit = ctx->Array.ActiveTexture; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (size < 1 || size > 4) { + _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" ); + return; + } + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" ); + return; + } + + if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API)) + _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n", + unit, size, _mesa_lookup_enum_by_nr( type ), stride); + + /* always need to check that <type> is legal */ + switch (type) { + case GL_SHORT: + elementSize = size * sizeof(GLshort); + break; + case GL_INT: + elementSize = size * sizeof(GLint); + break; + case GL_FLOAT: + elementSize = size * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = size * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" ); + return; + } + + update_array(ctx, &ctx->Array.TexCoord[unit], _NEW_ARRAY_TEXCOORD(unit), + elementSize, size, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.TexCoordPointer) + ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr ); +} + + +void GLAPIENTRY +_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" ); + return; + } + + update_array(ctx, &ctx->Array.EdgeFlag, _NEW_ARRAY_EDGEFLAG, + sizeof(GLboolean), 1, GL_BOOLEAN, stride, GL_FALSE, ptr); + + if (ctx->Driver.EdgeFlagPointer) + ctx->Driver.EdgeFlagPointer( ctx, stride, ptr ); +} + + +#if FEATURE_NV_vertex_program +void GLAPIENTRY +_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= VERT_ATTRIB_MAX) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)"); + return; + } + + if (size < 1 || size > 4) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)"); + return; + } + + if (stride < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)"); + return; + } + + if (type == GL_UNSIGNED_BYTE && size != 4) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)"); + return; + } + + /* check for valid 'type' and compute StrideB right away */ + switch (type) { + case GL_UNSIGNED_BYTE: + elementSize = size * sizeof(GLubyte); + break; + case GL_SHORT: + elementSize = size * sizeof(GLshort); + break; + case GL_FLOAT: + elementSize = size * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = size * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" ); + return; + } + + update_array(ctx, &ctx->Array.VertexAttrib[index], _NEW_ARRAY_ATTRIB(index), + elementSize, size, type, stride, GL_FALSE, ptr); + + if (ctx->Driver.VertexAttribPointer) + ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr ); +} +#endif + + +#if FEATURE_ARB_vertex_program +void GLAPIENTRY +_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type, + GLboolean normalized, + GLsizei stride, const GLvoid *ptr) +{ + GLsizei elementSize; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (index >= ctx->Const.MaxVertexProgramAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)"); + return; + } + + if (size < 1 || size > 4) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)"); + return; + } + + if (stride < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)"); + return; + } + + if (type == GL_UNSIGNED_BYTE && size != 4) { + _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size!=4)"); + return; + } + + /* check for valid 'type' and compute StrideB right away */ + /* NOTE: more types are supported here than in the NV extension */ + switch (type) { + case GL_BYTE: + elementSize = size * sizeof(GLbyte); + break; + case GL_UNSIGNED_BYTE: + elementSize = size * sizeof(GLubyte); + break; + case GL_SHORT: + elementSize = size * sizeof(GLshort); + break; + case GL_UNSIGNED_SHORT: + elementSize = size * sizeof(GLushort); + break; + case GL_INT: + elementSize = size * sizeof(GLint); + break; + case GL_UNSIGNED_INT: + elementSize = size * sizeof(GLuint); + break; + case GL_FLOAT: + elementSize = size * sizeof(GLfloat); + break; + case GL_DOUBLE: + elementSize = size * sizeof(GLdouble); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" ); + return; + } + + update_array(ctx, &ctx->Array.VertexAttrib[index], _NEW_ARRAY_ATTRIB(index), + elementSize, size, type, stride, normalized, ptr); + + /* XXX fix + if (ctx->Driver.VertexAttribPointer) + ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr ); + */ +} +#endif + + +void GLAPIENTRY +_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr) +{ + (void) count; + _mesa_VertexPointer(size, type, stride, ptr); +} + + +void GLAPIENTRY +_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr) +{ + (void) count; + _mesa_NormalPointer(type, stride, ptr); +} + + +void GLAPIENTRY +_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr) +{ + (void) count; + _mesa_ColorPointer(size, type, stride, ptr); +} + + +void GLAPIENTRY +_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr) +{ + (void) count; + _mesa_IndexPointer(type, stride, ptr); +} + + +void GLAPIENTRY +_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr) +{ + (void) count; + _mesa_TexCoordPointer(size, type, stride, ptr); +} + + +void GLAPIENTRY +_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr) +{ + (void) count; + _mesa_EdgeFlagPointer(stride, ptr); +} + + +void GLAPIENTRY +_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) +{ + GET_CURRENT_CONTEXT(ctx); + GLboolean tflag, cflag, nflag; /* enable/disable flags */ + GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */ + GLenum ctype = 0; /* color type */ + GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */ + const GLint toffset = 0; /* always zero */ + GLint defstride; /* default stride */ + GLint c, f; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + f = sizeof(GLfloat); + c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f); + + if (stride < 0) { + _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" ); + return; + } + + switch (format) { + case GL_V2F: + tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 0; ccomps = 0; vcomps = 2; + voffset = 0; + defstride = 2*f; + break; + case GL_V3F: + tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 0; ccomps = 0; vcomps = 3; + voffset = 0; + defstride = 3*f; + break; + case GL_C4UB_V2F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 0; ccomps = 4; vcomps = 2; + ctype = GL_UNSIGNED_BYTE; + coffset = 0; + voffset = c; + defstride = c + 2*f; + break; + case GL_C4UB_V3F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 0; ccomps = 4; vcomps = 3; + ctype = GL_UNSIGNED_BYTE; + coffset = 0; + voffset = c; + defstride = c + 3*f; + break; + case GL_C3F_V3F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 0; ccomps = 3; vcomps = 3; + ctype = GL_FLOAT; + coffset = 0; + voffset = 3*f; + defstride = 6*f; + break; + case GL_N3F_V3F: + tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE; + tcomps = 0; ccomps = 0; vcomps = 3; + noffset = 0; + voffset = 3*f; + defstride = 6*f; + break; + case GL_C4F_N3F_V3F: + tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE; + tcomps = 0; ccomps = 4; vcomps = 3; + ctype = GL_FLOAT; + coffset = 0; + noffset = 4*f; + voffset = 7*f; + defstride = 10*f; + break; + case GL_T2F_V3F: + tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 2; ccomps = 0; vcomps = 3; + voffset = 2*f; + defstride = 5*f; + break; + case GL_T4F_V4F: + tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE; + tcomps = 4; ccomps = 0; vcomps = 4; + voffset = 4*f; + defstride = 8*f; + break; + case GL_T2F_C4UB_V3F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 2; ccomps = 4; vcomps = 3; + ctype = GL_UNSIGNED_BYTE; + coffset = 2*f; + voffset = c+2*f; + defstride = c+5*f; + break; + case GL_T2F_C3F_V3F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE; + tcomps = 2; ccomps = 3; vcomps = 3; + ctype = GL_FLOAT; + coffset = 2*f; + voffset = 5*f; + defstride = 8*f; + break; + case GL_T2F_N3F_V3F: + tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE; + tcomps = 2; ccomps = 0; vcomps = 3; + noffset = 2*f; + voffset = 5*f; + defstride = 8*f; + break; + case GL_T2F_C4F_N3F_V3F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; + tcomps = 2; ccomps = 4; vcomps = 3; + ctype = GL_FLOAT; + coffset = 2*f; + noffset = 6*f; + voffset = 9*f; + defstride = 12*f; + break; + case GL_T4F_C4F_N3F_V4F: + tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE; + tcomps = 4; ccomps = 4; vcomps = 4; + ctype = GL_FLOAT; + coffset = 4*f; + noffset = 8*f; + voffset = 11*f; + defstride = 15*f; + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" ); + return; + } + + if (stride==0) { + stride = defstride; + } + + _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY ); + _mesa_DisableClientState( GL_INDEX_ARRAY ); + + /* Texcoords */ + if (tflag) { + _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY ); + _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride, + (GLubyte *) pointer + toffset ); + } + else { + _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY ); + } + + /* Color */ + if (cflag) { + _mesa_EnableClientState( GL_COLOR_ARRAY ); + _mesa_ColorPointer( ccomps, ctype, stride, + (GLubyte *) pointer + coffset ); + } + else { + _mesa_DisableClientState( GL_COLOR_ARRAY ); + } + + + /* Normals */ + if (nflag) { + _mesa_EnableClientState( GL_NORMAL_ARRAY ); + _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset ); + } + else { + _mesa_DisableClientState( GL_NORMAL_ARRAY ); + } + + /* Vertices */ + _mesa_EnableClientState( GL_VERTEX_ARRAY ); + _mesa_VertexPointer( vcomps, GL_FLOAT, stride, + (GLubyte *) pointer + voffset ); +} + + +void GLAPIENTRY +_mesa_LockArraysEXT(GLint first, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glLockArrays %d %d\n", first, count); + + if (first == 0 && count > 0 && + count <= (GLint) ctx->Const.MaxArrayLockSize) { + ctx->Array.LockFirst = first; + ctx->Array.LockCount = count; + } + else { + ctx->Array.LockFirst = 0; + ctx->Array.LockCount = 0; + } + + ctx->NewState |= _NEW_ARRAY; + ctx->Array.NewState |= _NEW_ARRAY_ALL; + + if (ctx->Driver.LockArraysEXT) + ctx->Driver.LockArraysEXT( ctx, first, count ); +} + + +void GLAPIENTRY +_mesa_UnlockArraysEXT( void ) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glUnlockArrays\n"); + + ctx->Array.LockFirst = 0; + ctx->Array.LockCount = 0; + ctx->NewState |= _NEW_ARRAY; + ctx->Array.NewState |= _NEW_ARRAY_ALL; + + if (ctx->Driver.UnlockArraysEXT) + ctx->Driver.UnlockArraysEXT( ctx ); +} + + +/* GL_EXT_multi_draw_arrays */ +/* Somebody forgot to spec the first and count parameters as const! <sigh> */ +void GLAPIENTRY +_mesa_MultiDrawArraysEXT( GLenum mode, GLint *first, + GLsizei *count, GLsizei primcount ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + for (i = 0; i < primcount; i++) { + if (count[i] > 0) { + CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i])); + } + } +} + + +/* GL_EXT_multi_draw_arrays */ +void GLAPIENTRY +_mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type, + const GLvoid **indices, GLsizei primcount ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + for (i = 0; i < primcount; i++) { + if (count[i] > 0) { + CALL_DrawElements(ctx->Exec, (mode, count[i], type, indices[i])); + } + } +} + + +/* GL_IBM_multimode_draw_arrays */ +void GLAPIENTRY +_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first, + const GLsizei * count, + GLsizei primcount, GLint modestride ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + for ( i = 0 ; i < primcount ; i++ ) { + if ( count[i] > 0 ) { + GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); + CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] )); + } + } +} + + +/* GL_IBM_multimode_draw_arrays */ +void GLAPIENTRY +_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count, + GLenum type, const GLvoid * const * indices, + GLsizei primcount, GLint modestride ) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + + /* XXX not sure about ARB_vertex_buffer_object handling here */ + + for ( i = 0 ; i < primcount ; i++ ) { + if ( count[i] > 0 ) { + GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride)); + CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] )); + } + } +} + + +/**********************************************************************/ +/***** Initialization *****/ +/**********************************************************************/ + +void +_mesa_init_varray( GLcontext * ctx ) +{ + GLuint i; + + /* Vertex arrays */ + ctx->Array.Vertex.Size = 4; + ctx->Array.Vertex.Type = GL_FLOAT; + ctx->Array.Vertex.Stride = 0; + ctx->Array.Vertex.StrideB = 0; + ctx->Array.Vertex.Ptr = NULL; + ctx->Array.Vertex.Enabled = GL_FALSE; + ctx->Array.Vertex.Flags = CA_CLIENT_DATA; + ctx->Array.Normal.Type = GL_FLOAT; + ctx->Array.Normal.Stride = 0; + ctx->Array.Normal.StrideB = 0; + ctx->Array.Normal.Ptr = NULL; + ctx->Array.Normal.Enabled = GL_FALSE; + ctx->Array.Normal.Flags = CA_CLIENT_DATA; + ctx->Array.Color.Size = 4; + ctx->Array.Color.Type = GL_FLOAT; + ctx->Array.Color.Stride = 0; + ctx->Array.Color.StrideB = 0; + ctx->Array.Color.Ptr = NULL; + ctx->Array.Color.Enabled = GL_FALSE; + ctx->Array.Color.Flags = CA_CLIENT_DATA; + ctx->Array.SecondaryColor.Size = 4; + ctx->Array.SecondaryColor.Type = GL_FLOAT; + ctx->Array.SecondaryColor.Stride = 0; + ctx->Array.SecondaryColor.StrideB = 0; + ctx->Array.SecondaryColor.Ptr = NULL; + ctx->Array.SecondaryColor.Enabled = GL_FALSE; + ctx->Array.SecondaryColor.Flags = CA_CLIENT_DATA; + ctx->Array.FogCoord.Size = 1; + ctx->Array.FogCoord.Type = GL_FLOAT; + ctx->Array.FogCoord.Stride = 0; + ctx->Array.FogCoord.StrideB = 0; + ctx->Array.FogCoord.Ptr = NULL; + ctx->Array.FogCoord.Enabled = GL_FALSE; + ctx->Array.FogCoord.Flags = CA_CLIENT_DATA; + ctx->Array.Index.Type = GL_FLOAT; + ctx->Array.Index.Stride = 0; + ctx->Array.Index.StrideB = 0; + ctx->Array.Index.Ptr = NULL; + ctx->Array.Index.Enabled = GL_FALSE; + ctx->Array.Index.Flags = CA_CLIENT_DATA; + for (i = 0; i < MAX_TEXTURE_UNITS; i++) { + ctx->Array.TexCoord[i].Size = 4; + ctx->Array.TexCoord[i].Type = GL_FLOAT; + ctx->Array.TexCoord[i].Stride = 0; + ctx->Array.TexCoord[i].StrideB = 0; + ctx->Array.TexCoord[i].Ptr = NULL; + ctx->Array.TexCoord[i].Enabled = GL_FALSE; + ctx->Array.TexCoord[i].Flags = CA_CLIENT_DATA; + } + ctx->Array.EdgeFlag.Stride = 0; + ctx->Array.EdgeFlag.StrideB = 0; + ctx->Array.EdgeFlag.Ptr = NULL; + ctx->Array.EdgeFlag.Enabled = GL_FALSE; + ctx->Array.EdgeFlag.Flags = CA_CLIENT_DATA; + ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + ctx->Array.VertexAttrib[i].Size = 4; + ctx->Array.VertexAttrib[i].Type = GL_FLOAT; + ctx->Array.VertexAttrib[i].Stride = 0; + ctx->Array.VertexAttrib[i].StrideB = 0; + ctx->Array.VertexAttrib[i].Ptr = NULL; + ctx->Array.VertexAttrib[i].Enabled = GL_FALSE; + ctx->Array.VertexAttrib[i].Flags = CA_CLIENT_DATA; + } +} diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h new file mode 100644 index 00000000000..3589735f684 --- /dev/null +++ b/src/mesa/main/varray.h @@ -0,0 +1,160 @@ +/** + * \file varray.h + * Vertex arrays. + * + * \if subset + * (No-op) + * + * \endif + */ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef VARRAY_H +#define VARRAY_H + + +#include "mtypes.h" + +#if _HAVE_FULL_GL + +extern void GLAPIENTRY +_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr); + +extern void GLAPIENTRY +_mesa_UnlockArraysEXT( void ); + +extern void GLAPIENTRY +_mesa_LockArraysEXT(GLint first, GLsizei count); + + +extern void GLAPIENTRY +_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count, + const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr); + + +extern void GLAPIENTRY +_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_SecondaryColorPointerEXT(GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr); + + +extern void GLAPIENTRY +_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer); + + +extern void GLAPIENTRY +_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type, + GLboolean normalized, GLsizei stride, + const GLvoid *pointer); + + +extern void GLAPIENTRY +_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer); + + +extern void GLAPIENTRY +_mesa_MultiDrawArraysEXT( GLenum mode, GLint *first, + GLsizei *count, GLsizei primcount ); + +extern void GLAPIENTRY +_mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type, + const GLvoid **indices, GLsizei primcount ); + + +extern void GLAPIENTRY +_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first, + const GLsizei * count, + GLsizei primcount, GLint modestride ); + + +extern void GLAPIENTRY +_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count, + GLenum type, const GLvoid * const * indices, + GLsizei primcount, GLint modestride ); + + +extern void +_mesa_init_varray( GLcontext * ctx ); + +#else + +/** No-op */ +#define _mesa_init_varray( c ) ((void)0) + +#endif + +#endif diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h new file mode 100644 index 00000000000..f2987b9f504 --- /dev/null +++ b/src/mesa/main/version.h @@ -0,0 +1,52 @@ +/* + * Mesa 3-D graphics library + * Version: 6.4 + * + * Copyright (C) 1999-2005 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef VERSION_H +#define VERSION_H + + +/* Mesa version */ +#define MESA_MAJOR 6 +#define MESA_MINOR 4 +#define MESA_PATCH 0 +#define MESA_VERSION_STRING "6.4" + +/* To make version comparison easy */ +#define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#define MESA_VERSION_CODE MESA_VERSION(MESA_MAJOR, MESA_MINOR, MESA_PATCH) + + +/* OpenGL API version */ +#define OPENGL_MAJOR 1 +#define OPENGL_MINOR 5 +#define OPENGL_PATCH 0 +#define OPENGL_VERSION_STRING "1.5" + +/* To make version comparison easy */ +#define OPENGL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#define OPENGL_VERSION_CODE OPENGL_VERSION(OPENGL_MAJOR, OPENGL_MINOR, OPENGL_PATCH) + + +#endif /* VERSION_H */ diff --git a/src/mesa/main/vsnprintf.c b/src/mesa/main/vsnprintf.c new file mode 100644 index 00000000000..ab6c740d772 --- /dev/null +++ b/src/mesa/main/vsnprintf.c @@ -0,0 +1,165 @@ +/* + * Revision 12: http://theos.com/~deraadt/snprintf.c + * + * Copyright (c) 1997 Theo de Raadt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __VMS +# include <sys/param.h> +#endif +#include <sys/types.h> +#include <sys/mman.h> +#include <signal.h> +#include <stdio.h> +#if __STDC__ +#include <stdarg.h> +#include <stdlib.h> +#else +#include <varargs.h> +#endif +#include <setjmp.h> +#include <unistd.h> +#include <string.h> + +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif + +#ifdef __sgi +#define size_t ssize_t +#endif + +static int pgsize; +static char *curobj; +static int caught; +static sigjmp_buf bail; + +#define EXTRABYTES 2 /* XXX: why 2? you don't want to know */ + +static char * +msetup(str, n) + char *str; + size_t n; +{ + char *e; + + if (n == 0) + return NULL; + if (pgsize == 0) + pgsize = getpagesize(); + curobj = (char *)malloc(n + EXTRABYTES + pgsize * 2); + if (curobj == NULL) + return NULL; + e = curobj + n + EXTRABYTES; + e = (char *)roundup((unsigned long)e, pgsize); + if (mprotect(e, pgsize, PROT_NONE) == -1) { + free(curobj); + curobj = NULL; + return NULL; + } + e = e - n - EXTRABYTES; + *e = '\0'; + return (e); +} + +static void + mcatch( int a ) +{ + siglongjmp(bail, 1); +} + +static void +mcleanup(str, n, p) + char *str; + size_t n; + char *p; +{ + strncpy(str, p, n-1); + str[n-1] = '\0'; + if (mprotect((caddr_t)(p + n + EXTRABYTES), pgsize, + PROT_READ|PROT_WRITE|PROT_EXEC) == -1) + mprotect((caddr_t)(p + n + EXTRABYTES), pgsize, + PROT_READ|PROT_WRITE); + free(curobj); +} + +int +#if __STDC__ +vsnprintf(char *str, size_t n, char const *fmt, va_list ap) +#else +vsnprintf(str, n, fmt, ap) + char *str; + size_t n; + char *fmt; + char *ap; +#endif +{ + struct sigaction osa, nsa; + char *p; + int ret = n + 1; /* if we bail, indicated we overflowed */ + + memset(&nsa, 0, sizeof nsa); + nsa.sa_handler = mcatch; + sigemptyset(&nsa.sa_mask); + + p = msetup(str, n); + if (p == NULL) { + *str = '\0'; + return 0; + } + if (sigsetjmp(bail, 1) == 0) { + if (sigaction(SIGSEGV, &nsa, &osa) == -1) { + mcleanup(str, n, p); + return (0); + } + ret = vsprintf(p, fmt, ap); + } + mcleanup(str, n, p); + (void) sigaction(SIGSEGV, &osa, NULL); + return (ret); +} + +int +#if __STDC__ +snprintf(char *str, size_t n, char const *fmt, ...) +#else +snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + + return (vsnprintf(str, n, fmt, ap)); + va_end(ap); +} + + + diff --git a/src/mesa/main/vtxfmt.c b/src/mesa/main/vtxfmt.c new file mode 100644 index 00000000000..b3c63982911 --- /dev/null +++ b/src/mesa/main/vtxfmt.c @@ -0,0 +1,185 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <[email protected]> + * Gareth Hughes + */ + +#include "glheader.h" +#include "api_loopback.h" +#include "context.h" +#include "imports.h" +#include "mtypes.h" +#include "state.h" +#include "vtxfmt.h" + + +/* The neutral vertex format. This wraps all tnl module functions, + * verifying that the currently-installed module is valid and then + * installing the function pointers in a lazy fashion. It records the + * function pointers that have been swapped out, which allows a fast + * restoration of the neutral module in almost all cases -- a typical + * app might only require 4-6 functions to be modified from the neutral + * baseline, and only restoring these is certainly preferable to doing + * the entire module's 60 or so function pointers. + */ + +#define PRE_LOOPBACK( FUNC ) \ +{ \ + GET_CURRENT_CONTEXT(ctx); \ + struct gl_tnl_module * const tnl = &(ctx->TnlModule); \ + const int tmp_offset = _gloffset_ ## FUNC ; \ + \ + ASSERT( tnl->Current ); \ + ASSERT( tnl->SwapCount < NUM_VERTEX_FORMAT_ENTRIES ); \ + ASSERT( tmp_offset >= 0 ); \ + \ + /* Save the swapped function's dispatch entry so it can be */ \ + /* restored later. */ \ + tnl->Swapped[tnl->SwapCount].location = & (((_glapi_proc *)ctx->Exec)[tmp_offset]); \ + tnl->Swapped[tnl->SwapCount].function = (_glapi_proc)TAG(FUNC); \ + tnl->SwapCount++; \ + \ + if ( 0 ) \ + _mesa_debug(ctx, " swapping gl" #FUNC"...\n" ); \ + \ + /* Install the tnl function pointer. */ \ + SET_ ## FUNC(ctx->Exec, tnl->Current->FUNC); \ +} + +#define TAG(x) neutral_##x +#include "vtxfmt_tmp.h" + + + +static void +install_vtxfmt( struct _glapi_table *tab, const GLvertexformat *vfmt ) +{ + SET_ArrayElement(tab, vfmt->ArrayElement); + SET_Color3f(tab, vfmt->Color3f); + SET_Color3fv(tab, vfmt->Color3fv); + SET_Color4f(tab, vfmt->Color4f); + SET_Color4fv(tab, vfmt->Color4fv); + SET_EdgeFlag(tab, vfmt->EdgeFlag); + SET_EdgeFlagv(tab, vfmt->EdgeFlagv); + SET_EvalCoord1f(tab, vfmt->EvalCoord1f); + SET_EvalCoord1fv(tab, vfmt->EvalCoord1fv); + SET_EvalCoord2f(tab, vfmt->EvalCoord2f); + SET_EvalCoord2fv(tab, vfmt->EvalCoord2fv); + SET_EvalPoint1(tab, vfmt->EvalPoint1); + SET_EvalPoint2(tab, vfmt->EvalPoint2); + SET_FogCoordfEXT(tab, vfmt->FogCoordfEXT); + SET_FogCoordfvEXT(tab, vfmt->FogCoordfvEXT); + SET_Indexf(tab, vfmt->Indexf); + SET_Indexfv(tab, vfmt->Indexfv); + SET_Materialfv(tab, vfmt->Materialfv); + SET_MultiTexCoord1fARB(tab, vfmt->MultiTexCoord1fARB); + SET_MultiTexCoord1fvARB(tab, vfmt->MultiTexCoord1fvARB); + SET_MultiTexCoord2fARB(tab, vfmt->MultiTexCoord2fARB); + SET_MultiTexCoord2fvARB(tab, vfmt->MultiTexCoord2fvARB); + SET_MultiTexCoord3fARB(tab, vfmt->MultiTexCoord3fARB); + SET_MultiTexCoord3fvARB(tab, vfmt->MultiTexCoord3fvARB); + SET_MultiTexCoord4fARB(tab, vfmt->MultiTexCoord4fARB); + SET_MultiTexCoord4fvARB(tab, vfmt->MultiTexCoord4fvARB); + SET_Normal3f(tab, vfmt->Normal3f); + SET_Normal3fv(tab, vfmt->Normal3fv); + SET_SecondaryColor3fEXT(tab, vfmt->SecondaryColor3fEXT); + SET_SecondaryColor3fvEXT(tab, vfmt->SecondaryColor3fvEXT); + SET_TexCoord1f(tab, vfmt->TexCoord1f); + SET_TexCoord1fv(tab, vfmt->TexCoord1fv); + SET_TexCoord2f(tab, vfmt->TexCoord2f); + SET_TexCoord2fv(tab, vfmt->TexCoord2fv); + SET_TexCoord3f(tab, vfmt->TexCoord3f); + SET_TexCoord3fv(tab, vfmt->TexCoord3fv); + SET_TexCoord4f(tab, vfmt->TexCoord4f); + SET_TexCoord4fv(tab, vfmt->TexCoord4fv); + SET_Vertex2f(tab, vfmt->Vertex2f); + SET_Vertex2fv(tab, vfmt->Vertex2fv); + SET_Vertex3f(tab, vfmt->Vertex3f); + SET_Vertex3fv(tab, vfmt->Vertex3fv); + SET_Vertex4f(tab, vfmt->Vertex4f); + SET_Vertex4fv(tab, vfmt->Vertex4fv); + SET_CallList(tab, vfmt->CallList); + SET_CallLists(tab, vfmt->CallLists); + SET_Begin(tab, vfmt->Begin); + SET_End(tab, vfmt->End); + SET_VertexAttrib1fNV(tab, vfmt->VertexAttrib1fNV); + SET_VertexAttrib1fvNV(tab, vfmt->VertexAttrib1fvNV); + SET_VertexAttrib2fNV(tab, vfmt->VertexAttrib2fNV); + SET_VertexAttrib2fvNV(tab, vfmt->VertexAttrib2fvNV); + SET_VertexAttrib3fNV(tab, vfmt->VertexAttrib3fNV); + SET_VertexAttrib3fvNV(tab, vfmt->VertexAttrib3fvNV); + SET_VertexAttrib4fNV(tab, vfmt->VertexAttrib4fNV); + SET_VertexAttrib4fvNV(tab, vfmt->VertexAttrib4fvNV); + SET_VertexAttrib1fARB(tab, vfmt->VertexAttrib1fARB); + SET_VertexAttrib1fvARB(tab, vfmt->VertexAttrib1fvARB); + SET_VertexAttrib2fARB(tab, vfmt->VertexAttrib2fARB); + SET_VertexAttrib2fvARB(tab, vfmt->VertexAttrib2fvARB); + SET_VertexAttrib3fARB(tab, vfmt->VertexAttrib3fARB); + SET_VertexAttrib3fvARB(tab, vfmt->VertexAttrib3fvARB); + SET_VertexAttrib4fARB(tab, vfmt->VertexAttrib4fARB); + SET_VertexAttrib4fvARB(tab, vfmt->VertexAttrib4fvARB); + SET_Rectf(tab, vfmt->Rectf); + SET_DrawArrays(tab, vfmt->DrawArrays); + SET_DrawElements(tab, vfmt->DrawElements); + SET_DrawRangeElements(tab, vfmt->DrawRangeElements); + SET_EvalMesh1(tab, vfmt->EvalMesh1); + SET_EvalMesh2(tab, vfmt->EvalMesh2); + ASSERT(tab->EvalMesh2); +} + + +void _mesa_init_exec_vtxfmt( GLcontext *ctx ) +{ + install_vtxfmt( ctx->Exec, &neutral_vtxfmt ); + ctx->TnlModule.SwapCount = 0; +} + + +void _mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt ) +{ + ctx->TnlModule.Current = vfmt; + _mesa_restore_exec_vtxfmt( ctx ); +} + + +void _mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt ) +{ + install_vtxfmt( ctx->Save, vfmt ); +} + + +void _mesa_restore_exec_vtxfmt( GLcontext *ctx ) +{ + struct gl_tnl_module *tnl = &(ctx->TnlModule); + GLuint i; + + /* Restore the neutral tnl module wrapper. + */ + for ( i = 0 ; i < tnl->SwapCount ; i++ ) { + *(tnl->Swapped[i].location) = tnl->Swapped[i].function; + } + + tnl->SwapCount = 0; +} diff --git a/src/mesa/main/vtxfmt.h b/src/mesa/main/vtxfmt.h new file mode 100644 index 00000000000..76f108e0232 --- /dev/null +++ b/src/mesa/main/vtxfmt.h @@ -0,0 +1,43 @@ +/** + * \file vtxfmt.h + * + * \author Keith Whitwell <[email protected]> + * \author Gareth Hughes + */ + +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _VTXFMT_H_ +#define _VTXFMT_H_ + +extern void _mesa_init_exec_vtxfmt( GLcontext *ctx ); + +extern void _mesa_install_exec_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt ); +extern void _mesa_install_save_vtxfmt( GLcontext *ctx, const GLvertexformat *vfmt ); + +extern void _mesa_restore_exec_vtxfmt( GLcontext *ctx ); + +#endif diff --git a/src/mesa/main/vtxfmt_tmp.h b/src/mesa/main/vtxfmt_tmp.h new file mode 100644 index 00000000000..2a0fdde4665 --- /dev/null +++ b/src/mesa/main/vtxfmt_tmp.h @@ -0,0 +1,537 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes + */ + +#ifndef PRE_LOOPBACK +#define PRE_LOOPBACK( FUNC ) +#endif + +#include "dispatch.h" +#include "glapioffsets.h" + +static void GLAPIENTRY TAG(ArrayElement)( GLint i ) +{ + PRE_LOOPBACK( ArrayElement ); + CALL_ArrayElement(GET_DISPATCH(), ( i )); +} + +static void GLAPIENTRY TAG(Color3f)( GLfloat r, GLfloat g, GLfloat b ) +{ + PRE_LOOPBACK( Color3f ); + CALL_Color3f(GET_DISPATCH(), ( r, g, b )); +} + +static void GLAPIENTRY TAG(Color3fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Color3fv ); + CALL_Color3fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + PRE_LOOPBACK( Color4f ); + CALL_Color4f(GET_DISPATCH(), ( r, g, b, a )); +} + +static void GLAPIENTRY TAG(Color4fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Color4fv ); + CALL_Color4fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(EdgeFlag)( GLboolean e ) +{ + PRE_LOOPBACK( EdgeFlag ); + CALL_EdgeFlag(GET_DISPATCH(), ( e )); +} + +static void GLAPIENTRY TAG(EdgeFlagv)( const GLboolean *v ) +{ + PRE_LOOPBACK( EdgeFlagv ); + CALL_EdgeFlagv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(EvalCoord1f)( GLfloat s ) +{ + PRE_LOOPBACK( EvalCoord1f ); + CALL_EvalCoord1f(GET_DISPATCH(), ( s )); +} + +static void GLAPIENTRY TAG(EvalCoord1fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( EvalCoord1fv ); + CALL_EvalCoord1fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(EvalCoord2f)( GLfloat s, GLfloat t ) +{ + PRE_LOOPBACK( EvalCoord2f ); + CALL_EvalCoord2f(GET_DISPATCH(), ( s, t )); +} + +static void GLAPIENTRY TAG(EvalCoord2fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( EvalCoord2fv ); + CALL_EvalCoord2fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(EvalPoint1)( GLint i ) +{ + PRE_LOOPBACK( EvalPoint1 ); + CALL_EvalPoint1(GET_DISPATCH(), ( i )); +} + +static void GLAPIENTRY TAG(EvalPoint2)( GLint i, GLint j ) +{ + PRE_LOOPBACK( EvalPoint2 ); + CALL_EvalPoint2(GET_DISPATCH(), ( i, j )); +} + +static void GLAPIENTRY TAG(FogCoordfEXT)( GLfloat f ) +{ + PRE_LOOPBACK( FogCoordfEXT ); + CALL_FogCoordfEXT(GET_DISPATCH(), ( f )); +} + +static void GLAPIENTRY TAG(FogCoordfvEXT)( const GLfloat *v ) +{ + PRE_LOOPBACK( FogCoordfvEXT ); + CALL_FogCoordfvEXT(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(Indexf)( GLfloat f ) +{ + PRE_LOOPBACK( Indexf ); + CALL_Indexf(GET_DISPATCH(), ( f )); +} + +static void GLAPIENTRY TAG(Indexfv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Indexfv ); + CALL_Indexfv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(Materialfv)( GLenum face, GLenum pname, const GLfloat *v ) +{ + PRE_LOOPBACK( Materialfv ); + CALL_Materialfv(GET_DISPATCH(), ( face, pname, v )); +} + +static void GLAPIENTRY TAG(MultiTexCoord1fARB)( GLenum target, GLfloat a ) +{ + PRE_LOOPBACK( MultiTexCoord1fARB ); + CALL_MultiTexCoord1fARB(GET_DISPATCH(), ( target, a )); +} + +static void GLAPIENTRY TAG(MultiTexCoord1fvARB)( GLenum target, const GLfloat *tc ) +{ + PRE_LOOPBACK( MultiTexCoord1fvARB ); + CALL_MultiTexCoord1fvARB(GET_DISPATCH(), ( target, tc )); +} + +static void GLAPIENTRY TAG(MultiTexCoord2fARB)( GLenum target, GLfloat s, GLfloat t ) +{ + PRE_LOOPBACK( MultiTexCoord2fARB ); + CALL_MultiTexCoord2fARB(GET_DISPATCH(), ( target, s, t )); +} + +static void GLAPIENTRY TAG(MultiTexCoord2fvARB)( GLenum target, const GLfloat *tc ) +{ + PRE_LOOPBACK( MultiTexCoord2fvARB ); + CALL_MultiTexCoord2fvARB(GET_DISPATCH(), ( target, tc )); +} + +static void GLAPIENTRY TAG(MultiTexCoord3fARB)( GLenum target, GLfloat s, + GLfloat t, GLfloat r ) +{ + PRE_LOOPBACK( MultiTexCoord3fARB ); + CALL_MultiTexCoord3fARB(GET_DISPATCH(), ( target, s, t, r )); +} + +static void GLAPIENTRY TAG(MultiTexCoord3fvARB)( GLenum target, const GLfloat *tc ) +{ + PRE_LOOPBACK( MultiTexCoord3fvARB ); + CALL_MultiTexCoord3fvARB(GET_DISPATCH(), ( target, tc )); +} + +static void GLAPIENTRY TAG(MultiTexCoord4fARB)( GLenum target, GLfloat s, + GLfloat t, GLfloat r, GLfloat q ) +{ + PRE_LOOPBACK( MultiTexCoord4fARB ); + CALL_MultiTexCoord4fARB(GET_DISPATCH(), ( target, s, t, r, q )); +} + +static void GLAPIENTRY TAG(MultiTexCoord4fvARB)( GLenum target, const GLfloat *tc ) +{ + PRE_LOOPBACK( MultiTexCoord4fvARB ); + CALL_MultiTexCoord4fvARB(GET_DISPATCH(), ( target, tc )); +} + +static void GLAPIENTRY TAG(Normal3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + PRE_LOOPBACK( Normal3f ); + CALL_Normal3f(GET_DISPATCH(), ( x, y, z )); +} + +static void GLAPIENTRY TAG(Normal3fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Normal3fv ); + CALL_Normal3fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(SecondaryColor3fEXT)( GLfloat r, GLfloat g, GLfloat b ) +{ + PRE_LOOPBACK( SecondaryColor3fEXT ); + CALL_SecondaryColor3fEXT(GET_DISPATCH(), ( r, g, b )); +} + +static void GLAPIENTRY TAG(SecondaryColor3fvEXT)( const GLfloat *v ) +{ + PRE_LOOPBACK( SecondaryColor3fvEXT ); + CALL_SecondaryColor3fvEXT(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(TexCoord1f)( GLfloat s ) +{ + PRE_LOOPBACK( TexCoord1f ); + CALL_TexCoord1f(GET_DISPATCH(), ( s )); +} + +static void GLAPIENTRY TAG(TexCoord1fv)( const GLfloat *tc ) +{ + PRE_LOOPBACK( TexCoord1fv ); + CALL_TexCoord1fv(GET_DISPATCH(), ( tc )); +} + +static void GLAPIENTRY TAG(TexCoord2f)( GLfloat s, GLfloat t ) +{ + PRE_LOOPBACK( TexCoord2f ); + CALL_TexCoord2f(GET_DISPATCH(), ( s, t )); +} + +static void GLAPIENTRY TAG(TexCoord2fv)( const GLfloat *tc ) +{ + PRE_LOOPBACK( TexCoord2fv ); + CALL_TexCoord2fv(GET_DISPATCH(), ( tc )); +} + +static void GLAPIENTRY TAG(TexCoord3f)( GLfloat s, GLfloat t, GLfloat r ) +{ + PRE_LOOPBACK( TexCoord3f ); + CALL_TexCoord3f(GET_DISPATCH(), ( s, t, r )); +} + +static void GLAPIENTRY TAG(TexCoord3fv)( const GLfloat *tc ) +{ + PRE_LOOPBACK( TexCoord3fv ); + CALL_TexCoord3fv(GET_DISPATCH(), ( tc )); +} + +static void GLAPIENTRY TAG(TexCoord4f)( GLfloat s, GLfloat t, GLfloat r, GLfloat q ) +{ + PRE_LOOPBACK( TexCoord4f ); + CALL_TexCoord4f(GET_DISPATCH(), ( s, t, r, q )); +} + +static void GLAPIENTRY TAG(TexCoord4fv)( const GLfloat *tc ) +{ + PRE_LOOPBACK( TexCoord4fv ); + CALL_TexCoord4fv(GET_DISPATCH(), ( tc )); +} + +static void GLAPIENTRY TAG(Vertex2f)( GLfloat x, GLfloat y ) +{ + PRE_LOOPBACK( Vertex2f ); + CALL_Vertex2f(GET_DISPATCH(), ( x, y )); +} + +static void GLAPIENTRY TAG(Vertex2fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Vertex2fv ); + CALL_Vertex2fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(Vertex3f)( GLfloat x, GLfloat y, GLfloat z ) +{ + PRE_LOOPBACK( Vertex3f ); + CALL_Vertex3f(GET_DISPATCH(), ( x, y, z )); +} + +static void GLAPIENTRY TAG(Vertex3fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Vertex3fv ); + CALL_Vertex3fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(Vertex4f)( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + PRE_LOOPBACK( Vertex4f ); + CALL_Vertex4f(GET_DISPATCH(), ( x, y, z, w )); +} + +static void GLAPIENTRY TAG(Vertex4fv)( const GLfloat *v ) +{ + PRE_LOOPBACK( Vertex4fv ); + CALL_Vertex4fv(GET_DISPATCH(), ( v )); +} + +static void GLAPIENTRY TAG(CallList)( GLuint i ) +{ + PRE_LOOPBACK( CallList ); + CALL_CallList(GET_DISPATCH(), ( i )); +} + +static void GLAPIENTRY TAG(CallLists)( GLsizei sz, GLenum type, const GLvoid *v ) +{ + PRE_LOOPBACK( CallLists ); + CALL_CallLists(GET_DISPATCH(), ( sz, type, v )); +} + +static void GLAPIENTRY TAG(Begin)( GLenum mode ) +{ + PRE_LOOPBACK( Begin ); + CALL_Begin(GET_DISPATCH(), ( mode )); +} + +static void GLAPIENTRY TAG(End)( void ) +{ + PRE_LOOPBACK( End ); + CALL_End(GET_DISPATCH(), ()); +} + +static void GLAPIENTRY TAG(Rectf)( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + PRE_LOOPBACK( Rectf ); + CALL_Rectf(GET_DISPATCH(), ( x1, y1, x2, y2 )); +} + +static void GLAPIENTRY TAG(DrawArrays)( GLenum mode, GLint start, GLsizei count ) +{ + PRE_LOOPBACK( DrawArrays ); + CALL_DrawArrays(GET_DISPATCH(), ( mode, start, count )); +} + +static void GLAPIENTRY TAG(DrawElements)( GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices ) +{ + PRE_LOOPBACK( DrawElements ); + CALL_DrawElements(GET_DISPATCH(), ( mode, count, type, indices )); +} + +static void GLAPIENTRY TAG(DrawRangeElements)( GLenum mode, GLuint start, + GLuint end, GLsizei count, + GLenum type, const GLvoid *indices ) +{ + PRE_LOOPBACK( DrawRangeElements ); + CALL_DrawRangeElements(GET_DISPATCH(), ( mode, start, end, count, type, indices )); +} + +static void GLAPIENTRY TAG(EvalMesh1)( GLenum mode, GLint i1, GLint i2 ) +{ + PRE_LOOPBACK( EvalMesh1 ); + CALL_EvalMesh1(GET_DISPATCH(), ( mode, i1, i2 )); +} + +static void GLAPIENTRY TAG(EvalMesh2)( GLenum mode, GLint i1, GLint i2, + GLint j1, GLint j2 ) +{ + PRE_LOOPBACK( EvalMesh2 ); + CALL_EvalMesh2(GET_DISPATCH(), ( mode, i1, i2, j1, j2 )); +} + +static void GLAPIENTRY TAG(VertexAttrib1fNV)( GLuint index, GLfloat x ) +{ + PRE_LOOPBACK( VertexAttrib1fNV ); + CALL_VertexAttrib1fNV(GET_DISPATCH(), ( index, x )); +} + +static void GLAPIENTRY TAG(VertexAttrib1fvNV)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib1fvNV ); + CALL_VertexAttrib1fvNV(GET_DISPATCH(), ( index, v )); +} + +static void GLAPIENTRY TAG(VertexAttrib2fNV)( GLuint index, GLfloat x, GLfloat y ) +{ + PRE_LOOPBACK( VertexAttrib2fNV ); + CALL_VertexAttrib2fNV(GET_DISPATCH(), ( index, x, y )); +} + +static void GLAPIENTRY TAG(VertexAttrib2fvNV)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib2fvNV ); + CALL_VertexAttrib2fvNV(GET_DISPATCH(), ( index, v )); +} + +static void GLAPIENTRY TAG(VertexAttrib3fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z ) +{ + PRE_LOOPBACK( VertexAttrib3fNV ); + CALL_VertexAttrib3fNV(GET_DISPATCH(), ( index, x, y, z )); +} + +static void GLAPIENTRY TAG(VertexAttrib3fvNV)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib3fvNV ); + CALL_VertexAttrib3fvNV(GET_DISPATCH(), ( index, v )); +} + +static void GLAPIENTRY TAG(VertexAttrib4fNV)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + PRE_LOOPBACK( VertexAttrib4fNV ); + CALL_VertexAttrib4fNV(GET_DISPATCH(), ( index, x, y, z, w )); +} + +static void GLAPIENTRY TAG(VertexAttrib4fvNV)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib4fvNV ); + CALL_VertexAttrib4fvNV(GET_DISPATCH(), ( index, v )); +} + + +static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x ) +{ + PRE_LOOPBACK( VertexAttrib1fARB ); + CALL_VertexAttrib1fARB(GET_DISPATCH(), ( index, x )); +} + +static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib1fvARB ); + CALL_VertexAttrib1fvARB(GET_DISPATCH(), ( index, v )); +} + +static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x, GLfloat y ) +{ + PRE_LOOPBACK( VertexAttrib2fARB ); + CALL_VertexAttrib2fARB(GET_DISPATCH(), ( index, x, y )); +} + +static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib2fvARB ); + CALL_VertexAttrib2fvARB(GET_DISPATCH(), ( index, v )); +} + +static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z ) +{ + PRE_LOOPBACK( VertexAttrib3fARB ); + CALL_VertexAttrib3fARB(GET_DISPATCH(), ( index, x, y, z )); +} + +static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib3fvARB ); + CALL_VertexAttrib3fvARB(GET_DISPATCH(), ( index, v )); +} + +static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + PRE_LOOPBACK( VertexAttrib4fARB ); + CALL_VertexAttrib4fARB(GET_DISPATCH(), ( index, x, y, z, w )); +} + +static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index, const GLfloat *v ) +{ + PRE_LOOPBACK( VertexAttrib4fvARB ); + CALL_VertexAttrib4fvARB(GET_DISPATCH(), ( index, v )); +} + + +static GLvertexformat TAG(vtxfmt) = { + TAG(ArrayElement), + TAG(Color3f), + TAG(Color3fv), + TAG(Color4f), + TAG(Color4fv), + TAG(EdgeFlag), + TAG(EdgeFlagv), + TAG(EvalCoord1f), + TAG(EvalCoord1fv), + TAG(EvalCoord2f), + TAG(EvalCoord2fv), + TAG(EvalPoint1), + TAG(EvalPoint2), + TAG(FogCoordfEXT), + TAG(FogCoordfvEXT), + TAG(Indexf), + TAG(Indexfv), + TAG(Materialfv), + TAG(MultiTexCoord1fARB), + TAG(MultiTexCoord1fvARB), + TAG(MultiTexCoord2fARB), + TAG(MultiTexCoord2fvARB), + TAG(MultiTexCoord3fARB), + TAG(MultiTexCoord3fvARB), + TAG(MultiTexCoord4fARB), + TAG(MultiTexCoord4fvARB), + TAG(Normal3f), + TAG(Normal3fv), + TAG(SecondaryColor3fEXT), + TAG(SecondaryColor3fvEXT), + TAG(TexCoord1f), + TAG(TexCoord1fv), + TAG(TexCoord2f), + TAG(TexCoord2fv), + TAG(TexCoord3f), + TAG(TexCoord3fv), + TAG(TexCoord4f), + TAG(TexCoord4fv), + TAG(Vertex2f), + TAG(Vertex2fv), + TAG(Vertex3f), + TAG(Vertex3fv), + TAG(Vertex4f), + TAG(Vertex4fv), + TAG(CallList), + TAG(CallLists), + TAG(Begin), + TAG(End), + TAG(VertexAttrib1fNV), + TAG(VertexAttrib1fvNV), + TAG(VertexAttrib2fNV), + TAG(VertexAttrib2fvNV), + TAG(VertexAttrib3fNV), + TAG(VertexAttrib3fvNV), + TAG(VertexAttrib4fNV), + TAG(VertexAttrib4fvNV), + TAG(VertexAttrib1fARB), + TAG(VertexAttrib1fvARB), + TAG(VertexAttrib2fARB), + TAG(VertexAttrib2fvARB), + TAG(VertexAttrib3fARB), + TAG(VertexAttrib3fvARB), + TAG(VertexAttrib4fARB), + TAG(VertexAttrib4fvARB), + TAG(Rectf), + TAG(DrawArrays), + TAG(DrawElements), + TAG(DrawRangeElements), + TAG(EvalMesh1), + TAG(EvalMesh2) +}; + +#undef TAG +#undef PRE_LOOPBACK |