|
|
/******************************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_ArrayElementB(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_V2F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_C3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_N3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_C3F_N3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_C4F_N3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_T2F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_T2F_C3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_T2F_N3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_T2F_C3F_N3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices); void FASTCALL VA_ArrayElement_T2F_C4F_N3F_V3F_B(__GLcontext *gc, GLint firstVertex, GLint nVertices);
void FASTCALL VA_ArrayElementBI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_V2F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_C3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_N3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_C3F_N3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_C4F_N3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_T2F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_T2F_C3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_T2F_N3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_T2F_C3F_N3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices); void FASTCALL VA_ArrayElement_T2F_C4F_N3F_V3F_BI(__GLcontext *gc, GLint nVertices, VAMAP* indices);
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
VA_ArrayElementB, // pfnArrayElementBatch
VA_ArrayElementBI, // pfnArrayElementBatchIndirect
{ // 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; PFNVAELEMENTBATCH fpB; PFNVAELEMENTBATCHINDIRECT fpBI;
fp = VA_ArrayElement; fpB = VA_ArrayElementB; fpBI = VA_ArrayElementBI; 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; fpB = VA_ArrayElement_V2F_B; fpBI = VA_ArrayElement_V2F_BI; break; case VAMASK_FORMAT_V3F: fp = VA_ArrayElement_V3F; fpB = VA_ArrayElement_V3F_B; fpBI = VA_ArrayElement_V3F_BI; break; case VAMASK_FORMAT_C3F_V3F: fp = VA_ArrayElement_C3F_V3F; fpB = VA_ArrayElement_C3F_V3F_B; fpBI = VA_ArrayElement_C3F_V3F_BI; break; case VAMASK_FORMAT_N3F_V3F: fp = VA_ArrayElement_N3F_V3F; fpB = VA_ArrayElement_N3F_V3F_B; fpBI = VA_ArrayElement_N3F_V3F_BI; break; case VAMASK_FORMAT_C3F_N3F_V3F: fp = VA_ArrayElement_C3F_N3F_V3F; fpB = VA_ArrayElement_C3F_N3F_V3F_B; fpBI = VA_ArrayElement_C3F_N3F_V3F_BI; break; case VAMASK_FORMAT_C4F_N3F_V3F: fp = VA_ArrayElement_C4F_N3F_V3F; fpB = VA_ArrayElement_C4F_N3F_V3F_B; fpBI = VA_ArrayElement_C4F_N3F_V3F_BI; break; case VAMASK_FORMAT_T2F_V3F: fp = VA_ArrayElement_T2F_V3F; fpB = VA_ArrayElement_T2F_V3F_B; fpBI = VA_ArrayElement_T2F_V3F_BI; break; case VAMASK_FORMAT_T2F_C3F_V3F: fp = VA_ArrayElement_T2F_C3F_V3F; fpB = VA_ArrayElement_T2F_C3F_V3F_B; fpBI = VA_ArrayElement_T2F_C3F_V3F_BI; break; case VAMASK_FORMAT_T2F_N3F_V3F: fp = VA_ArrayElement_T2F_N3F_V3F; fpB = VA_ArrayElement_T2F_N3F_V3F_B; fpBI = VA_ArrayElement_T2F_N3F_V3F_BI; break; case VAMASK_FORMAT_T2F_C3F_N3F_V3F: fp = VA_ArrayElement_T2F_C3F_N3F_V3F; fpB = VA_ArrayElement_T2F_C3F_N3F_V3F_B; fpBI = VA_ArrayElement_T2F_C3F_N3F_V3F_BI; break; case VAMASK_FORMAT_T2F_C4F_N3F_V3F: fp = VA_ArrayElement_T2F_C4F_N3F_V3F; fpB = VA_ArrayElement_T2F_C4F_N3F_V3F_B; fpBI = VA_ArrayElement_T2F_C4F_N3F_V3F_BI; 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.pfnArrayElementBatch = fpB; gc->vertexArray.pfnArrayElementBatchIndirect = fpBI; 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))
#define CALLARRAYPOINTERS \
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 FASTCALL VA_ArrayElementB(__GLcontext *gc, GLint firstVertex, GLint nVertices) { GLint k, i; GLuint vaMask = gc->vertexArray.mask;
for (k=0; k < nVertices; k++) { i = k+firstVertex; CALLARRAYPOINTERS; } }
void FASTCALL VA_ArrayElementBI(__GLcontext *gc, GLint nVertices, VAMAP* indices) { GLint k, i; GLuint vaMask = gc->vertexArray.mask;
for (k=0; k < nVertices; k++) { i = indices[k].iIn; CALLARRAYPOINTERS; } }
void FASTCALL VA_ArrayElement(__GLcontext *gc, GLint i) { GLuint vaMask = gc->vertexArray.mask;
CALLARRAYPOINTERS; }
void APIENTRY glcltDrawArrays (GLenum mode, GLint first, GLsizei count) { int i; POLYARRAY *pa; PFNVAELEMENTBATCH 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.pfnArrayElementBatch;
// 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;
(*pfn)(gc, first, count);
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 consecutive order.
// Dword aligned hash array.
pHash = (GLushort *) (((UINT_PTR) _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, 0, 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, 0, aMap+iPartialIndices, iOutNext, aOut, GL_FALSE); }
void FASTCALL glcltReducedElementsHandler(__GLcontext *gc, GLenum mode, GLsizei iVertexCount, GLsizei iVertexBase, 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) { PFNVAELEMENTBATCHINDIRECT pfn = gc->vertexArray.pfnArrayElementBatchIndirect; (*pfn)(gc, iVertexCount, pvmVertices); } else { // Access consecutive block of vertices, starting at iVertexBase
PFNVAELEMENTBATCH pfn = gc->vertexArray.pfnArrayElementBatch; (*pfn)(gc, iVertexBase, iVertexCount); } // 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); } }
// This handles primitive modes that DrawElements or DrawRangeElements don't.
void FASTCALL VA_DrawElementsHandleOtherPrimTypes( __GLcontext *gc, GLenum mode, GLsizei count, GLenum type, GLvoid *pIn ) { GLsizei iCount; PFNVAELEMENT pfn; POLYARRAY *pa; GLuint iIn;
pa = gc->paTeb; pfn = gc->vertexArray.pfnArrayElement;
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(); }
void APIENTRY glcltDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *pIn) { 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);
// 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) { VA_DrawElementsHandleOtherPrimTypes( gc, mode, count, type, (GLvoid *) pIn ); 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); }
void RebaseIndices( GLvoid *pIn, GLubyte *aOut, GLsizei count, GLuint start, GLenum type ) { if (type == GL_UNSIGNED_BYTE) { while( count-- ) *aOut++ = (GLubyte) ( ((GLuint) *( ((GLubyte *) pIn) ++ )) - start); } else if (type == GL_UNSIGNED_SHORT) { while( count-- ) *aOut++ = (GLubyte) ( ((GLuint) *( ((GLushort *) pIn) ++ )) - start); } else { while( count-- ) *aOut++ = (GLubyte) ( ((GLuint) *( ((GLuint *) pIn) ++ )) - start); } }
void APIENTRY glcltDrawRangeElementsWIN(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *pIn) { POLYARRAY *pa; GLuint iVertexCount; GLubyte aOut[VA_DRAWELEM_INDEX_SIZE];
__GL_SETUP();
pa = gc->paTeb;
// 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; }
iVertexCount = end-start+1; if( (count < 0) || (end < start) ) { 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; }
if (gc->vertexArray.flags & __GL_VERTEX_ARRAY_DIRTY) VA_ValidateArrayPointers(gc);
// 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) { VA_DrawElementsHandleOtherPrimTypes( gc, mode, count, type, (GLvoid *) pIn ); return; }
// Begin primitive.
VA_DrawElementsBegin(pa, mode, count);
if ( (count > VA_DRAWRANGEELEM_MAX_INDICES) || (iVertexCount > VA_DRAWRANGEELEM_MAX_VERTICES) ) { // The primitive is too large to be processed directly so
// we have to reduce it. The primitive will be ended on the
// last batch of elements.
ReduceDrawElements(gc, mode, count, type, pIn, glcltReducedElementsHandler); } else { // Need to rebase (0-base) the indices and convert them to ubyte for
// the reduced element handler.
RebaseIndices( (GLvoid *) pIn, aOut, count, start, type );
// Finish primitive
glcltReducedElementsHandler(gc, mode, iVertexCount, start, // iVertexBase
NULL, count, aOut, GL_FALSE); } }
// 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; } }
|