1721 lines
48 KiB
C
1721 lines
48 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: array.c
|
|
*
|
|
* OpenGL client side vertex array functions.
|
|
*
|
|
* Created: 1-30-1996
|
|
* Author: Hock San Lee [hockl]
|
|
*
|
|
* Copyright (c) 1996 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "os.h"
|
|
#include "glsbcltu.h"
|
|
#include "glclt.h"
|
|
#include "compsize.h"
|
|
#include "glsize.h"
|
|
#include "context.h"
|
|
#include "global.h"
|
|
#include "lcfuncs.h"
|
|
|
|
void FASTCALL VA_ArrayElement(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_V2F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_C3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_N3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_C3F_N3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_C4F_N3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_T2F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_T2F_C3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_T2F_N3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_T2F_C3F_N3F_V3F(__GLcontext *gc, GLint i);
|
|
void FASTCALL VA_ArrayElement_T2F_C4F_N3F_V3F(__GLcontext *gc, GLint i);
|
|
|
|
#define VAMASK_FORMAT_C3F \
|
|
(VAMASK_COLOR_ENABLE_MASK | VAMASK_COLOR_SIZE_3 | VAMASK_COLOR_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_C4F \
|
|
(VAMASK_COLOR_ENABLE_MASK | VAMASK_COLOR_SIZE_4 | VAMASK_COLOR_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_C4UB \
|
|
(VAMASK_COLOR_ENABLE_MASK | VAMASK_COLOR_SIZE_4 | VAMASK_COLOR_TYPE_UBYTE)
|
|
#define VAMASK_FORMAT_N3F \
|
|
(VAMASK_NORMAL_ENABLE_MASK | VAMASK_NORMAL_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_T2F \
|
|
(VAMASK_TEXCOORD_ENABLE_MASK | VAMASK_TEXCOORD_SIZE_2 | VAMASK_TEXCOORD_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_T4F \
|
|
(VAMASK_TEXCOORD_ENABLE_MASK | VAMASK_TEXCOORD_SIZE_4 | VAMASK_TEXCOORD_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_V2F \
|
|
(VAMASK_VERTEX_ENABLE_MASK | VAMASK_VERTEX_SIZE_2 | VAMASK_VERTEX_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_V3F \
|
|
(VAMASK_VERTEX_ENABLE_MASK | VAMASK_VERTEX_SIZE_3 | VAMASK_VERTEX_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_V4F \
|
|
(VAMASK_VERTEX_ENABLE_MASK | VAMASK_VERTEX_SIZE_4 | VAMASK_VERTEX_TYPE_FLOAT)
|
|
#define VAMASK_FORMAT_C3F_V3F \
|
|
(VAMASK_FORMAT_C3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_N3F_V3F \
|
|
(VAMASK_FORMAT_N3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_C3F_N3F_V3F \
|
|
(VAMASK_FORMAT_C3F | VAMASK_FORMAT_N3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_C4F_N3F_V3F \
|
|
(VAMASK_FORMAT_C4F | VAMASK_FORMAT_N3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T2F_V3F \
|
|
(VAMASK_FORMAT_T2F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T2F_C3F_V3F \
|
|
(VAMASK_FORMAT_T2F | VAMASK_FORMAT_C3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T2F_N3F_V3F \
|
|
(VAMASK_FORMAT_T2F | VAMASK_FORMAT_N3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T2F_C3F_N3F_V3F \
|
|
(VAMASK_FORMAT_T2F | VAMASK_FORMAT_C3F | VAMASK_FORMAT_N3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T2F_C4F_N3F_V3F \
|
|
(VAMASK_FORMAT_T2F | VAMASK_FORMAT_C4F | VAMASK_FORMAT_N3F | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_C4UB_V2F \
|
|
(VAMASK_FORMAT_C4UB | VAMASK_FORMAT_V2F)
|
|
#define VAMASK_FORMAT_C4UB_V3F \
|
|
(VAMASK_FORMAT_C4UB | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T4F_V4F \
|
|
(VAMASK_FORMAT_T4F | VAMASK_FORMAT_V4F)
|
|
#define VAMASK_FORMAT_T2F_C4UB_V3F \
|
|
(VAMASK_FORMAT_T2F | VAMASK_FORMAT_C4UB | VAMASK_FORMAT_V3F)
|
|
#define VAMASK_FORMAT_T4F_C4F_N3F_V4F \
|
|
(VAMASK_FORMAT_T4F | VAMASK_FORMAT_C4F | VAMASK_FORMAT_N3F | VAMASK_FORMAT_V4F)
|
|
|
|
// TYPE_ASSERT
|
|
GLint __glTypeSize[] =
|
|
{
|
|
sizeof(GLbyte), // GL_BYTE
|
|
sizeof(GLubyte), // GL_UNSIGNED_BYTE
|
|
sizeof(GLshort), // GL_SHORT
|
|
sizeof(GLushort), // GL_UNSIGNED_SHORT
|
|
sizeof(GLint), // GL_INT
|
|
sizeof(GLuint), // GL_UNSIGNED_INT
|
|
sizeof(GLfloat), // GL_FLOAT
|
|
2, // GL_2_BYTES
|
|
3, // GL_3_BYTES
|
|
4, // GL_4_BYTES
|
|
sizeof(GLdouble) // GL_DOUBLE
|
|
};
|
|
|
|
// ARRAY_TYPE_ASSERT
|
|
GLuint vaEnable[] =
|
|
{
|
|
VAMASK_VERTEX_ENABLE_MASK, // GL_VERTEX_ARRAY
|
|
VAMASK_NORMAL_ENABLE_MASK, // GL_NORMAL_ARRAY
|
|
VAMASK_COLOR_ENABLE_MASK, // GL_COLOR_ARRAY
|
|
VAMASK_INDEX_ENABLE_MASK, // GL_INDEX_ARRAY
|
|
VAMASK_TEXCOORD_ENABLE_MASK, // GL_TEXTURE_COORD_ARRAY
|
|
VAMASK_EDGEFLAG_ENABLE_MASK // GL_EDGE_FLAG_ARRAY
|
|
};
|
|
|
|
PFNGLVECTOR afnTexCoord[] =
|
|
{
|
|
(PFNGLVECTOR)glcltTexCoord1sv,
|
|
(PFNGLVECTOR)glcltTexCoord1iv,
|
|
(PFNGLVECTOR)glcltTexCoord1fv,
|
|
(PFNGLVECTOR)glcltTexCoord1dv,
|
|
|
|
(PFNGLVECTOR)glcltTexCoord2sv,
|
|
(PFNGLVECTOR)glcltTexCoord2iv,
|
|
(PFNGLVECTOR)glcltTexCoord2fv,
|
|
(PFNGLVECTOR)glcltTexCoord2dv,
|
|
|
|
(PFNGLVECTOR)glcltTexCoord3sv,
|
|
(PFNGLVECTOR)glcltTexCoord3iv,
|
|
(PFNGLVECTOR)glcltTexCoord3fv,
|
|
(PFNGLVECTOR)glcltTexCoord3dv,
|
|
|
|
(PFNGLVECTOR)glcltTexCoord4sv,
|
|
(PFNGLVECTOR)glcltTexCoord4iv,
|
|
(PFNGLVECTOR)glcltTexCoord4fv,
|
|
(PFNGLVECTOR)glcltTexCoord4dv,
|
|
};
|
|
|
|
PFNGLVECTOR afnTexCoordCompile[] =
|
|
{
|
|
(PFNGLVECTOR)__gllc_TexCoord1sv,
|
|
(PFNGLVECTOR)__gllc_TexCoord1iv,
|
|
(PFNGLVECTOR)__gllc_TexCoord1fv,
|
|
(PFNGLVECTOR)__gllc_TexCoord1dv,
|
|
|
|
(PFNGLVECTOR)__gllc_TexCoord2sv,
|
|
(PFNGLVECTOR)__gllc_TexCoord2iv,
|
|
(PFNGLVECTOR)__gllc_TexCoord2fv,
|
|
(PFNGLVECTOR)__gllc_TexCoord2dv,
|
|
|
|
(PFNGLVECTOR)__gllc_TexCoord3sv,
|
|
(PFNGLVECTOR)__gllc_TexCoord3iv,
|
|
(PFNGLVECTOR)__gllc_TexCoord3fv,
|
|
(PFNGLVECTOR)__gllc_TexCoord3dv,
|
|
|
|
(PFNGLVECTOR)__gllc_TexCoord4sv,
|
|
(PFNGLVECTOR)__gllc_TexCoord4iv,
|
|
(PFNGLVECTOR)__gllc_TexCoord4fv,
|
|
(PFNGLVECTOR)__gllc_TexCoord4dv,
|
|
};
|
|
|
|
PFNGLVECTOR afnColor_InRGBA[] =
|
|
{
|
|
(PFNGLVECTOR)glcltColor3bv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3ubv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3sv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3usv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3iv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3uiv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3fv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor3dv_InRGBA,
|
|
|
|
(PFNGLVECTOR)glcltColor4bv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4ubv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4sv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4usv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4iv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4uiv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4fv_InRGBA,
|
|
(PFNGLVECTOR)glcltColor4dv_InRGBA,
|
|
};
|
|
|
|
PFNGLVECTOR afnColor_InCI[] =
|
|
{
|
|
(PFNGLVECTOR)glcltColor3bv_InCI,
|
|
(PFNGLVECTOR)glcltColor3ubv_InCI,
|
|
(PFNGLVECTOR)glcltColor3sv_InCI,
|
|
(PFNGLVECTOR)glcltColor3usv_InCI,
|
|
(PFNGLVECTOR)glcltColor3iv_InCI,
|
|
(PFNGLVECTOR)glcltColor3uiv_InCI,
|
|
(PFNGLVECTOR)glcltColor3fv_InCI,
|
|
(PFNGLVECTOR)glcltColor3dv_InCI,
|
|
|
|
(PFNGLVECTOR)glcltColor4bv_InCI,
|
|
(PFNGLVECTOR)glcltColor4ubv_InCI,
|
|
(PFNGLVECTOR)glcltColor4sv_InCI,
|
|
(PFNGLVECTOR)glcltColor4usv_InCI,
|
|
(PFNGLVECTOR)glcltColor4iv_InCI,
|
|
(PFNGLVECTOR)glcltColor4uiv_InCI,
|
|
(PFNGLVECTOR)glcltColor4fv_InCI,
|
|
(PFNGLVECTOR)glcltColor4dv_InCI,
|
|
};
|
|
|
|
PFNGLVECTOR afnColorCompile[] =
|
|
{
|
|
(PFNGLVECTOR)__gllc_Color3bv,
|
|
(PFNGLVECTOR)__gllc_Color3ubv,
|
|
(PFNGLVECTOR)__gllc_Color3sv,
|
|
(PFNGLVECTOR)__gllc_Color3usv,
|
|
(PFNGLVECTOR)__gllc_Color3iv,
|
|
(PFNGLVECTOR)__gllc_Color3uiv,
|
|
(PFNGLVECTOR)__gllc_Color3fv,
|
|
(PFNGLVECTOR)__gllc_Color3dv,
|
|
|
|
(PFNGLVECTOR)__gllc_Color4bv,
|
|
(PFNGLVECTOR)__gllc_Color4ubv,
|
|
(PFNGLVECTOR)__gllc_Color4sv,
|
|
(PFNGLVECTOR)__gllc_Color4usv,
|
|
(PFNGLVECTOR)__gllc_Color4iv,
|
|
(PFNGLVECTOR)__gllc_Color4uiv,
|
|
(PFNGLVECTOR)__gllc_Color4fv,
|
|
(PFNGLVECTOR)__gllc_Color4dv,
|
|
};
|
|
|
|
PFNGLVECTOR afnIndex_InRGBA[] =
|
|
{
|
|
(PFNGLVECTOR)glcltIndexubv_InRGBA,
|
|
(PFNGLVECTOR)glcltIndexsv_InRGBA,
|
|
(PFNGLVECTOR)glcltIndexiv_InRGBA,
|
|
(PFNGLVECTOR)glcltIndexfv_InRGBA,
|
|
(PFNGLVECTOR)glcltIndexdv_InRGBA,
|
|
};
|
|
|
|
PFNGLVECTOR afnIndex_InCI[] =
|
|
{
|
|
(PFNGLVECTOR)glcltIndexubv_InCI,
|
|
(PFNGLVECTOR)glcltIndexsv_InCI,
|
|
(PFNGLVECTOR)glcltIndexiv_InCI,
|
|
(PFNGLVECTOR)glcltIndexfv_InCI,
|
|
(PFNGLVECTOR)glcltIndexdv_InCI,
|
|
};
|
|
|
|
PFNGLVECTOR afnIndexCompile[] =
|
|
{
|
|
(PFNGLVECTOR)__gllc_Indexubv,
|
|
(PFNGLVECTOR)__gllc_Indexsv,
|
|
(PFNGLVECTOR)__gllc_Indexiv,
|
|
(PFNGLVECTOR)__gllc_Indexfv,
|
|
(PFNGLVECTOR)__gllc_Indexdv,
|
|
};
|
|
|
|
PFNGLVECTOR afnNormal[] =
|
|
{
|
|
(PFNGLVECTOR)glcltNormal3bv,
|
|
(PFNGLVECTOR)glcltNormal3sv,
|
|
(PFNGLVECTOR)glcltNormal3iv,
|
|
(PFNGLVECTOR)glcltNormal3fv,
|
|
(PFNGLVECTOR)glcltNormal3dv,
|
|
};
|
|
|
|
PFNGLVECTOR afnNormalCompile[] =
|
|
{
|
|
(PFNGLVECTOR)__gllc_Normal3bv,
|
|
(PFNGLVECTOR)__gllc_Normal3sv,
|
|
(PFNGLVECTOR)__gllc_Normal3iv,
|
|
(PFNGLVECTOR)__gllc_Normal3fv,
|
|
(PFNGLVECTOR)__gllc_Normal3dv,
|
|
};
|
|
|
|
PFNGLVECTOR afnVertex[] =
|
|
{
|
|
(PFNGLVECTOR)glcltVertex2sv,
|
|
(PFNGLVECTOR)glcltVertex2iv,
|
|
(PFNGLVECTOR)glcltVertex2fv,
|
|
(PFNGLVECTOR)glcltVertex2dv,
|
|
|
|
(PFNGLVECTOR)glcltVertex3sv,
|
|
(PFNGLVECTOR)glcltVertex3iv,
|
|
(PFNGLVECTOR)glcltVertex3fv,
|
|
(PFNGLVECTOR)glcltVertex3dv,
|
|
|
|
(PFNGLVECTOR)glcltVertex4sv,
|
|
(PFNGLVECTOR)glcltVertex4iv,
|
|
(PFNGLVECTOR)glcltVertex4fv,
|
|
(PFNGLVECTOR)glcltVertex4dv,
|
|
};
|
|
|
|
PFNGLVECTOR afnVertexCompile[] =
|
|
{
|
|
(PFNGLVECTOR)__gllc_Vertex2sv,
|
|
(PFNGLVECTOR)__gllc_Vertex2iv,
|
|
(PFNGLVECTOR)__gllc_Vertex2fv,
|
|
(PFNGLVECTOR)__gllc_Vertex2dv,
|
|
|
|
(PFNGLVECTOR)__gllc_Vertex3sv,
|
|
(PFNGLVECTOR)__gllc_Vertex3iv,
|
|
(PFNGLVECTOR)__gllc_Vertex3fv,
|
|
(PFNGLVECTOR)__gllc_Vertex3dv,
|
|
|
|
(PFNGLVECTOR)__gllc_Vertex4sv,
|
|
(PFNGLVECTOR)__gllc_Vertex4iv,
|
|
(PFNGLVECTOR)__gllc_Vertex4fv,
|
|
(PFNGLVECTOR)__gllc_Vertex4dv,
|
|
};
|
|
|
|
void FASTCALL __glInitVertexArray(__GLcontext *gc)
|
|
{
|
|
// Initial vertex array state.
|
|
static __GLvertexArray defaultVertexArrayState =
|
|
{
|
|
__GL_VERTEX_ARRAY_DIRTY, // flags
|
|
|
|
VAMASK_TEXCOORD_SIZE_4 | // mask
|
|
VAMASK_TEXCOORD_TYPE_FLOAT |
|
|
VAMASK_INDEX_TYPE_FLOAT |
|
|
VAMASK_COLOR_SIZE_4 |
|
|
VAMASK_COLOR_TYPE_FLOAT |
|
|
VAMASK_NORMAL_TYPE_FLOAT |
|
|
VAMASK_VERTEX_SIZE_4 |
|
|
VAMASK_VERTEX_TYPE_FLOAT,
|
|
|
|
VA_ArrayElement, // pfnArrayElement
|
|
|
|
{ // edgeFlag
|
|
sizeof(GLboolean), // ibytes
|
|
0, // stride
|
|
NULL, // pointer
|
|
glcltEdgeFlagv, // pfn
|
|
__gllc_EdgeFlagv, // pfnCompile
|
|
},
|
|
|
|
{ // texcoord
|
|
4, // size
|
|
GL_FLOAT, // type
|
|
4 * sizeof(GLfloat), // ibytes
|
|
0, // stride
|
|
NULL, // pointer
|
|
NULL, // pfn
|
|
NULL, // pfnCompile
|
|
},
|
|
|
|
{ // index
|
|
GL_FLOAT, // type
|
|
sizeof(GLfloat), // ibytes
|
|
0, // stride
|
|
NULL, // pointer
|
|
NULL, // pfn
|
|
NULL, // pfnCompile
|
|
},
|
|
|
|
{ // color
|
|
4, // size
|
|
GL_FLOAT, // type
|
|
4 * sizeof(GLfloat), // ibytes
|
|
0, // stride
|
|
NULL, // pointer
|
|
NULL, // pfn
|
|
NULL, // pfnCompile
|
|
},
|
|
|
|
{ // normal
|
|
GL_FLOAT, // type
|
|
3 * sizeof(GLfloat), // ibytes
|
|
0, // stride
|
|
NULL, // pointer
|
|
NULL, // pfn
|
|
NULL, // pfnCompile
|
|
},
|
|
|
|
{ // vertex
|
|
4, // size
|
|
GL_FLOAT, // type
|
|
4 * sizeof(GLfloat), // ibytes
|
|
0, // stride
|
|
NULL, // pointer
|
|
NULL, // pfn
|
|
NULL, // pfnCompile
|
|
},
|
|
};
|
|
|
|
gc->vertexArray = defaultVertexArrayState;
|
|
}
|
|
|
|
void APIENTRY glcltEdgeFlagPointer (GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
gc->vertexArray.edgeFlag.ibytes = stride;
|
|
else
|
|
gc->vertexArray.edgeFlag.ibytes = sizeof(GLboolean);
|
|
|
|
gc->vertexArray.edgeFlag.stride = stride;
|
|
gc->vertexArray.edgeFlag.pointer = pointer;
|
|
}
|
|
|
|
void APIENTRY glcltTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
GLuint vaMask;
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case GL_SHORT:
|
|
vaMask = VAMASK_TEXCOORD_TYPE_SHORT;
|
|
break;
|
|
case GL_INT:
|
|
vaMask = VAMASK_TEXCOORD_TYPE_INT;
|
|
break;
|
|
case GL_FLOAT:
|
|
vaMask = VAMASK_TEXCOORD_TYPE_FLOAT;
|
|
break;
|
|
case GL_DOUBLE:
|
|
vaMask = VAMASK_TEXCOORD_TYPE_DOUBLE;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
switch (size)
|
|
{
|
|
case 1:
|
|
vaMask |= VAMASK_TEXCOORD_SIZE_1;
|
|
break;
|
|
case 2:
|
|
vaMask |= VAMASK_TEXCOORD_SIZE_2;
|
|
break;
|
|
case 3:
|
|
vaMask |= VAMASK_TEXCOORD_SIZE_3;
|
|
break;
|
|
case 4:
|
|
vaMask |= VAMASK_TEXCOORD_SIZE_4;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
gc->vertexArray.texCoord.ibytes = stride;
|
|
else
|
|
gc->vertexArray.texCoord.ibytes = size * __GLTYPESIZE(type);
|
|
|
|
gc->vertexArray.texCoord.size = size;
|
|
gc->vertexArray.texCoord.type = type;
|
|
gc->vertexArray.texCoord.stride = stride;
|
|
gc->vertexArray.texCoord.pointer = pointer;
|
|
if ((gc->vertexArray.mask & VAMASK_TEXCOORD_TYPE_SIZE_MASK) != vaMask)
|
|
{
|
|
gc->vertexArray.mask &= ~VAMASK_TEXCOORD_TYPE_SIZE_MASK;
|
|
gc->vertexArray.mask |= vaMask;
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
GLuint vaMask;
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case GL_BYTE:
|
|
vaMask = VAMASK_COLOR_TYPE_BYTE;
|
|
break;
|
|
case GL_UNSIGNED_BYTE:
|
|
vaMask = VAMASK_COLOR_TYPE_UBYTE;
|
|
break;
|
|
case GL_SHORT:
|
|
vaMask = VAMASK_COLOR_TYPE_SHORT;
|
|
break;
|
|
case GL_UNSIGNED_SHORT:
|
|
vaMask = VAMASK_COLOR_TYPE_USHORT;
|
|
break;
|
|
case GL_INT:
|
|
vaMask = VAMASK_COLOR_TYPE_INT;
|
|
break;
|
|
case GL_UNSIGNED_INT:
|
|
vaMask = VAMASK_COLOR_TYPE_UINT;
|
|
break;
|
|
case GL_FLOAT:
|
|
vaMask = VAMASK_COLOR_TYPE_FLOAT;
|
|
break;
|
|
case GL_DOUBLE:
|
|
vaMask = VAMASK_COLOR_TYPE_DOUBLE;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
switch (size)
|
|
{
|
|
case 3:
|
|
vaMask |= VAMASK_COLOR_SIZE_3;
|
|
break;
|
|
case 4:
|
|
vaMask |= VAMASK_COLOR_SIZE_4;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
gc->vertexArray.color.ibytes = stride;
|
|
else
|
|
gc->vertexArray.color.ibytes = size * __GLTYPESIZE(type);
|
|
|
|
gc->vertexArray.color.size = size;
|
|
gc->vertexArray.color.type = type;
|
|
gc->vertexArray.color.stride = stride;
|
|
gc->vertexArray.color.pointer = pointer;
|
|
if ((gc->vertexArray.mask & VAMASK_COLOR_TYPE_SIZE_MASK) != vaMask)
|
|
{
|
|
gc->vertexArray.mask &= ~VAMASK_COLOR_TYPE_SIZE_MASK;
|
|
gc->vertexArray.mask |= vaMask;
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
GLuint vaMask;
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case GL_UNSIGNED_BYTE:
|
|
vaMask = VAMASK_INDEX_TYPE_UBYTE;
|
|
break;
|
|
case GL_SHORT:
|
|
vaMask = VAMASK_INDEX_TYPE_SHORT;
|
|
break;
|
|
case GL_INT:
|
|
vaMask = VAMASK_INDEX_TYPE_INT;
|
|
break;
|
|
case GL_FLOAT:
|
|
vaMask = VAMASK_INDEX_TYPE_FLOAT;
|
|
break;
|
|
case GL_DOUBLE:
|
|
vaMask = VAMASK_INDEX_TYPE_DOUBLE;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
gc->vertexArray.index.ibytes = stride;
|
|
else
|
|
gc->vertexArray.index.ibytes = __GLTYPESIZE(type);
|
|
|
|
gc->vertexArray.index.type = type;
|
|
gc->vertexArray.index.stride = stride;
|
|
gc->vertexArray.index.pointer = pointer;
|
|
// update index function pointer!
|
|
if ((gc->vertexArray.mask & VAMASK_INDEX_TYPE_SIZE_MASK) != vaMask)
|
|
{
|
|
gc->vertexArray.mask &= ~VAMASK_INDEX_TYPE_SIZE_MASK;
|
|
gc->vertexArray.mask |= vaMask;
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
GLuint vaMask;
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case GL_BYTE:
|
|
vaMask = VAMASK_NORMAL_TYPE_BYTE;
|
|
break;
|
|
case GL_SHORT:
|
|
vaMask = VAMASK_NORMAL_TYPE_SHORT;
|
|
break;
|
|
case GL_INT:
|
|
vaMask = VAMASK_NORMAL_TYPE_INT;
|
|
break;
|
|
case GL_FLOAT:
|
|
vaMask = VAMASK_NORMAL_TYPE_FLOAT;
|
|
break;
|
|
case GL_DOUBLE:
|
|
vaMask = VAMASK_NORMAL_TYPE_DOUBLE;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
gc->vertexArray.normal.ibytes = stride;
|
|
else
|
|
gc->vertexArray.normal.ibytes = 3 * __GLTYPESIZE(type);
|
|
|
|
gc->vertexArray.normal.type = type;
|
|
gc->vertexArray.normal.stride = stride;
|
|
gc->vertexArray.normal.pointer = pointer;
|
|
if ((gc->vertexArray.mask & VAMASK_NORMAL_TYPE_SIZE_MASK) != vaMask)
|
|
{
|
|
gc->vertexArray.mask &= ~VAMASK_NORMAL_TYPE_SIZE_MASK;
|
|
gc->vertexArray.mask |= vaMask;
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
GLuint vaMask;
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case GL_SHORT:
|
|
vaMask = VAMASK_VERTEX_TYPE_SHORT;
|
|
break;
|
|
case GL_INT:
|
|
vaMask = VAMASK_VERTEX_TYPE_INT;
|
|
break;
|
|
case GL_FLOAT:
|
|
vaMask = VAMASK_VERTEX_TYPE_FLOAT;
|
|
break;
|
|
case GL_DOUBLE:
|
|
vaMask = VAMASK_VERTEX_TYPE_DOUBLE;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
switch (size)
|
|
{
|
|
case 2:
|
|
vaMask |= VAMASK_VERTEX_SIZE_2;
|
|
break;
|
|
case 3:
|
|
vaMask |= VAMASK_VERTEX_SIZE_3;
|
|
break;
|
|
case 4:
|
|
vaMask |= VAMASK_VERTEX_SIZE_4;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
gc->vertexArray.vertex.ibytes = stride;
|
|
else
|
|
gc->vertexArray.vertex.ibytes = size * __GLTYPESIZE(type);
|
|
|
|
gc->vertexArray.vertex.size = size;
|
|
gc->vertexArray.vertex.type = type;
|
|
gc->vertexArray.vertex.stride = stride;
|
|
gc->vertexArray.vertex.pointer = pointer;
|
|
if ((gc->vertexArray.mask & VAMASK_VERTEX_TYPE_SIZE_MASK) != vaMask)
|
|
{
|
|
gc->vertexArray.mask &= ~VAMASK_VERTEX_TYPE_SIZE_MASK;
|
|
gc->vertexArray.mask |= vaMask;
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltEnableClientState (GLenum cap)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
// ARRAY_TYPE_ASSERT
|
|
if (RANGE(cap,GL_VERTEX_ARRAY,GL_EDGE_FLAG_ARRAY))
|
|
{
|
|
if (!(gc->vertexArray.mask & vaEnable[cap - GL_VERTEX_ARRAY]))
|
|
{
|
|
gc->vertexArray.mask |= vaEnable[cap - GL_VERTEX_ARRAY];
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltDisableClientState (GLenum cap)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
// ARRAY_TYPE_ASSERT
|
|
if (RANGE(cap,GL_VERTEX_ARRAY,GL_EDGE_FLAG_ARRAY))
|
|
{
|
|
if (gc->vertexArray.mask & vaEnable[cap - GL_VERTEX_ARRAY])
|
|
{
|
|
gc->vertexArray.mask &= ~vaEnable[cap - GL_VERTEX_ARRAY];
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltGetPointerv (GLenum pname, GLvoid* *params)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
switch (pname)
|
|
{
|
|
case GL_VERTEX_ARRAY_POINTER:
|
|
*params = (GLvoid *) gc->vertexArray.vertex.pointer;
|
|
break;
|
|
case GL_NORMAL_ARRAY_POINTER:
|
|
*params = (GLvoid *) gc->vertexArray.normal.pointer;
|
|
break;
|
|
case GL_COLOR_ARRAY_POINTER:
|
|
*params = (GLvoid *) gc->vertexArray.color.pointer;
|
|
break;
|
|
case GL_INDEX_ARRAY_POINTER:
|
|
*params = (GLvoid *) gc->vertexArray.index.pointer;
|
|
break;
|
|
case GL_TEXTURE_COORD_ARRAY_POINTER:
|
|
*params = (GLvoid *) gc->vertexArray.texCoord.pointer;
|
|
break;
|
|
case GL_EDGE_FLAG_ARRAY_POINTER:
|
|
*params = (GLvoid *) gc->vertexArray.edgeFlag.pointer;
|
|
break;
|
|
case GL_SELECTION_BUFFER_POINTER:
|
|
// The client pointer is maintained current at all times.
|
|
*params = (GLvoid *) gc->select.resultBase;
|
|
break;
|
|
case GL_FEEDBACK_BUFFER_POINTER:
|
|
// The client pointer is maintained current at all times.
|
|
*params = (GLvoid *) gc->feedback.resultBase;
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// We have special cases for the following formats. They also match the
|
|
// special cases in display list.
|
|
//
|
|
// V2F
|
|
// V3F
|
|
// C3F_V3F
|
|
// N3F_V3F
|
|
// C3F_N3F_V3F (non 1.1 format)
|
|
// C4F_N3F_V3F
|
|
// T2F_V3F
|
|
// T2F_C3F_V3F
|
|
// T2F_N3F_V3F
|
|
// T2F_C3F_N3F_V3F (non 1.1 format)
|
|
// T2F_C4F_N3F_V3F
|
|
//
|
|
// There are no special cases for the following 1.1 formats:
|
|
//
|
|
// C4UB_V2F
|
|
// C4UB_V3F
|
|
// T4F_V4F
|
|
// T2F_C4UB_V3F
|
|
// T4F_C4F_N3F_V4F
|
|
|
|
void FASTCALL VA_ValidateArrayPointers(__GLcontext *gc)
|
|
{
|
|
GLuint vaMask;
|
|
GLuint formatMask;
|
|
PFNVAELEMENT fp;
|
|
|
|
fp = VA_ArrayElement;
|
|
vaMask = gc->vertexArray.mask;
|
|
|
|
// The fast routines are for RGBA mode only. Edge flag and index array
|
|
// pointers are disabled in these routines. Vertex array pointer is enabled.
|
|
|
|
if (!gc->modes.colorIndexMode &&
|
|
!(vaMask & (VAMASK_EDGEFLAG_ENABLE_MASK | VAMASK_INDEX_ENABLE_MASK)) &&
|
|
(vaMask & VAMASK_VERTEX_ENABLE_MASK))
|
|
{
|
|
formatMask = VAMASK_VERTEX_TYPE_SIZE_MASK | VAMASK_VERTEX_ENABLE_MASK;
|
|
if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
|
|
formatMask |= VAMASK_TEXCOORD_TYPE_SIZE_MASK | VAMASK_TEXCOORD_ENABLE_MASK;
|
|
if (vaMask & VAMASK_COLOR_ENABLE_MASK)
|
|
formatMask |= VAMASK_COLOR_TYPE_SIZE_MASK | VAMASK_COLOR_ENABLE_MASK;
|
|
if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
|
|
formatMask |= VAMASK_NORMAL_TYPE_SIZE_MASK | VAMASK_NORMAL_ENABLE_MASK;
|
|
|
|
switch (vaMask & formatMask)
|
|
{
|
|
case VAMASK_FORMAT_V2F:
|
|
fp = VA_ArrayElement_V2F;
|
|
break;
|
|
case VAMASK_FORMAT_V3F:
|
|
fp = VA_ArrayElement_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_C3F_V3F:
|
|
fp = VA_ArrayElement_C3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_N3F_V3F:
|
|
fp = VA_ArrayElement_N3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_C3F_N3F_V3F:
|
|
fp = VA_ArrayElement_C3F_N3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_C4F_N3F_V3F:
|
|
fp = VA_ArrayElement_C4F_N3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_T2F_V3F:
|
|
fp = VA_ArrayElement_T2F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_T2F_C3F_V3F:
|
|
fp = VA_ArrayElement_T2F_C3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_T2F_N3F_V3F:
|
|
fp = VA_ArrayElement_T2F_N3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_T2F_C3F_N3F_V3F:
|
|
fp = VA_ArrayElement_T2F_C3F_N3F_V3F;
|
|
break;
|
|
case VAMASK_FORMAT_T2F_C4F_N3F_V3F:
|
|
fp = VA_ArrayElement_T2F_C4F_N3F_V3F;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// The default function pointers are used outside Begin.
|
|
|
|
ASSERTOPENGL(gc->vertexArray.edgeFlag.pfn == (PFNGLVECTOR) glcltEdgeFlagv &&
|
|
gc->vertexArray.edgeFlag.pfnCompile == (PFNGLVECTOR) __gllc_EdgeFlagv,
|
|
"edgeFlag.pfn and edgeFlag.pfnCompile not initialized\n");
|
|
gc->vertexArray.texCoord.pfn
|
|
= afnTexCoord[(vaMask & VAMASK_TEXCOORD_TYPE_SIZE_MASK) >> VAMASK_TEXCOORD_TYPE_SHIFT];
|
|
gc->vertexArray.texCoord.pfnCompile
|
|
= afnTexCoordCompile[(vaMask & VAMASK_TEXCOORD_TYPE_SIZE_MASK) >> VAMASK_TEXCOORD_TYPE_SHIFT];
|
|
if (gc->modes.colorIndexMode)
|
|
{
|
|
gc->vertexArray.color.pfn
|
|
= afnColor_InCI[(vaMask & VAMASK_COLOR_TYPE_SIZE_MASK) >> VAMASK_COLOR_TYPE_SHIFT];
|
|
gc->vertexArray.index.pfn
|
|
= afnIndex_InCI[(vaMask & VAMASK_INDEX_TYPE_SIZE_MASK) >> VAMASK_INDEX_TYPE_SHIFT];
|
|
}
|
|
else
|
|
{
|
|
gc->vertexArray.color.pfn
|
|
= afnColor_InRGBA[(vaMask & VAMASK_COLOR_TYPE_SIZE_MASK) >> VAMASK_COLOR_TYPE_SHIFT];
|
|
gc->vertexArray.index.pfn
|
|
= afnIndex_InRGBA[(vaMask & VAMASK_INDEX_TYPE_SIZE_MASK) >> VAMASK_INDEX_TYPE_SHIFT];
|
|
}
|
|
gc->vertexArray.color.pfnCompile
|
|
= afnColorCompile[(vaMask & VAMASK_COLOR_TYPE_SIZE_MASK) >> VAMASK_COLOR_TYPE_SHIFT];
|
|
gc->vertexArray.index.pfnCompile
|
|
= afnIndexCompile[(vaMask & VAMASK_INDEX_TYPE_SIZE_MASK) >> VAMASK_INDEX_TYPE_SHIFT];
|
|
gc->vertexArray.normal.pfn
|
|
= afnNormal[(vaMask & VAMASK_NORMAL_TYPE_SIZE_MASK) >> VAMASK_NORMAL_TYPE_SHIFT];
|
|
gc->vertexArray.normal.pfnCompile
|
|
= afnNormalCompile[(vaMask & VAMASK_NORMAL_TYPE_SIZE_MASK) >> VAMASK_NORMAL_TYPE_SHIFT];
|
|
gc->vertexArray.vertex.pfn
|
|
= afnVertex[(vaMask & VAMASK_VERTEX_TYPE_SIZE_MASK) >> VAMASK_VERTEX_TYPE_SHIFT];
|
|
gc->vertexArray.vertex.pfnCompile
|
|
= afnVertexCompile[(vaMask & VAMASK_VERTEX_TYPE_SIZE_MASK) >> VAMASK_VERTEX_TYPE_SHIFT];
|
|
|
|
gc->vertexArray.pfnArrayElement = fp;
|
|
gc->vertexArray.flags &= ~__GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
|
|
void APIENTRY glcltArrayElement (GLint i)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY)
|
|
VA_ValidateArrayPointers(gc);
|
|
|
|
// The fast routines are called in Begin only.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
(*gc->vertexArray.pfnArrayElement)(gc, i);
|
|
else
|
|
VA_ArrayElement(gc, i);
|
|
}
|
|
|
|
// Define fast VA_ArrayElement functions.
|
|
|
|
#define __VA_ARRAY_ELEMENT_V2F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_V2F
|
|
|
|
#define __VA_ARRAY_ELEMENT_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_C3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_C3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_N3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_N3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_C3F_N3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_C3F_N3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_C4F_N3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_C4F_N3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_T2F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_T2F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_T2F_C3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_T2F_C3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_T2F_N3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_T2F_N3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_T2F_C3F_N3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_T2F_C3F_N3F_V3F
|
|
|
|
#define __VA_ARRAY_ELEMENT_T2F_C4F_N3F_V3F 1
|
|
#include "array.h"
|
|
#undef __VA_ARRAY_ELEMENT_T2F_C4F_N3F_V3F
|
|
|
|
#define CALLARRAYPOINTER(ap, i) \
|
|
((*(ap).pfn)((ap).pointer + (i) * (ap).ibytes))
|
|
|
|
void FASTCALL VA_ArrayElement(__GLcontext *gc, GLint i)
|
|
{
|
|
GLuint vaMask = gc->vertexArray.mask;
|
|
|
|
if (vaMask & VAMASK_EDGEFLAG_ENABLE_MASK)
|
|
CALLARRAYPOINTER(gc->vertexArray.edgeFlag, i);
|
|
if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
|
|
CALLARRAYPOINTER(gc->vertexArray.texCoord, i);
|
|
if (vaMask & VAMASK_COLOR_ENABLE_MASK)
|
|
CALLARRAYPOINTER(gc->vertexArray.color, i);
|
|
if (vaMask & VAMASK_INDEX_ENABLE_MASK)
|
|
CALLARRAYPOINTER(gc->vertexArray.index, i);
|
|
if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
|
|
CALLARRAYPOINTER(gc->vertexArray.normal, i);
|
|
if (vaMask & VAMASK_VERTEX_ENABLE_MASK)
|
|
CALLARRAYPOINTER(gc->vertexArray.vertex, i);
|
|
}
|
|
|
|
void APIENTRY glcltDrawArrays (GLenum mode, GLint first, GLsizei count)
|
|
{
|
|
int i;
|
|
POLYARRAY *pa;
|
|
PFNVAELEMENT pfn;
|
|
__GL_SETUP();
|
|
|
|
pa = gc->paTeb;
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (pa->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
if ((GLuint) mode > GL_POLYGON)
|
|
{
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (count < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
} else if (!count)
|
|
return;
|
|
|
|
// Find array element function to use.
|
|
|
|
if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY)
|
|
VA_ValidateArrayPointers(gc);
|
|
pfn = gc->vertexArray.pfnArrayElement;
|
|
|
|
// Check polyarray buffer size before calling Begin.
|
|
// We will minimize breaking poly data records into batches where possible.
|
|
// The number 8 is loosely chosen to allow for the poly array entry
|
|
// and the flush limit. At worst, it causes an unnecessary attention!
|
|
|
|
if (count <= (GLsizei) gc->vertex.pdBufSize - 8
|
|
&& count >= (GLsizei) (pa->pdBufferMax - pa->pdBufferNext + 1 - 8))
|
|
glsbAttention();
|
|
|
|
// Draw the array elements.
|
|
|
|
glcltBegin(mode);
|
|
pa->flags |= POLYARRAY_SAME_POLYDATA_TYPE;
|
|
|
|
for (i = 0; i < count; i++)
|
|
(*pfn)(gc, first + i);
|
|
|
|
glcltEnd();
|
|
}
|
|
|
|
// Do not modify these constants. The code will likely break if they are
|
|
// changed.
|
|
#define VA_HASH_SIZE 256
|
|
#define VA_HASH(indexIn) ((GLubyte) indexIn)
|
|
|
|
// If the size of the mapping array is greater than 256, we need to change
|
|
// datatype and code below.
|
|
#if (VA_DRAWELEM_MAP_SIZE > 256)
|
|
#error "VA_DRAWELEM_MAP_SIZE is too large"
|
|
#endif
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ReduceDrawElements
|
|
*
|
|
* Takes a set of DrawElements indices and reduces it into small chunks
|
|
* of unique vertex indices
|
|
*
|
|
* History:
|
|
* Sat Mar 02 14:25:26 1996 -by- Hock San Lee [hockl]
|
|
* Wrote original version embedded in DrawElements
|
|
* Sat Mar 02 14:25:26 1996 -by- Drew Bliss [drewb]
|
|
* Split into function shared between immediate and dlist
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void FASTCALL ReduceDrawElements(__GLcontext *gc,
|
|
GLenum mode, GLsizei count, GLenum type,
|
|
const GLvoid *pIn,
|
|
pfnReducedElementsHandler pfnHandler)
|
|
{
|
|
GLushort _aHash[VA_HASH_SIZE + 2];
|
|
GLushort *pHash;
|
|
VAMAP aMap[VA_DRAWELEM_MAP_SIZE];
|
|
GLushort iMap, iMapNext;
|
|
GLushort iOutNext;
|
|
GLubyte aOut[VA_DRAWELEM_INDEX_SIZE];
|
|
GLsizei iPartialIndices;
|
|
GLsizei iCount, nLeft;
|
|
GLuint iIn;
|
|
|
|
// We will now sort the input index array using a hash table. The output
|
|
// index array will be zero based. For example, if the input array is
|
|
// [103, 101, 0, 2, 105, 103, 2, 4], the output index will be
|
|
// [0, 1, 2, 3, 4, 0, 3, 5]. This allows us to store
|
|
// vertices in a consequtive order.
|
|
// Dword aligned hash array.
|
|
|
|
pHash = (GLushort *) (((unsigned int) _aHash + 3) & ~3);
|
|
|
|
// Initialize input index array pointer.
|
|
|
|
iCount = 0;
|
|
iPartialIndices = 0;
|
|
|
|
DrawElements_NextBatch:
|
|
|
|
// Reset output index array for this batch.
|
|
// Initialize identity mapping for the first reserved vertex entries.
|
|
// New vertices are accumulated after them.
|
|
|
|
for (iOutNext = 0; iOutNext < (GLushort) iPartialIndices; iOutNext++)
|
|
aOut[iOutNext] = (GLubyte) iOutNext;
|
|
|
|
// Reset index mapping array that maps the In array to Out array.
|
|
// The index map corresponds to the vertices in the vertex buffer.
|
|
// Skip the reserved indices that are used for connectivity between
|
|
// partial primitives.
|
|
|
|
iMapNext = iOutNext;
|
|
|
|
// Reset hash array to no mapping (-1).
|
|
|
|
RtlFillMemoryUlong((PVOID) pHash, (ULONG) VA_HASH_SIZE * sizeof(*pHash),
|
|
(ULONG) -1);
|
|
|
|
// There are 3 possibilities in the following loop:
|
|
//
|
|
// 1. All input indices have been processed. The primitive is complete!
|
|
// 2. The index map overflows. We have accumulated 256 vertices for a partial
|
|
// primitive.
|
|
// 3. The output index array overflows. We have exceeded our estimated size
|
|
// of the output index array for a partial primitive.
|
|
|
|
for ( ; iCount < count; iCount++)
|
|
{
|
|
// Get next input index.
|
|
|
|
if (type == GL_UNSIGNED_BYTE)
|
|
iIn = (GLuint) ((GLubyte *) pIn)[iCount];
|
|
else if (type == GL_UNSIGNED_SHORT)
|
|
iIn = (GLuint) ((GLushort *) pIn)[iCount];
|
|
else
|
|
iIn = (GLuint) ((GLuint *) pIn)[iCount];
|
|
|
|
#if DRAWELEM_DEBUG
|
|
DbgPrint("iCount %d ", iCount);
|
|
DbgPrint("iIn %d ", iIn);
|
|
DbgPrint("iMapNext %d iOutNext %d",
|
|
(GLuint) iMapNext, (GLuint) iOutNext);
|
|
#endif
|
|
|
|
// Look up previously mapped index if one exists.
|
|
|
|
iMap = pHash[VA_HASH(iIn)];
|
|
while (iMap != (GLushort) -1 && aMap[iMap].iIn != iIn)
|
|
iMap = aMap[iMap].next;
|
|
|
|
#if DRAWELEM_DEBUG
|
|
DbgPrint("iMapFound %d\n", (GLuint) iMap);
|
|
#endif
|
|
|
|
// If aMap or aOut overflows, flush the partial primitive.
|
|
|
|
if (iOutNext >= VA_DRAWELEM_INDEX_SIZE ||
|
|
(iMap == (GLushort) -1 && iMapNext >= VA_DRAWELEM_MAP_SIZE))
|
|
{
|
|
#if DRAWELEM_DEBUG
|
|
DbgPrint("Flush iMapNext %d iOutNext %d\n",
|
|
(GLuint) iMapNext, (GLuint) iOutNext);
|
|
#endif
|
|
|
|
// We have accumulated enough vertices for a partial primitive. We now
|
|
// need to figure out the exact number of vertices to flush and redo
|
|
// the leftover vertices in the next partial primitive.
|
|
|
|
#if DBG
|
|
if (iOutNext >= VA_DRAWELEM_INDEX_SIZE)
|
|
DbgPrint("DrawElements: aOut buffer overflows\n");
|
|
#endif
|
|
|
|
// Find the flush vertex of this partial primitive.
|
|
|
|
nLeft = 0;
|
|
switch (mode)
|
|
{
|
|
case GL_LINE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
break;
|
|
case GL_POINTS:
|
|
case GL_LINE_LOOP:
|
|
case GL_POLYGON:
|
|
ASSERTOPENGL(FALSE, "unexpected primitive type\n");
|
|
break;
|
|
case GL_LINES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_QUAD_STRIP:
|
|
// number of vertices must be a multiple of 2
|
|
if (iOutNext % 2)
|
|
nLeft++;
|
|
break;
|
|
case GL_TRIANGLES:
|
|
// number of vertices must be a multiple of 3
|
|
switch (iOutNext % 3)
|
|
{
|
|
case 2: nLeft++; // fall through
|
|
case 1: nLeft++;
|
|
}
|
|
break;
|
|
case GL_QUADS:
|
|
// number of vertices must be a multiple of 4
|
|
switch (iOutNext % 4)
|
|
{
|
|
case 3: nLeft++; // fall through
|
|
case 2: nLeft++; // fall through
|
|
case 1: nLeft++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add the leftover vertices back to the input array and redo them
|
|
// in the next partial primitive.
|
|
|
|
iCount -= nLeft;
|
|
iOutNext -= (GLushort) nLeft;
|
|
|
|
// When passing on our data, skip any vertices
|
|
// that were reserved from a previous partial primitive
|
|
(*pfnHandler)(gc, mode,
|
|
iMapNext-iPartialIndices, aMap+iPartialIndices,
|
|
iOutNext, aOut, GL_TRUE);
|
|
|
|
iPartialIndices = nReservedIndicesPartialBegin[mode];
|
|
|
|
// Continue to process remaining vertices.
|
|
|
|
goto DrawElements_NextBatch;
|
|
}
|
|
|
|
// If no previously mapped index is found, add the new vertex.
|
|
|
|
if (iMap == (GLushort) -1)
|
|
{
|
|
ASSERTOPENGL(iMapNext < VA_DRAWELEM_MAP_SIZE,
|
|
"index map overflows!\n");
|
|
|
|
#if DRAWELEM_DEBUG
|
|
DbgPrint(" Add iIn %d iMap %d iHash %d\n",
|
|
iIn, (GLuint) iMapNext, (GLuint) VA_HASH(iIn));
|
|
#endif
|
|
|
|
iMap = iMapNext++;
|
|
aMap[iMap].iIn = iIn;
|
|
aMap[iMap].next = pHash[VA_HASH(iIn)];
|
|
pHash[VA_HASH(iIn)] = iMap;
|
|
}
|
|
|
|
// Add the mapped index to output index array.
|
|
|
|
ASSERTOPENGL(iMap < VA_DRAWELEM_MAP_SIZE, "bad mapped index\n");
|
|
ASSERTOPENGL(iOutNext < VA_DRAWELEM_INDEX_SIZE,
|
|
"aOut array overflows!\n");
|
|
|
|
#if DRAWELEM_DEBUG
|
|
DbgPrint(" Add iOutNext %d iMap %d\n",
|
|
(GLuint) iOutNext, (GLuint) iMap);
|
|
#endif
|
|
aOut[iOutNext++] = (GLubyte) iMap;
|
|
}
|
|
|
|
// We have processed all input vertices.
|
|
// Pass on any remaining data
|
|
|
|
(*pfnHandler)(gc, mode,
|
|
iMapNext-iPartialIndices, aMap+iPartialIndices,
|
|
iOutNext, aOut, GL_FALSE);
|
|
}
|
|
|
|
void FASTCALL glcltReducedElementsHandler(__GLcontext *gc,
|
|
GLenum mode,
|
|
GLsizei iVertexCount,
|
|
VAMAP *pvmVertices,
|
|
GLsizei iElementCount,
|
|
GLubyte *pbElements,
|
|
GLboolean fPartial)
|
|
{
|
|
POLYARRAY *pa = gc->paTeb;
|
|
PFNVAELEMENT pfn;
|
|
GLsizei i;
|
|
|
|
// Set up the vertex data
|
|
pfn = gc->vertexArray.pfnArrayElement;
|
|
if (pvmVertices != NULL)
|
|
{
|
|
for (i = 0; i < iVertexCount; i++)
|
|
{
|
|
(*pfn)(gc, pvmVertices->iIn);
|
|
pvmVertices++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < iVertexCount; i++)
|
|
{
|
|
(*pfn)(gc, i);
|
|
}
|
|
}
|
|
|
|
// Copy the index array to the end of the polyarray primitive.
|
|
|
|
pa->nIndices = (GLuint) iElementCount;
|
|
// skip terminator vertex
|
|
pa->aIndices = (GLubyte *) (pa->pdNextVertex + 1);
|
|
ASSERTOPENGL(pa->aIndices + pa->nIndices
|
|
<= (GLubyte *) (pa->pdBufferMax+1),
|
|
"Vertex buffer overflows!\n");
|
|
memcpy(pa->aIndices, pbElements, pa->nIndices * sizeof(GLubyte));
|
|
|
|
if (fPartial)
|
|
{
|
|
// Flush the partial primitive.
|
|
|
|
VA_DrawElementsFlushPartialPrimitive(pa, mode);
|
|
}
|
|
else
|
|
{
|
|
VA_DrawElementsEnd(pa);
|
|
}
|
|
}
|
|
|
|
void APIENTRY glcltDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *pIn)
|
|
{
|
|
PFNVAELEMENT pfn;
|
|
POLYARRAY *pa;
|
|
GLuint iIn;
|
|
GLsizei iCount;
|
|
|
|
__GL_SETUP();
|
|
|
|
pa = gc->paTeb;
|
|
|
|
#define DRAWELEM_DEBUG 0
|
|
#if DRAWELEM_DEBUG
|
|
{
|
|
DbgPrint("mode %d, count %d, type %d\n", mode, count, type);
|
|
DbgPrint("pIn: ");
|
|
for (iCount = 0; iCount < count; iCount++)
|
|
{
|
|
if (type == GL_UNSIGNED_BYTE)
|
|
iIn = (GLuint) ((GLubyte *) pIn)[iCount];
|
|
else if (type == GL_UNSIGNED_SHORT)
|
|
iIn = (GLuint) ((GLushort *) pIn)[iCount];
|
|
else
|
|
iIn = (GLuint) ((GLuint *) pIn)[iCount];
|
|
|
|
DbgPrint("%d ", iIn);
|
|
}
|
|
DbgPrint("\n");
|
|
}
|
|
#endif
|
|
|
|
// If we are already in the begin/end bracket, return an error.
|
|
|
|
if (pa->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
if ((GLuint) mode > GL_POLYGON)
|
|
{
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (count < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
} else if (!count)
|
|
return;
|
|
|
|
switch (type)
|
|
{
|
|
case GL_UNSIGNED_BYTE:
|
|
case GL_UNSIGNED_SHORT:
|
|
case GL_UNSIGNED_INT:
|
|
break;
|
|
default:
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
// Find array element function to use.
|
|
|
|
if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY)
|
|
VA_ValidateArrayPointers(gc);
|
|
pfn = gc->vertexArray.pfnArrayElement;
|
|
|
|
// Send Points, Line Loop, and Polygon to Begin/End call. Points and Polygon
|
|
// don't benefit from optimization in this function. Further, Polygon and
|
|
// Line Loop are too tricky to deal with in this function.
|
|
|
|
if (mode == GL_POINTS || mode == GL_LINE_LOOP || mode == GL_POLYGON)
|
|
{
|
|
glcltBegin(mode);
|
|
pa->flags |= POLYARRAY_SAME_POLYDATA_TYPE;
|
|
|
|
for (iCount = 0; iCount < count; iCount++)
|
|
{
|
|
// Get next input index.
|
|
if (type == GL_UNSIGNED_BYTE)
|
|
iIn = (GLuint) ((GLubyte *) pIn)[iCount];
|
|
else if (type == GL_UNSIGNED_SHORT)
|
|
iIn = (GLuint) ((GLushort *) pIn)[iCount];
|
|
else
|
|
iIn = (GLuint) ((GLuint *) pIn)[iCount];
|
|
|
|
(*pfn)(gc, iIn);
|
|
}
|
|
|
|
glcltEnd();
|
|
return;
|
|
}
|
|
|
|
// Begin primitive.
|
|
|
|
VA_DrawElementsBegin(pa, mode, count);
|
|
|
|
// The primitive will be ended on the last batch of
|
|
// elements
|
|
ReduceDrawElements(gc, mode, count, type, pIn,
|
|
glcltReducedElementsHandler);
|
|
}
|
|
|
|
// Interleaved array AND mask.
|
|
// INTERLEAVED_FORMAT_ASSERT
|
|
GLuint iaAndMask[14] =
|
|
{
|
|
// GL_V2F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_COLOR_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_COLOR_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_C4UB_V2F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_C4UB_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_C3F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_N3F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_COLOR_TYPE_SIZE_MASK,
|
|
// GL_C4F_N3F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_TEXCOORD_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK,
|
|
// GL_T2F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_COLOR_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_T4F_V4F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_COLOR_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_T2F_C4UB_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_T2F_C3F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_NORMAL_TYPE_SIZE_MASK,
|
|
// GL_T2F_N3F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK |
|
|
VAMASK_COLOR_TYPE_SIZE_MASK,
|
|
// GL_T2F_C4F_N3F_V3F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK,
|
|
// GL_T4F_C4F_N3F_V4F
|
|
VAMASK_EDGEFLAG_TYPE_SIZE_MASK |
|
|
VAMASK_INDEX_TYPE_SIZE_MASK,
|
|
};
|
|
|
|
// Interleaved array OR mask.
|
|
// INTERLEAVED_FORMAT_ASSERT
|
|
GLuint iaOrMask[14] =
|
|
{
|
|
VAMASK_FORMAT_V2F, // GL_V2F
|
|
VAMASK_FORMAT_V3F, // GL_V3F
|
|
VAMASK_FORMAT_C4UB_V2F, // GL_C4UB_V2F
|
|
VAMASK_FORMAT_C4UB_V3F, // GL_C4UB_V3F
|
|
VAMASK_FORMAT_C3F_V3F, // GL_C3F_V3F
|
|
VAMASK_FORMAT_N3F_V3F, // GL_N3F_V3F
|
|
VAMASK_FORMAT_C4F_N3F_V3F, // GL_C4F_N3F_V3F
|
|
VAMASK_FORMAT_T2F_V3F, // GL_T2F_V3F
|
|
VAMASK_FORMAT_T4F_V4F, // GL_T4F_V4F
|
|
VAMASK_FORMAT_T2F_C4UB_V3F, // GL_T2F_C4UB_V3F
|
|
VAMASK_FORMAT_T2F_C3F_V3F, // GL_T2F_C3F_V3F
|
|
VAMASK_FORMAT_T2F_N3F_V3F, // GL_T2F_N3F_V3F
|
|
VAMASK_FORMAT_T2F_C4F_N3F_V3F, // GL_T2F_C4F_N3F_V3F
|
|
VAMASK_FORMAT_T4F_C4F_N3F_V4F, // GL_T4F_C4F_N3F_V4F
|
|
};
|
|
|
|
// Interleaved array default strides.
|
|
GLuint iaStride[14] =
|
|
{
|
|
2 * sizeof(GLfloat), // GL_V2F
|
|
3 * sizeof(GLfloat), // GL_V3F
|
|
2 * sizeof(GLfloat) + 4 * sizeof(GLubyte), // GL_C4UB_V2F
|
|
3 * sizeof(GLfloat) + 4 * sizeof(GLubyte), // GL_C4UB_V3F
|
|
6 * sizeof(GLfloat), // GL_C3F_V3F
|
|
6 * sizeof(GLfloat), // GL_N3F_V3F
|
|
10 * sizeof(GLfloat), // GL_C4F_N3F_V3F
|
|
5 * sizeof(GLfloat), // GL_T2F_V3F
|
|
8 * sizeof(GLfloat), // GL_T4F_V4F
|
|
5 * sizeof(GLfloat) + 4 * sizeof(GLubyte), // GL_T2F_C4UB_V3F
|
|
8 * sizeof(GLfloat), // GL_T2F_C3F_V3F
|
|
8 * sizeof(GLfloat), // GL_T2F_N3F_V3F
|
|
12 * sizeof(GLfloat), // GL_T2F_C4F_N3F_V3F
|
|
15 * sizeof(GLfloat), // GL_T4F_C4F_N3F_V4F
|
|
};
|
|
|
|
void APIENTRY glcltInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer)
|
|
{
|
|
GLuint iFormat, iStride;
|
|
GLuint vaMask;
|
|
const GLbyte *pb = pointer;
|
|
__GL_SETUP();
|
|
|
|
// Not allowed in begin/end.
|
|
|
|
if (gc->paTeb->flags & POLYARRAY_IN_BEGIN)
|
|
{
|
|
GLSETERROR(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
|
|
// INTERLEAVED_FORMAT_ASSERT
|
|
iFormat = (GLuint) (format - GL_V2F);
|
|
if (iFormat > GL_T4F_C4F_N3F_V4F)
|
|
{
|
|
GLSETERROR(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (stride < 0)
|
|
{
|
|
GLSETERROR(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (stride)
|
|
iStride = stride;
|
|
else
|
|
iStride = iaStride[iFormat];
|
|
|
|
// Compute new mask.
|
|
// If we are disabling an array, don't modify its type and size field!
|
|
|
|
vaMask = gc->vertexArray.mask;
|
|
vaMask &= iaAndMask[iFormat];
|
|
vaMask |= iaOrMask[iFormat];
|
|
|
|
if (gc->vertexArray.mask != vaMask)
|
|
{
|
|
gc->vertexArray.mask = vaMask;
|
|
gc->vertexArray.flags |= __GL_VERTEX_ARRAY_DIRTY;
|
|
}
|
|
|
|
if (vaMask & VAMASK_TEXCOORD_ENABLE_MASK)
|
|
{
|
|
gc->vertexArray.texCoord.type = GL_FLOAT;
|
|
gc->vertexArray.texCoord.stride = iStride;
|
|
gc->vertexArray.texCoord.ibytes = iStride;
|
|
gc->vertexArray.texCoord.pointer = pb;
|
|
if ((vaMask & VAMASK_TEXCOORD_TYPE_SIZE_MASK) ==
|
|
(VAMASK_TEXCOORD_SIZE_4 | VAMASK_TEXCOORD_TYPE_FLOAT))
|
|
{
|
|
gc->vertexArray.texCoord.size = 4;
|
|
pb += 4 * sizeof(GLfloat);
|
|
}
|
|
else
|
|
{
|
|
ASSERTOPENGL((vaMask & VAMASK_TEXCOORD_TYPE_SIZE_MASK) ==
|
|
(VAMASK_TEXCOORD_SIZE_2 | VAMASK_TEXCOORD_TYPE_FLOAT),
|
|
"unhandled texcoord format\n");
|
|
gc->vertexArray.texCoord.size = 2;
|
|
pb += 2 * sizeof(GLfloat);
|
|
}
|
|
}
|
|
|
|
if (vaMask & VAMASK_COLOR_ENABLE_MASK)
|
|
{
|
|
gc->vertexArray.color.stride = iStride;
|
|
gc->vertexArray.color.ibytes = iStride;
|
|
gc->vertexArray.color.pointer = pb;
|
|
|
|
switch (vaMask & VAMASK_COLOR_TYPE_SIZE_MASK)
|
|
{
|
|
case VAMASK_COLOR_TYPE_UBYTE | VAMASK_COLOR_SIZE_4:
|
|
gc->vertexArray.color.type = GL_UNSIGNED_BYTE;
|
|
gc->vertexArray.color.size = 4;
|
|
pb += 4 * sizeof(GLubyte);
|
|
break;
|
|
case VAMASK_COLOR_TYPE_FLOAT | VAMASK_COLOR_SIZE_3:
|
|
gc->vertexArray.color.type = GL_FLOAT;
|
|
gc->vertexArray.color.size = 3;
|
|
pb += 3 * sizeof(GLfloat);
|
|
break;
|
|
case VAMASK_COLOR_TYPE_FLOAT | VAMASK_COLOR_SIZE_4:
|
|
gc->vertexArray.color.type = GL_FLOAT;
|
|
gc->vertexArray.color.size = 4;
|
|
pb += 4 * sizeof(GLfloat);
|
|
break;
|
|
default:
|
|
ASSERTOPENGL(FALSE, "unhandled color format\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (vaMask & VAMASK_NORMAL_ENABLE_MASK)
|
|
{
|
|
gc->vertexArray.normal.type = GL_FLOAT;
|
|
gc->vertexArray.normal.stride = iStride;
|
|
gc->vertexArray.normal.ibytes = iStride;
|
|
gc->vertexArray.normal.pointer = pb;
|
|
pb += 3 * sizeof(GLfloat);
|
|
}
|
|
|
|
gc->vertexArray.vertex.type = GL_FLOAT;
|
|
gc->vertexArray.vertex.stride = iStride;
|
|
gc->vertexArray.vertex.ibytes = iStride;
|
|
gc->vertexArray.vertex.pointer = pb;
|
|
switch (vaMask & VAMASK_VERTEX_TYPE_SIZE_MASK)
|
|
{
|
|
case VAMASK_VERTEX_TYPE_FLOAT | VAMASK_VERTEX_SIZE_4:
|
|
gc->vertexArray.vertex.size = 4;
|
|
break;
|
|
case VAMASK_VERTEX_TYPE_FLOAT | VAMASK_VERTEX_SIZE_3:
|
|
gc->vertexArray.vertex.size = 3;
|
|
break;
|
|
case VAMASK_VERTEX_TYPE_FLOAT | VAMASK_VERTEX_SIZE_2:
|
|
gc->vertexArray.vertex.size = 2;
|
|
break;
|
|
default:
|
|
ASSERTOPENGL(FALSE, "unhandled vertex format\n");
|
|
break;
|
|
}
|
|
}
|