NT4/private/windows/opengl/client/array.c
2020-09-30 17:12:29 +02:00

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;
}
}