3424 lines
98 KiB
C
3424 lines
98 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: so_array.c
|
|
*
|
|
* fast vertex array
|
|
*
|
|
* 04-May-1995 mikeke Created
|
|
*
|
|
* 08-Aug-1995 marcfo Added display list version.
|
|
*
|
|
* 06-Sep-1995 marcfo Optimized display list
|
|
*
|
|
* Copyright (c) 1995 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "array.h"
|
|
|
|
#include "listcomp.h"
|
|
#include "g_listop.h"
|
|
#include "lcfuncs.h"
|
|
#include "dlist.h"
|
|
#include "dlistopt.h"
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Vertex Array Setup Functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
PFNVECTOR ppfnvglimVertex[32] = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex2sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex2iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex2fv,
|
|
(PFNVECTOR)__glim_Vertex2dv,
|
|
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex3sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex3iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex3fv,
|
|
(PFNVECTOR)__glim_Vertex3dv,
|
|
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex4sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex4iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Vertex4fv,
|
|
(PFNVECTOR)__glim_Vertex4dv,
|
|
};
|
|
|
|
PFNVECTOR ppfnvglimTexCoord[32] = {
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord1sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord1iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord1fv,
|
|
(PFNVECTOR)__glim_TexCoord1dv,
|
|
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord2sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord2iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord2fv,
|
|
(PFNVECTOR)__glim_TexCoord2dv,
|
|
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord3sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord3iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord3fv,
|
|
(PFNVECTOR)__glim_TexCoord3dv,
|
|
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord4sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord4iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_TexCoord4fv,
|
|
(PFNVECTOR)__glim_TexCoord4dv,
|
|
};
|
|
|
|
PFNVECTOR ppfnvglimIndex[32] = {
|
|
NULL,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Indexsv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Indexiv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Indexfv,
|
|
(PFNVECTOR)__glim_Indexdv,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
|
|
PFNVECTOR ppfnvglimEdgeFlag[32] = {
|
|
NULL,
|
|
(PFNVECTOR)__glim_EdgeFlagv,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
|
|
PFNVECTOR ppfnvglimColor[32] = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
(PFNVECTOR)__glim_Color3bv,
|
|
(PFNVECTOR)__glim_Color3ubv,
|
|
(PFNVECTOR)__glim_Color3sv,
|
|
(PFNVECTOR)__glim_Color3usv,
|
|
(PFNVECTOR)__glim_Color3iv,
|
|
(PFNVECTOR)__glim_Color3uiv,
|
|
(PFNVECTOR)__glim_Color3fv,
|
|
(PFNVECTOR)__glim_Color3dv,
|
|
|
|
(PFNVECTOR)__glim_Color4bv,
|
|
(PFNVECTOR)__glim_Color4ubv,
|
|
(PFNVECTOR)__glim_Color4sv,
|
|
(PFNVECTOR)__glim_Color4usv,
|
|
(PFNVECTOR)__glim_Color4iv,
|
|
(PFNVECTOR)__glim_Color4uiv,
|
|
(PFNVECTOR)__glim_Color4fv,
|
|
(PFNVECTOR)__glim_Color4dv,
|
|
};
|
|
|
|
PFNVECTOR ppfnvglimNormal[32] = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
|
|
(PFNVECTOR)__glim_Normal3bv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Normal3sv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Normal3iv,
|
|
NULL,
|
|
(PFNVECTOR)__glim_Normal3fv,
|
|
(PFNVECTOR)__glim_Normal3dv,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
|
|
/****************************************************************************/
|
|
|
|
GLuint FASTCALL __glTypeSize(GLenum enm)
|
|
{
|
|
switch (enm) {
|
|
case GL_BYTE: return sizeof(GLbyte);
|
|
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
|
|
case GL_SHORT: return sizeof(GLshort);
|
|
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
|
|
case GL_INT: return sizeof(GLint);
|
|
case GL_UNSIGNED_INT: return sizeof(GLuint);
|
|
case GL_FLOAT: return sizeof(GLfloat);
|
|
case GL_DOUBLE_EXT: return sizeof(GLdouble);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL SetupArrayPointer(
|
|
PARRAYPOINTER pap,
|
|
PFNVECTOR* ppfnVector)
|
|
{
|
|
GLint itype;
|
|
pap->pfn = NULL;
|
|
|
|
switch (pap->type) {
|
|
case GL_BYTE: itype = 0; break;
|
|
case GL_UNSIGNED_BYTE: itype = 1; break;
|
|
case GL_SHORT: itype = 2; break;
|
|
case GL_UNSIGNED_SHORT: itype = 3; break;
|
|
case GL_INT: itype = 4; break;
|
|
case GL_UNSIGNED_INT: itype = 5; break;
|
|
case GL_FLOAT: itype = 6; break;
|
|
case GL_DOUBLE_EXT: itype = 7; break;
|
|
}
|
|
|
|
if (pap->stride != 0) {
|
|
pap->ibytes = pap->stride;
|
|
} else {
|
|
pap->ibytes = __glTypeSize(pap->type) * pap->size;
|
|
}
|
|
|
|
pap->pfn = ppfnVector[itype + (pap->size - 1) * 8];
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void APIPRIVATE __glim_VertexPointerEXT(
|
|
GLint size,
|
|
GLenum type,
|
|
GLsizei stride,
|
|
GLsizei count,
|
|
const GLvoid* pointer)
|
|
{
|
|
int i;
|
|
|
|
__GL_SETUP();
|
|
|
|
if (size < 2 || size > 4 || stride < 0 || count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
switch (type) {
|
|
case GL_SHORT: break;
|
|
case GL_INT: break;
|
|
case GL_FLOAT: break;
|
|
case GL_DOUBLE_EXT: break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
gc->apVertex.size = size ;
|
|
gc->apVertex.type = type ;
|
|
gc->apVertex.stride = stride ;
|
|
gc->apVertex.count = count ;
|
|
gc->apVertex.pointer = (GLbyte*)pointer;
|
|
|
|
SetupArrayPointer(&(gc->apVertex), ppfnvglimVertex);
|
|
__GL_DELAY_VALIDATE(gc);
|
|
}
|
|
|
|
void APIPRIVATE __glim_ColorPointerEXT(
|
|
GLint size,
|
|
GLenum type,
|
|
GLsizei stride,
|
|
GLsizei count,
|
|
const GLvoid* pointer)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
if (size < 3 || size > 4 || stride < 0 || count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
switch (type) {
|
|
case GL_BYTE: break;
|
|
case GL_UNSIGNED_BYTE: break;
|
|
case GL_SHORT: break;
|
|
case GL_UNSIGNED_SHORT: break;
|
|
case GL_INT: break;
|
|
case GL_UNSIGNED_INT: break;
|
|
case GL_FLOAT: break;
|
|
case GL_DOUBLE_EXT: break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
gc->apColor.size = size ;
|
|
gc->apColor.type = type ;
|
|
gc->apColor.stride = stride ;
|
|
gc->apColor.count = count ;
|
|
gc->apColor.pointer = (GLbyte*)pointer;
|
|
|
|
SetupArrayPointer(&(gc->apColor), ppfnvglimColor);
|
|
__GL_DELAY_VALIDATE(gc);
|
|
}
|
|
|
|
void APIPRIVATE __glim_TexCoordPointerEXT(
|
|
GLint size,
|
|
GLenum type,
|
|
GLsizei stride,
|
|
GLsizei count,
|
|
const GLvoid* pointer)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
if (size < 1 || size > 4 || stride < 0 || count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
switch (type) {
|
|
case GL_SHORT: break;
|
|
case GL_INT: break;
|
|
case GL_FLOAT: break;
|
|
case GL_DOUBLE_EXT: break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
gc->apTexCoord.size = size ;
|
|
gc->apTexCoord.type = type ;
|
|
gc->apTexCoord.stride = stride ;
|
|
gc->apTexCoord.count = count ;
|
|
gc->apTexCoord.pointer = (GLbyte*)pointer;
|
|
|
|
SetupArrayPointer(&(gc->apTexCoord), ppfnvglimTexCoord);
|
|
__GL_DELAY_VALIDATE(gc);
|
|
}
|
|
|
|
void APIPRIVATE __glim_NormalPointerEXT(
|
|
GLenum type,
|
|
GLsizei stride,
|
|
GLsizei count,
|
|
const GLvoid* pointer)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
if (stride < 0 || count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
switch (type) {
|
|
case GL_BYTE: break;
|
|
case GL_SHORT: break;
|
|
case GL_INT: break;
|
|
case GL_FLOAT: break;
|
|
case GL_DOUBLE_EXT: break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
gc->apNormal.size = 3 ;
|
|
gc->apNormal.type = type ;
|
|
gc->apNormal.stride = stride ;
|
|
gc->apNormal.count = count ;
|
|
gc->apNormal.pointer = (GLbyte*)pointer;
|
|
|
|
SetupArrayPointer(&(gc->apNormal), ppfnvglimNormal);
|
|
__GL_DELAY_VALIDATE(gc);
|
|
}
|
|
|
|
void APIPRIVATE __glim_IndexPointerEXT(
|
|
GLenum type,
|
|
GLsizei stride,
|
|
GLsizei count,
|
|
const GLvoid* pointer)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
if (stride < 0 || count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
switch (type) {
|
|
case GL_SHORT: break;
|
|
case GL_INT: break;
|
|
case GL_FLOAT: break;
|
|
case GL_DOUBLE_EXT: break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
gc->apIndex.size = 1 ;
|
|
gc->apIndex.type = type ;
|
|
gc->apIndex.stride = stride ;
|
|
gc->apIndex.count = count ;
|
|
gc->apIndex.pointer = (GLbyte*)pointer;
|
|
|
|
SetupArrayPointer(&(gc->apIndex), ppfnvglimIndex);
|
|
__GL_DELAY_VALIDATE(gc);
|
|
}
|
|
|
|
void APIPRIVATE __glim_EdgeFlagPointerEXT(
|
|
GLsizei stride,
|
|
GLsizei count,
|
|
const GLboolean* pointer)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
if (stride < 0 || count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
gc->apEdgeFlag.size = 1;
|
|
gc->apEdgeFlag.type = GL_UNSIGNED_BYTE;
|
|
gc->apEdgeFlag.stride = stride ;
|
|
gc->apEdgeFlag.count = count ;
|
|
gc->apEdgeFlag.pointer = (GLbyte*)pointer;
|
|
|
|
SetupArrayPointer(&(gc->apEdgeFlag), ppfnvglimEdgeFlag);
|
|
__GL_DELAY_VALIDATE(gc);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void APIPRIVATE __glim_GetPointervEXT(
|
|
GLenum pname,
|
|
void** params)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
switch (pname) {
|
|
case GL_VERTEX_ARRAY_POINTER_EXT: *params = gc->apVertex.pointer ; return;
|
|
case GL_NORMAL_ARRAY_POINTER_EXT: *params = gc->apNormal.pointer ; return;
|
|
case GL_COLOR_ARRAY_POINTER_EXT: *params = gc->apColor.pointer ; return;
|
|
case GL_INDEX_ARRAY_POINTER_EXT: *params = gc->apIndex.pointer ; return;
|
|
case GL_TEXTURE_COORD_ARRAY_POINTER_EXT: *params = gc->apTexCoord.pointer; return;
|
|
case GL_EDGE_FLAG_ARRAY_POINTER_EXT: *params = gc->apEdgeFlag.pointer; return;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#define CALLARRAYPOINTER(flag, ap) \
|
|
if (gc->ad.dwArrayEnable & flag) \
|
|
(((ap).pfn)((ap).pointer + i * (ap).ibytes))
|
|
|
|
void FASTCALL ArrayElementEXTInternal(
|
|
__GLcontext *gc,
|
|
GLint i)
|
|
{
|
|
CALLARRAYPOINTER(ENABLE_NORMAL, gc->apNormal);
|
|
CALLARRAYPOINTER(ENABLE_COLOR, gc->apColor);
|
|
CALLARRAYPOINTER(ENABLE_INDEX, gc->apIndex);
|
|
CALLARRAYPOINTER(ENABLE_TEXCOORD, gc->apTexCoord);
|
|
CALLARRAYPOINTER(ENABLE_EDGEFLAG, gc->apEdgeFlag);
|
|
CALLARRAYPOINTER(ENABLE_VERTEX, gc->apVertex);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void APIPRIVATE __glim_ArrayElementEXT(
|
|
GLint i)
|
|
{
|
|
__GL_SETUP();
|
|
|
|
ArrayElementEXTInternal(gc, i);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast DrawArray helper functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
void __inline MyCalcClipCode(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
__GLfloat negW;
|
|
GLuint code;
|
|
|
|
code = 0;
|
|
|
|
if (vx->clip.x > vx->clip.w) code |= __GL_CLIP_RIGHT;
|
|
if (vx->clip.y > vx->clip.w) code |= __GL_CLIP_TOP;
|
|
if (vx->clip.z > vx->clip.w) code |= __GL_CLIP_FAR;
|
|
|
|
negW = -vx->clip.w;
|
|
if (vx->clip.x < negW ) code |= __GL_CLIP_LEFT;
|
|
if (vx->clip.y < negW ) code |= __GL_CLIP_BOTTOM;
|
|
if (vx->clip.z < negW ) code |= __GL_CLIP_NEAR;
|
|
|
|
vx->clipCode = code;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyNormalize(float af[3])
|
|
{
|
|
__GLfloat len;
|
|
|
|
len = af[0] * af[0] + af[1] * af[1] + af[2] * af[2];
|
|
|
|
if (len <= __glZero) {
|
|
af[0] = __glZero;
|
|
af[1] = __glZero;
|
|
af[2] = __glZero;
|
|
} else {
|
|
len = ((__GLfloat) 1.0) / __GL_SQRTF(len);
|
|
af[0] *= len;
|
|
af[1] *= len;
|
|
af[2] *= len;
|
|
}
|
|
}
|
|
|
|
void __inline MyCalcNormal(
|
|
__GLcontext *gc,
|
|
__GLcoord *normal,
|
|
__GLfloat *pfNormal)
|
|
{
|
|
__GLtransform *tr = gc->transform.modelView;
|
|
#define imat (tr->inverseTranspose.matrix)
|
|
//!!! call xf3?
|
|
__GLfloat x = pfNormal[0];
|
|
__GLfloat y = pfNormal[1];
|
|
__GLfloat z = pfNormal[2];
|
|
|
|
normal->x = x * imat[0][0] + y * imat[1][0] + z * imat[2][0] + imat[3][0];
|
|
normal->y = x * imat[0][1] + y * imat[1][1] + z * imat[2][1] + imat[3][1];
|
|
normal->z = x * imat[0][2] + y * imat[1][2] + z * imat[2][2] + imat[3][2];
|
|
|
|
#undef imat
|
|
|
|
if (gc->state.enables.general & __GL_NORMALIZE_ENABLE) {
|
|
MyNormalize(&normal->x);
|
|
}
|
|
}
|
|
|
|
void __inline MyXForm3(__GLcoord *res, const __GLfloat v[3], const __GLmatrix *m)
|
|
{
|
|
__GLfloat x = v[0];
|
|
__GLfloat y = v[1];
|
|
__GLfloat z = v[2];
|
|
|
|
res->x = x*m->matrix[0][0] + y*m->matrix[1][0] + z*m->matrix[2][0] + m->matrix[3][0];
|
|
res->y = x*m->matrix[0][1] + y*m->matrix[1][1] + z*m->matrix[2][1] + m->matrix[3][1];
|
|
res->z = x*m->matrix[0][2] + y*m->matrix[1][2] + z*m->matrix[2][2] + m->matrix[3][2];
|
|
res->w = x*m->matrix[0][3] + y*m->matrix[1][3] + z*m->matrix[2][3] + m->matrix[3][3];
|
|
}
|
|
|
|
void ArrayStoreVertex(
|
|
__GLcontext *gc,
|
|
__GLvertex *vx,
|
|
int i)
|
|
{
|
|
GLfloat *pfVertex = (__GLfloat*)
|
|
(gc->apVertex.pointer + i * gc->apVertex.ibytes);
|
|
|
|
vx->iArray = i;
|
|
vx->has = 0;
|
|
|
|
MyXForm3(
|
|
&vx->clip,
|
|
pfVertex,
|
|
&gc->transform.modelView->mvp);
|
|
|
|
if( vx->clip.w != (__GLfloat) 0.0 ) {
|
|
vx->window.w = __glOne / vx->clip.w;
|
|
} else {
|
|
vx->window.w = (__GLfloat) 0.0;
|
|
}
|
|
|
|
vx->window.x = vx->clip.x * gc->state.viewport.xScale * vx->window.w + gc->state.viewport.xCenter;
|
|
vx->window.y = vx->clip.y * gc->state.viewport.yScale * vx->window.w + gc->state.viewport.yCenter;
|
|
vx->window.z = vx->clip.z * gc->state.viewport.zScale * vx->window.w + gc->state.viewport.zCenter;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#ifdef LATER
|
|
//
|
|
// don't support edge flag
|
|
//
|
|
void __inline InlineArrayStoreEdgeFlag(
|
|
__GLcontext *gc,
|
|
__GLvertex *vx,
|
|
int i)
|
|
{
|
|
if (gc->ad.dwArrayEnable & ENABLE_EDGEFLAG) {
|
|
GLubyte *pfEdgeFlag = (GLubyte *)
|
|
(gc->apEdgeFlag.pointer + i * gc->apEdgeFlag.ibytes);
|
|
|
|
vx->boundaryEdge = pfEdgeFlag[0];
|
|
} else {
|
|
vx->boundaryEdge = gc->state.current.edgeTag;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast DrawArray Lighting functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
void FASTCALL MyCalcCI(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
vx->colors[__GL_FRONTFACE].r = gc->state.current.userColorIndex;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyCalcCIArray(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
GLfloat *pfIndex = (__GLfloat*)(gc->apIndex.pointer + vx->iArray * gc->apIndex.ibytes);
|
|
|
|
vx->colors[__GL_FRONTFACE].r = pfIndex[0];
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyCalcCILight(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
__GLlightSourceMachine *lsm;
|
|
__GLfloat s, d, ci;
|
|
|
|
/* Compute the color */
|
|
s = __glZero;
|
|
d = __glZero;
|
|
|
|
lsm = gc->light.sources;
|
|
if (lsm != NULL) {
|
|
MyCalcNormal(gc, &vx->normal, (__GLfloat*)(gc->apNormal.pointer + vx->iArray * gc->apNormal.ibytes));
|
|
|
|
do {
|
|
__GLfloat n1, n2;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = vx->normal.x * lsm->unitVPpli.x + vx->normal.y * lsm->unitVPpli.y + vx->normal.z * lsm->unitVPpli.z;
|
|
if (n1 > __glZero) {
|
|
n2 = vx->normal.x * lsm->hHat.x + vx->normal.y * lsm->hHat.y + vx->normal.z * lsm->hHat.z;
|
|
n2 -= gc->light.front.threshold;
|
|
if (n2 >= __glZero) {
|
|
__GLfloat fx = n2 * gc->light.front.scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE ) {
|
|
n2 = gc->light.front.specTable[(GLint)fx];
|
|
} else {
|
|
n2 = __glOne;
|
|
}
|
|
|
|
s += n2 * lsm->sli;
|
|
}
|
|
d += n1 * lsm->dli;
|
|
}
|
|
lsm = lsm->next;
|
|
} while (lsm);
|
|
}
|
|
|
|
if (s > __glOne) {
|
|
s = __glOne;
|
|
}
|
|
ci = gc->state.light.front.cmapa
|
|
+ (__glOne - s) * d * (gc->state.light.front.cmapd - gc->state.light.front.cmapa)
|
|
+ s * (gc->state.light.front.cmaps - gc->state.light.front.cmapa);
|
|
if (ci > gc->state.light.front.cmaps) {
|
|
ci = gc->state.light.front.cmaps;
|
|
}
|
|
vx->colors[__GL_FRONTFACE].r = ci;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyCalcRGB(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
vx->colors[__GL_FRONTFACE] = gc->state.current.color;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyCalcRGBArray(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
GLfloat *pfColor = (__GLfloat*)(gc->apColor.pointer + vx->iArray * gc->apColor.ibytes);
|
|
|
|
if (pfColor[0] <= __glZero) {
|
|
vx->colors[__GL_FRONTFACE].r = __glZero;
|
|
} else if (pfColor[0] >= __glOne) {
|
|
vx->colors[__GL_FRONTFACE].r = gc->redVertexScale;
|
|
} else {
|
|
vx->colors[__GL_FRONTFACE].r = pfColor[0] * gc->redVertexScale;
|
|
}
|
|
|
|
if (pfColor[1] <= __glZero) {
|
|
vx->colors[__GL_FRONTFACE].g = __glZero;
|
|
} else if (pfColor[1] >= __glOne) {
|
|
vx->colors[__GL_FRONTFACE].g = gc->greenVertexScale;
|
|
} else {
|
|
vx->colors[__GL_FRONTFACE].g = pfColor[1] * gc->greenVertexScale;
|
|
}
|
|
|
|
if (pfColor[2] <= __glZero) {
|
|
vx->colors[__GL_FRONTFACE].b = __glZero;
|
|
} else if (pfColor[1] >= __glOne) {
|
|
vx->colors[__GL_FRONTFACE].b = gc->blueVertexScale;
|
|
} else {
|
|
vx->colors[__GL_FRONTFACE].b = pfColor[2] * gc->blueVertexScale;
|
|
}
|
|
|
|
vx->colors[__GL_FRONTFACE].a = gc->state.current.color.a;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL ClampColor(__GLcontext *gc, __GLcolor *color)
|
|
{
|
|
if (color->r <= __glZero) {
|
|
color->r = __glZero;
|
|
} else {
|
|
if (color->r >= gc->redVertexScale) {
|
|
color->r = gc->redVertexScale;
|
|
}
|
|
}
|
|
if (color->g <= __glZero) {
|
|
color->g = __glZero;
|
|
} else {
|
|
if (color->g >= gc->greenVertexScale) {
|
|
color->g = gc->greenVertexScale;
|
|
}
|
|
}
|
|
if (color->b <= __glZero) {
|
|
color->b = __glZero;
|
|
} else {
|
|
if (color->b >= gc->blueVertexScale) {
|
|
color->b = gc->blueVertexScale;
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL AddRGBLights(__GLcontext *gc, __GLcoord *normal, __GLcolor *color)
|
|
{
|
|
__GLlightSourceMachine *lsm = gc->light.sources;
|
|
|
|
do {
|
|
__GLfloat n1, n2;
|
|
|
|
color->r += lsm->front.ambient.r;
|
|
color->g += lsm->front.ambient.g;
|
|
color->b += lsm->front.ambient.b;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = normal->x * lsm->unitVPpli.x + normal->y * lsm->unitVPpli.y + normal->z * lsm->unitVPpli.z;
|
|
if (n1 > __glZero) {
|
|
n2 = normal->x * lsm->hHat.x + normal->y * lsm->hHat.y + normal->z * lsm->hHat.z;
|
|
n2 -= gc->light.front.threshold;
|
|
if (n2 >= __glZero) {
|
|
__GLfloat fx = n2 * gc->light.front.scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE ) {
|
|
n2 = gc->light.front.specTable[(GLint)fx];
|
|
} else {
|
|
n2 = __glOne;
|
|
}
|
|
|
|
color->r += n2 * lsm->front.specular.r;
|
|
color->g += n2 * lsm->front.specular.g;
|
|
color->b += n2 * lsm->front.specular.b;
|
|
}
|
|
color->r += n1 * lsm->front.diffuse.r;
|
|
color->g += n1 * lsm->front.diffuse.g;
|
|
color->b += n1 * lsm->front.diffuse.b;
|
|
}
|
|
lsm = lsm->next;
|
|
} while (lsm);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL ComputeRGBLightColor( __GLcontext *gc,
|
|
__GLfloat *normal, __GLcolor *color )
|
|
{
|
|
color->r = gc->light.front.sceneColor.r;
|
|
color->g = gc->light.front.sceneColor.g;
|
|
color->b = gc->light.front.sceneColor.b;
|
|
|
|
if (gc->light.sources != NULL) {
|
|
__GLcoord tnormal; // transformed normal
|
|
|
|
MyCalcNormal(gc, &tnormal, normal );
|
|
AddRGBLights( gc, &tnormal, color );
|
|
}
|
|
|
|
/* Clamp the computed color */
|
|
|
|
ClampColor( gc, color );
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyCalcRGBLight(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
__GLcolor color;
|
|
|
|
if( gc->ac.bComputeColor ) {
|
|
ComputeRGBLightColor( gc,
|
|
(__GLfloat*)(gc->apNormal.pointer + vx->iArray * gc->apNormal.ibytes),
|
|
&color );
|
|
vx->colors[__GL_FRONTFACE] = color; // mf: ~copies extra float (alpha)
|
|
} else {
|
|
// use precomputed color
|
|
vx->colors[__GL_FRONTFACE] = gc->ac.color;
|
|
}
|
|
vx->colors[__GL_FRONTFACE].a = gc->light.front.alpha;
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
// Add Color Material RGB Lights
|
|
|
|
void FASTCALL AddCMRGBLights(
|
|
__GLcontext *gc,
|
|
__GLcoord *normal,
|
|
__GLcolor *color,
|
|
__GLcolor *mcolor)
|
|
{
|
|
__GLlightSourceMachine *lsm = gc->light.sources;
|
|
|
|
do {
|
|
__GLfloat n1, n2;
|
|
|
|
mcolor->r += lsm->state->ambient.r;
|
|
mcolor->g += lsm->state->ambient.g;
|
|
mcolor->b += lsm->state->ambient.b;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = normal->x * lsm->unitVPpli.x + normal->y * lsm->unitVPpli.y + normal->z * lsm->unitVPpli.z;
|
|
if (n1 > __glZero) {
|
|
n2 = normal->x * lsm->hHat.x + normal->y * lsm->hHat.y + normal->z * lsm->hHat.z;
|
|
n2 -= gc->light.front.threshold;
|
|
if (n2 >= __glZero) {
|
|
__GLfloat fx = n2 * gc->light.front.scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE ) {
|
|
n2 = gc->light.front.specTable[(GLint)fx];
|
|
} else {
|
|
n2 = __glOne;
|
|
}
|
|
|
|
color->r += n2 * lsm->front.specular.r;
|
|
color->g += n2 * lsm->front.specular.g;
|
|
color->b += n2 * lsm->front.specular.b;
|
|
}
|
|
mcolor->r += n1 * lsm->state->diffuse.r;
|
|
mcolor->g += n1 * lsm->state->diffuse.g;
|
|
mcolor->b += n1 * lsm->state->diffuse.b;
|
|
}
|
|
lsm = lsm->next;
|
|
} while (lsm);
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL ComputeCMRGBLightColor(
|
|
__GLcontext *gc,
|
|
__GLfloat *normal,
|
|
__GLcolor *color,
|
|
__GLcolor *mcolor )
|
|
{
|
|
color->r = gc->state.light.front.emissive.r;
|
|
color->g = gc->state.light.front.emissive.g;
|
|
color->b = gc->state.light.front.emissive.b;
|
|
|
|
mcolor->r = gc->state.light.model.ambient.r;
|
|
mcolor->g = gc->state.light.model.ambient.g;
|
|
mcolor->b = gc->state.light.model.ambient.b;
|
|
|
|
if (gc->light.sources != NULL) {
|
|
__GLcoord tnormal;
|
|
|
|
MyCalcNormal(gc, &tnormal, normal );
|
|
AddCMRGBLights( gc, &tnormal, color, mcolor );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void FASTCALL MyCalcRGBLightArray(__GLcontext *gc, __GLvertex *vx)
|
|
{
|
|
__GLcolor color, mcolor;
|
|
|
|
if( gc->ac.bComputeColor ) {
|
|
ComputeCMRGBLightColor( gc,
|
|
(__GLfloat*)(gc->apNormal.pointer + vx->iArray * gc->apNormal.ibytes),
|
|
&color,
|
|
&mcolor );
|
|
} else { // use precalculated values
|
|
color = gc->ac.color;
|
|
mcolor = gc->ac.mcolor;
|
|
}
|
|
|
|
/* Clamp the computed color */
|
|
|
|
{
|
|
GLfloat *pfColor = (__GLfloat*)(gc->apColor.pointer + vx->iArray * gc->apColor.ibytes);
|
|
|
|
color.r += mcolor.r * pfColor[0];
|
|
color.g += mcolor.g * pfColor[1];
|
|
color.b += mcolor.b * pfColor[2];
|
|
}
|
|
|
|
ClampColor( gc, &color );
|
|
|
|
vx->colors[__GL_FRONTFACE].r = color.r;
|
|
vx->colors[__GL_FRONTFACE].g = color.g;
|
|
vx->colors[__GL_FRONTFACE].b = color.b;
|
|
vx->colors[__GL_FRONTFACE].a = gc->light.front.alpha;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast DrawArray Triangle functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
void MyRenderClippedTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c)
|
|
{
|
|
GLint ccw, reversed;
|
|
|
|
/*
|
|
** Sort vertices in y. Keep track if a reversal of the winding
|
|
** occurs in direction (0 means no reversal, 1 means reversal).
|
|
** Save old vertex pointers in case we end up not doing a fill.
|
|
*/
|
|
|
|
if (a->window.y < b->window.y) {
|
|
if (b->window.y < c->window.y) {
|
|
/* Already sorted */
|
|
reversed = 0;
|
|
} else {
|
|
if (a->window.y < c->window.y) {
|
|
__GLvertex *temp;
|
|
|
|
temp=b; b=c; c=temp;
|
|
reversed = 1;
|
|
} else {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=c; c=b; b=temp;
|
|
reversed = 0;
|
|
}
|
|
}
|
|
} else {
|
|
if (b->window.y < c->window.y) {
|
|
if (a->window.y < c->window.y) {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=b; b=temp;
|
|
reversed = 1;
|
|
} else {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=b; b=c; c=temp;
|
|
reversed = 0;
|
|
}
|
|
} else {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=c; c=temp;
|
|
reversed = 1;
|
|
}
|
|
}
|
|
|
|
/* Compute signed area of the triangle */
|
|
|
|
gc->polygon.shader.dxAC = a->window.x - c->window.x;
|
|
gc->polygon.shader.dxBC = b->window.x - c->window.x;
|
|
gc->polygon.shader.dyAC = a->window.y - c->window.y;
|
|
gc->polygon.shader.dyBC = b->window.y - c->window.y;
|
|
|
|
gc->polygon.shader.area = gc->polygon.shader.dxAC * gc->polygon.shader.dyBC - gc->polygon.shader.dxBC * gc->polygon.shader.dyAC;
|
|
if (gc->polygon.shader.area == __glZero) {
|
|
return;
|
|
}
|
|
ccw = gc->polygon.shader.area >= __glZero;
|
|
|
|
/* is the triangle culled? */
|
|
|
|
if (gc->polygon.face[ccw ^ reversed] == gc->polygon.cullFace) {
|
|
return;
|
|
}
|
|
|
|
/* validate the vertices */
|
|
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_SMOOTH_LIGHT) {
|
|
if (a->has == 0) {
|
|
a->has = 1;
|
|
gc->ad.pfnCalcColor(gc, a);
|
|
MyCalcClipCode(gc, a);
|
|
}
|
|
if (b->has == 0) {
|
|
b->has = 1;
|
|
gc->ad.pfnCalcColor(gc, b);
|
|
MyCalcClipCode(gc, b);
|
|
}
|
|
if (c->has == 0) {
|
|
c->has = 1;
|
|
gc->ad.pfnCalcColor(gc, c);
|
|
MyCalcClipCode(gc, c);
|
|
}
|
|
} else {
|
|
if (gc->vertex.provoking->has == 0) {
|
|
gc->ad.pfnCalcColor(gc, gc->vertex.provoking);
|
|
}
|
|
if (a->has == 0) {
|
|
a->has = 1;
|
|
MyCalcClipCode(gc, a);
|
|
}
|
|
if (b->has == 0) {
|
|
b->has = 1;
|
|
MyCalcClipCode(gc, b);
|
|
}
|
|
if (c->has == 0) {
|
|
c->has = 1;
|
|
MyCalcClipCode(gc, c);
|
|
}
|
|
}
|
|
|
|
/* see if triangle is cliped otherwise fill it */
|
|
{
|
|
/* Clip check */
|
|
GLuint orCodes = a->clipCode | b->clipCode | c->clipCode;
|
|
if (orCodes) {
|
|
/* Some kind of clipping is needed */
|
|
if (a->clipCode & b->clipCode & c->clipCode) {
|
|
/* Trivially reject the triangle */
|
|
} else {
|
|
GLuint needs = gc->vertex.needs | gc->vertex.faceNeeds[__GL_FRONTFACE];
|
|
|
|
a->has = needs;
|
|
b->has = needs;
|
|
c->has = needs;
|
|
|
|
/* Clip the triangle */
|
|
if (reversed) {
|
|
(*gc->procs.clipTriangle)(gc, a, c, b, orCodes);
|
|
} else {
|
|
(*gc->procs.clipTriangle)(gc, a, b, c, orCodes);
|
|
}
|
|
}
|
|
} else {
|
|
/* Fill the triangle */
|
|
(*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
void MyRenderTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c)
|
|
{
|
|
GLint ccw, reversed;
|
|
|
|
/*
|
|
** Sort vertices in y. Keep track if a reversal of the winding
|
|
** occurs in direction (0 means no reversal, 1 means reversal).
|
|
** Save old vertex pointers in case we end up not doing a fill.
|
|
*/
|
|
|
|
if (a->window.y < b->window.y) {
|
|
if (b->window.y < c->window.y) {
|
|
/* Already sorted */
|
|
reversed = 0;
|
|
} else {
|
|
if (a->window.y < c->window.y) {
|
|
__GLvertex *temp;
|
|
|
|
temp=b; b=c; c=temp;
|
|
reversed = 1;
|
|
} else {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=c; c=b; b=temp;
|
|
reversed = 0;
|
|
}
|
|
}
|
|
} else {
|
|
if (b->window.y < c->window.y) {
|
|
if (a->window.y < c->window.y) {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=b; b=temp;
|
|
reversed = 1;
|
|
} else {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=b; b=c; c=temp;
|
|
reversed = 0;
|
|
}
|
|
} else {
|
|
__GLvertex *temp;
|
|
|
|
temp=a; a=c; c=temp;
|
|
reversed = 1;
|
|
}
|
|
}
|
|
|
|
/* Compute signed area of the triangle */
|
|
|
|
gc->polygon.shader.dxAC = a->window.x - c->window.x;
|
|
gc->polygon.shader.dxBC = b->window.x - c->window.x;
|
|
gc->polygon.shader.dyAC = a->window.y - c->window.y;
|
|
gc->polygon.shader.dyBC = b->window.y - c->window.y;
|
|
|
|
gc->polygon.shader.area = gc->polygon.shader.dxAC * gc->polygon.shader.dyBC - gc->polygon.shader.dxBC * gc->polygon.shader.dyAC;
|
|
if (gc->polygon.shader.area == __glZero) {
|
|
return;
|
|
}
|
|
ccw = gc->polygon.shader.area >= __glZero;
|
|
|
|
/* is the triangle culled? */
|
|
|
|
if (gc->polygon.face[ccw ^ reversed] == gc->polygon.cullFace) {
|
|
return;
|
|
}
|
|
|
|
/* validate the vertices */
|
|
|
|
if (a->has == 0) {
|
|
a->has = 1;
|
|
gc->ad.pfnCalcColor(gc, a);
|
|
}
|
|
if (b->has == 0) {
|
|
b->has = 1;
|
|
gc->ad.pfnCalcColor(gc, b);
|
|
}
|
|
if (c->has == 0) {
|
|
c->has = 1;
|
|
gc->ad.pfnCalcColor(gc, c);
|
|
}
|
|
|
|
/* Fill the triangle */
|
|
(*gc->procs.fillTriangle)(gc, a, b, c, (GLboolean) ccw);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void MyRenderQuad(__GLcontext *gc, __GLvertex *v0, __GLvertex *v1, __GLvertex *v2, __GLvertex *v3)
|
|
{
|
|
GLuint orCodes = v0->clipCode | v1->clipCode | v2->clipCode | v3->clipCode;
|
|
|
|
if (orCodes) {
|
|
if (v0->clipCode & v1->clipCode & v2->clipCode & v3->clipCode) {
|
|
/* Trivially reject the quad */
|
|
} else {
|
|
/* Clip the quad as a polygon */
|
|
__GLvertex *iv[4];
|
|
GLuint needs = gc->vertex.needs | gc->vertex.faceNeeds[__GL_FRONTFACE];
|
|
|
|
if (v0->has == 0) gc->ad.pfnCalcColor(gc, v0);
|
|
if (v1->has == 0) gc->ad.pfnCalcColor(gc, v1);
|
|
if (v2->has == 0) gc->ad.pfnCalcColor(gc, v2);
|
|
if (v3->has == 0) gc->ad.pfnCalcColor(gc, v3);
|
|
|
|
v0->has = needs;
|
|
v1->has = needs;
|
|
v2->has = needs;
|
|
v3->has = needs;
|
|
|
|
iv[0] = v0;
|
|
iv[1] = v1;
|
|
iv[2] = v2;
|
|
iv[3] = v3;
|
|
__glDoPolygonClip(gc, &iv[0], 4, orCodes);
|
|
}
|
|
} else {
|
|
/* Render the quad as two triangles */
|
|
GLboolean saveTag;
|
|
saveTag = v1->boundaryEdge;
|
|
v1->boundaryEdge = GL_FALSE;
|
|
MyRenderTriangle(gc, v3, v0, v1);
|
|
v1->boundaryEdge = saveTag;
|
|
saveTag = v3->boundaryEdge;
|
|
v3->boundaryEdge = GL_FALSE;
|
|
MyRenderTriangle(gc, v3, v1, v2);
|
|
v3->boundaryEdge = saveTag;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast ElementArray primitive functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
void FASTCALL ArrayElementDrawTriangles(
|
|
__GLcontext *gc,
|
|
GLsizei count,
|
|
GLint* pindex)
|
|
{
|
|
GLint first = 0;
|
|
|
|
#define v0 (&gc->vertex.vbuf[0])
|
|
#define v1 (&gc->vertex.vbuf[1])
|
|
#define v2 (&gc->vertex.vbuf[2])
|
|
|
|
v0->boundaryEdge = gc->state.current.edgeTag;
|
|
v1->boundaryEdge = gc->state.current.edgeTag;
|
|
v2->boundaryEdge = gc->state.current.edgeTag;
|
|
|
|
gc->vertex.provoking = v2;
|
|
|
|
count -= 2;
|
|
while (first < count) {
|
|
|
|
ArrayStoreVertex(gc, v0, pindex[first + 0]);
|
|
ArrayStoreVertex(gc, v1, pindex[first + 1]);
|
|
ArrayStoreVertex(gc, v2, pindex[first + 2]);
|
|
MyRenderClippedTriangle(gc, v0, v1, v2);
|
|
first += 3;
|
|
}
|
|
#undef v0
|
|
#undef v1
|
|
#undef v2
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayElementDrawTStrip(
|
|
__GLcontext *gc,
|
|
GLsizei count,
|
|
GLint* pindex)
|
|
{
|
|
GLint first = 0;
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
|
|
if (count < 3) return;
|
|
|
|
ArrayStoreVertex(gc, v0, pindex[first + 0]);
|
|
ArrayStoreVertex(gc, v1, pindex[first + 1]);
|
|
|
|
v0->boundaryEdge = GL_TRUE;
|
|
v1->boundaryEdge = GL_TRUE;
|
|
v2->boundaryEdge = GL_TRUE;
|
|
gc->vertex.provoking = v2;
|
|
|
|
first += 2;
|
|
while (first < count) {
|
|
|
|
ArrayStoreVertex(gc, v2, pindex[first]);
|
|
gc->vertex.provoking = v2;
|
|
MyRenderClippedTriangle(gc, v0, v1, v2);
|
|
first++;
|
|
|
|
if (first >= count) break;
|
|
|
|
ArrayStoreVertex(gc, v0, pindex[first]);
|
|
gc->vertex.provoking = v0;
|
|
MyRenderClippedTriangle(gc, v0, v2, v1);
|
|
first++;
|
|
|
|
{
|
|
__GLvertex *vt;
|
|
vt = v0;
|
|
v0 = v2;
|
|
v2 = v1;
|
|
v1 = vt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayElementDrawTFan(
|
|
__GLcontext *gc,
|
|
GLsizei count,
|
|
GLint* pindex)
|
|
{
|
|
GLint first = 0;
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
|
|
if (count < 3) return;
|
|
|
|
ArrayStoreVertex(gc, v0, pindex[first + 0]);
|
|
ArrayStoreVertex(gc, v1, pindex[first + 1]);
|
|
|
|
v0->boundaryEdge = GL_TRUE;
|
|
v1->boundaryEdge = GL_TRUE;
|
|
v2->boundaryEdge = GL_TRUE;
|
|
|
|
first += 2;
|
|
while (first < count) {
|
|
ArrayStoreVertex(gc, v2, pindex[first]);
|
|
gc->vertex.provoking = v2;
|
|
MyRenderClippedTriangle(gc, v0, v1, v2);
|
|
first++;
|
|
|
|
{
|
|
__GLvertex *vt;
|
|
vt = v1;
|
|
v1 = v2;
|
|
v2 = vt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayElementDrawQStrip(
|
|
__GLcontext *gc,
|
|
GLsizei count,
|
|
GLint* pindex)
|
|
{
|
|
GLint first = 0;
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
__GLvertex *v3 = &gc->vertex.vbuf[3];
|
|
|
|
if (count < 4) return;
|
|
|
|
ArrayStoreVertex(gc, v0, pindex[first + 0]);
|
|
ArrayStoreVertex(gc, v1, pindex[first + 1]);
|
|
MyCalcClipCode(gc, v0);
|
|
MyCalcClipCode(gc, v1);
|
|
|
|
v0->boundaryEdge = GL_TRUE;
|
|
v1->boundaryEdge = GL_TRUE;
|
|
v2->boundaryEdge = GL_TRUE;
|
|
v3->boundaryEdge = GL_TRUE;
|
|
|
|
count -= 1;
|
|
first += 2;
|
|
while (first < count) {
|
|
|
|
ArrayStoreVertex(gc, v2, pindex[first]);
|
|
ArrayStoreVertex(gc, v3, pindex[first + 1]);
|
|
first += 2;
|
|
MyCalcClipCode(gc, v2);
|
|
MyCalcClipCode(gc, v3);
|
|
|
|
gc->vertex.provoking = v3;
|
|
|
|
MyRenderQuad(gc, v0, v1, v3, v2);
|
|
|
|
{
|
|
__GLvertex *vt;
|
|
vt = v0;
|
|
v0 = v2;
|
|
v2 = vt;
|
|
|
|
vt = v1;
|
|
v1 = v3;
|
|
v3 = vt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayElementDrawQuads(
|
|
__GLcontext *gc,
|
|
GLsizei count,
|
|
GLint* pindex)
|
|
{
|
|
GLint first = 0;
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
__GLvertex *v3 = &gc->vertex.vbuf[3];
|
|
|
|
count -= 3;
|
|
while (first < count) {
|
|
ArrayStoreVertex(gc, v0, pindex[first + 0]);
|
|
ArrayStoreVertex(gc, v1, pindex[first + 1]);
|
|
ArrayStoreVertex(gc, v2, pindex[first + 2]);
|
|
ArrayStoreVertex(gc, v3, pindex[first + 3]);
|
|
MyCalcClipCode(gc, v0);
|
|
MyCalcClipCode(gc, v1);
|
|
MyCalcClipCode(gc, v2);
|
|
MyCalcClipCode(gc, v3);
|
|
|
|
#ifdef LATER
|
|
InlineArrayStoreEdgeFlag(gc, v0, pindex[first + 0]);
|
|
InlineArrayStoreEdgeFlag(gc, v1, pindex[first + 1]);
|
|
InlineArrayStoreEdgeFlag(gc, v2, pindex[first + 2]);
|
|
InlineArrayStoreEdgeFlag(gc, v3, pindex[first + 3]);
|
|
#endif
|
|
|
|
first += 4;
|
|
|
|
gc->vertex.provoking = v3;
|
|
MyRenderQuad(gc, v0, v1, v2, v3);
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast DrawArray primitive functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
void FASTCALL ArrayDrawTriangles(
|
|
__GLcontext *gc,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
#define v0 (&gc->vertex.vbuf[0])
|
|
#define v1 (&gc->vertex.vbuf[1])
|
|
#define v2 (&gc->vertex.vbuf[2])
|
|
|
|
v0->boundaryEdge = gc->state.current.edgeTag;
|
|
v1->boundaryEdge = gc->state.current.edgeTag;
|
|
v2->boundaryEdge = gc->state.current.edgeTag;
|
|
|
|
gc->vertex.provoking = v2;
|
|
|
|
count += first - 2;
|
|
while (first < count) {
|
|
|
|
ArrayStoreVertex(gc, v0, first + 0);
|
|
ArrayStoreVertex(gc, v1, first + 1);
|
|
ArrayStoreVertex(gc, v2, first + 2);
|
|
MyRenderClippedTriangle(gc, v0, v1, v2);
|
|
first += 3;
|
|
}
|
|
#undef v0
|
|
#undef v1
|
|
#undef v2
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayDrawTStrip(
|
|
__GLcontext *gc,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
|
|
if (count < 3) return;
|
|
|
|
ArrayStoreVertex(gc, v0, first + 0);
|
|
ArrayStoreVertex(gc, v1, first + 1);
|
|
|
|
v0->boundaryEdge = GL_TRUE;
|
|
v1->boundaryEdge = GL_TRUE;
|
|
v2->boundaryEdge = GL_TRUE;
|
|
gc->vertex.provoking = v2;
|
|
|
|
count += first;
|
|
first += 2;
|
|
while (first < count) {
|
|
|
|
ArrayStoreVertex(gc, v2, first);
|
|
gc->vertex.provoking = v2;
|
|
MyRenderClippedTriangle(gc, v0, v1, v2);
|
|
first++;
|
|
|
|
if (first >= count) break;
|
|
|
|
ArrayStoreVertex(gc, v0, first);
|
|
gc->vertex.provoking = v0;
|
|
MyRenderClippedTriangle(gc, v0, v2, v1);
|
|
first++;
|
|
|
|
{
|
|
__GLvertex *vt;
|
|
vt = v0;
|
|
v0 = v2;
|
|
v2 = v1;
|
|
v1 = vt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayDrawTFan(
|
|
__GLcontext *gc,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
|
|
if (count < 3) return;
|
|
|
|
ArrayStoreVertex(gc, v0, first + 0);
|
|
ArrayStoreVertex(gc, v1, first + 1);
|
|
|
|
v0->boundaryEdge = GL_TRUE;
|
|
v1->boundaryEdge = GL_TRUE;
|
|
v2->boundaryEdge = GL_TRUE;
|
|
|
|
count += first;
|
|
first += 2;
|
|
while (first < count) {
|
|
ArrayStoreVertex(gc, v2, first);
|
|
gc->vertex.provoking = v2;
|
|
MyRenderClippedTriangle(gc, v0, v1, v2);
|
|
first++;
|
|
|
|
{
|
|
__GLvertex *vt;
|
|
vt = v1;
|
|
v1 = v2;
|
|
v2 = vt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayDrawQStrip(
|
|
__GLcontext *gc,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
__GLvertex *v3 = &gc->vertex.vbuf[3];
|
|
|
|
if (count < 4) return;
|
|
|
|
ArrayStoreVertex(gc, v0, first + 0);
|
|
ArrayStoreVertex(gc, v1, first + 1);
|
|
MyCalcClipCode(gc, v0);
|
|
MyCalcClipCode(gc, v1);
|
|
|
|
v0->boundaryEdge = GL_TRUE;
|
|
v1->boundaryEdge = GL_TRUE;
|
|
v2->boundaryEdge = GL_TRUE;
|
|
v3->boundaryEdge = GL_TRUE;
|
|
|
|
count += first - 1;
|
|
first += 2;
|
|
while (first < count) {
|
|
|
|
ArrayStoreVertex(gc, v2, first);
|
|
ArrayStoreVertex(gc, v3, first + 1);
|
|
first += 2;
|
|
|
|
MyCalcClipCode(gc, v2);
|
|
MyCalcClipCode(gc, v3);
|
|
|
|
gc->vertex.provoking = v3;
|
|
|
|
MyRenderQuad(gc, v0, v1, v3, v2);
|
|
|
|
{
|
|
__GLvertex *vt;
|
|
vt = v0;
|
|
v0 = v2;
|
|
v2 = vt;
|
|
|
|
vt = v1;
|
|
v1 = v3;
|
|
v3 = vt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL ArrayDrawQuads(
|
|
__GLcontext *gc,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
__GLvertex *v0 = &gc->vertex.vbuf[0];
|
|
__GLvertex *v1 = &gc->vertex.vbuf[1];
|
|
__GLvertex *v2 = &gc->vertex.vbuf[2];
|
|
__GLvertex *v3 = &gc->vertex.vbuf[3];
|
|
|
|
count += first - 3;
|
|
while (first < count) {
|
|
ArrayStoreVertex(gc, v0, first + 0);
|
|
ArrayStoreVertex(gc, v1, first + 1);
|
|
ArrayStoreVertex(gc, v2, first + 2);
|
|
ArrayStoreVertex(gc, v3, first + 3);
|
|
MyCalcClipCode(gc, v0);
|
|
MyCalcClipCode(gc, v1);
|
|
MyCalcClipCode(gc, v2);
|
|
MyCalcClipCode(gc, v3);
|
|
|
|
#ifdef LATER
|
|
InlineArrayStoreEdgeFlag(gc, v0, first + 0);
|
|
InlineArrayStoreEdgeFlag(gc, v1, first + 1);
|
|
InlineArrayStoreEdgeFlag(gc, v2, first + 2);
|
|
InlineArrayStoreEdgeFlag(gc, v3, first + 3);
|
|
#endif
|
|
|
|
first += 4;
|
|
|
|
gc->vertex.provoking = v3;
|
|
MyRenderQuad(gc, v0, v1, v2, v3);
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// 3dddi macros
|
|
//
|
|
//***************************************************************************
|
|
|
|
#define BATCHED_DRV_STATE(state, value)\
|
|
{\
|
|
RXSETSTATE *ddiCmd;\
|
|
\
|
|
ddiCmd = (RXSETSTATE *)(pDrvAccel->pCmd);\
|
|
\
|
|
ddiCmd->command = RXCMD_SET_STATE;\
|
|
ddiCmd->stateToChange = state;\
|
|
ddiCmd->newState[0] = value;\
|
|
pDrvAccel->pCmd += sizeof(RXSETSTATE);\
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast 3dddi DrawArray lighting functions
|
|
//
|
|
//***************************************************************************
|
|
|
|
#ifdef LATER
|
|
// don't support 3dddi color index yet
|
|
void FASTCALL Calc3dddiCI(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
prxVertex->color.r = (char)(gc->state.current.userColorIndex * pGenAccel->rAccelPrimScale);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL Calc3dddiCIArray(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
prxVertex->color.r = (char)(pfColor[0] * pGenAccel->rAccelPrimScale);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL Calc3dddiCILight(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
__GLlightSourceMachine *lsm;
|
|
__GLfloat s, d, ci;
|
|
|
|
/* Compute the color */
|
|
s = __glZero;
|
|
d = __glZero;
|
|
|
|
lsm = gc->light.sources;
|
|
if (lsm != NULL) {
|
|
__GLcoord normal;
|
|
MyCalcNormal(gc, &normal, pfNormal);
|
|
|
|
do {
|
|
__GLfloat n1, n2;
|
|
|
|
/* Add in specular and diffuse effect of light, if any */
|
|
n1 = normal.x * lsm->unitVPpli.x + normal.y * lsm->unitVPpli.y + normal.z * lsm->unitVPpli.z;
|
|
if (n1 > __glZero) {
|
|
n2 = normal.x * lsm->hHat.x + normal.y * lsm->hHat.y + normal.z * lsm->hHat.z;
|
|
n2 -= gc->light.front.threshold;
|
|
if (n2 >= __glZero) {
|
|
__GLfloat fx = n2 * gc->light.front.scale + __glHalf;
|
|
|
|
if( fx < (__GLfloat)__GL_SPEC_LOOKUP_TABLE_SIZE ) {
|
|
n2 = gc->light.front.specTable[(GLint)fx];
|
|
} else {
|
|
n2 = __glOne;
|
|
}
|
|
|
|
s += n2 * lsm->sli;
|
|
}
|
|
d += n1 * lsm->dli;
|
|
}
|
|
lsm = lsm->next;
|
|
} while (lsm);
|
|
}
|
|
|
|
if (s > __glOne) {
|
|
s = __glOne;
|
|
}
|
|
ci = gc->state.light.front.cmapa
|
|
+ (__glOne - s) * d * (gc->state.light.front.cmapd - gc->state.light.front.cmapa)
|
|
+ s * (gc->state.light.front.cmaps - gc->state.light.front.cmapa);
|
|
if (ci > gc->state.light.front.cmaps) {
|
|
ci = gc->state.light.front.cmaps;
|
|
}
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
prxVertex->color.r = (char)(ci * pGenAccel->rAccelPrimScale);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL Calc3dddiRGB(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
#ifdef RXENABLED
|
|
prxVertex->color.r = (char)(gc->state.current.color.r * pGenAccel->rAccelPrimScale);
|
|
prxVertex->color.g = (char)(gc->state.current.color.g * pGenAccel->gAccelPrimScale);
|
|
prxVertex->color.b = (char)(gc->state.current.color.b * pGenAccel->bAccelPrimScale);
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL Calc3dddiRGBArray(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
#ifdef RXENABLED
|
|
if (pfColor[0] <= __glZero) {
|
|
prxVertex->color.r = 0;
|
|
} else if (pfColor[0] >= __glOne) {
|
|
prxVertex->color.r = (char)(gc->redVertexScale * pGenAccel->rAccelPrimScale);
|
|
} else {
|
|
prxVertex->color.r = (char)(pfColor[0] * gc->redVertexScale * pGenAccel->rAccelPrimScale);
|
|
}
|
|
|
|
if (pfColor[1] <= __glZero) {
|
|
prxVertex->color.g = 0;
|
|
} else if (pfColor[1] >= __glOne) {
|
|
prxVertex->color.g = (char)(gc->greenVertexScale * pGenAccel->gAccelPrimScale);
|
|
} else {
|
|
prxVertex->color.g = (char)(pfColor[1] * gc->greenVertexScale * pGenAccel->gAccelPrimScale);
|
|
}
|
|
|
|
if (pfColor[2] <= __glZero) {
|
|
prxVertex->color.b = 0;
|
|
} else if (pfColor[1] >= __glOne) {
|
|
prxVertex->color.b = (char)(gc->blueVertexScale * pGenAccel->bAccelPrimScale);
|
|
} else {
|
|
prxVertex->color.b = (char)(pfColor[2] * gc->blueVertexScale * pGenAccel->bAccelPrimScale);
|
|
}
|
|
|
|
//prxVertex->color.a = (char)gc->state.current.color.a;
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL Calc3dddiRGBLight(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
__GLcolor color;
|
|
|
|
if( gc->ac.bComputeColor )
|
|
ComputeRGBLightColor( gc, pfNormal, &color );
|
|
else
|
|
// use precomputed color
|
|
color = gc->ac.color;
|
|
#ifdef RXENABLED
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
prxVertex->color.r = (char)(color.r * pGenAccel->rAccelPrimScale);
|
|
prxVertex->color.g = (char)(color.g * pGenAccel->gAccelPrimScale);
|
|
prxVertex->color.b = (char)(color.b * pGenAccel->bAccelPrimScale);
|
|
//!!! Should alpha be turned on at all times?
|
|
//prxVertex->color.a = gc->light.front.alpha;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL Calc3dddiRGBLightArray(__GLcontext *gc, GLfloat *pfNormal, GLfloat *pfColor, PRXVERTEX prxVertex)
|
|
{
|
|
__GLcolor color, mcolor;
|
|
|
|
if( gc->ac.bComputeColor ) {
|
|
ComputeCMRGBLightColor( gc, pfNormal, &color, &mcolor );
|
|
} else { // use precalculated values
|
|
color = gc->ac.color;
|
|
mcolor = gc->ac.mcolor;
|
|
}
|
|
|
|
/* Clamp the computed color */
|
|
|
|
color.r += mcolor.r * pfColor[0];
|
|
color.g += mcolor.g * pfColor[1];
|
|
color.b += mcolor.b * pfColor[2];
|
|
|
|
ClampColor( gc , &color );
|
|
#ifdef RXENABLED
|
|
|
|
{
|
|
GENACCEL *pGenAccel = (GENACCEL *)(((__GLGENcontext *)gc)->pPrivateArea);
|
|
prxVertex->color.r = (char)(color.r * pGenAccel->rAccelPrimScale);
|
|
prxVertex->color.g = (char)(color.g * pGenAccel->gAccelPrimScale);
|
|
prxVertex->color.b = (char)(color.b * pGenAccel->bAccelPrimScale);
|
|
//!!! Should alpha be turned on at all times?
|
|
//prxVertex->color.a = gc->light.front.alpha;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast 3dddi DrawArray tranformation and clipping function
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL FASTCALL Transform3dddiVertices(
|
|
__GLcontext *gc,
|
|
PRXVERTEX prxVertex,
|
|
GLfloat *pfVertex,
|
|
GLfloat *pfNormal,
|
|
GLfloat *pfColor,
|
|
GLint ibytesVertex,
|
|
GLint ibytesNormal,
|
|
GLint ibytesColor,
|
|
PFNCALC3DDDICOLOR pfn3dddiCalcColor,
|
|
const __GLmatrix *m,
|
|
GLsizei count)
|
|
{
|
|
// !!! make a version that only uses one array pointer
|
|
// !!! hint flag that doesn't do x,y clipping
|
|
// PVERTEXDATA pvd = this->pvd;
|
|
|
|
int i;
|
|
|
|
for (i = count; i > 0; i--) {
|
|
{
|
|
__GLfloat xt, yt, zt, wt;
|
|
{
|
|
__GLfloat x = pfVertex[0];
|
|
__GLfloat y = pfVertex[1];
|
|
__GLfloat z = pfVertex[2];
|
|
|
|
xt = x * m->matrix[0][0] + y * m->matrix[1][0] + z * m->matrix[2][0] + m->matrix[3][0];
|
|
yt = x * m->matrix[0][1] + y * m->matrix[1][1] + z * m->matrix[2][1] + m->matrix[3][1];
|
|
zt = x * m->matrix[0][2] + y * m->matrix[1][2] + z * m->matrix[2][2] + m->matrix[3][2];
|
|
wt = x * m->matrix[0][3] + y * m->matrix[1][3] + z * m->matrix[2][3] + m->matrix[3][3];
|
|
}
|
|
{
|
|
__GLfloat negW = -wt;
|
|
|
|
//
|
|
// If any of the vertices is clipped we are completely screwed since we're not keeping
|
|
// any global state. Return FALSE and we'll restart through the slower path that
|
|
// handles clipping.
|
|
//
|
|
|
|
if ( (xt > wt)
|
|
|| (yt > wt)
|
|
|| (zt > wt)
|
|
|| (xt < negW)
|
|
|| (yt < negW)
|
|
|| (zt < negW)
|
|
) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//prxVertex->point.w = wt;
|
|
|
|
if(wt != (__GLfloat) 0.0) {
|
|
wt = __glOne / wt;
|
|
}
|
|
|
|
#define FIXEDSCALE (0x10000)
|
|
#ifdef RXENABLED
|
|
prxVertex->point.x = (long)((xt * gc->state.viewport.xScale * wt + gc->state.viewport.xCenter - gc->constants.viewportXAdjust) * FIXEDSCALE);
|
|
prxVertex->point.y = (long)((yt * gc->state.viewport.yScale * wt + gc->state.viewport.yCenter - gc->constants.viewportYAdjust) * FIXEDSCALE);
|
|
prxVertex->point.z = (long)(zt * gc->state.viewport.zScale * wt + gc->state.viewport.zCenter);
|
|
#endif
|
|
//prxVertex->point.s = ;
|
|
//prxVertex->point.t = ;
|
|
}
|
|
|
|
pfn3dddiCalcColor(gc, pfNormal, pfColor, prxVertex);
|
|
|
|
pfVertex = (__GLfloat*)((char *)(pfVertex) + ibytesVertex);
|
|
pfNormal = (__GLfloat*)((char *)(pfNormal) + ibytesNormal);
|
|
pfColor = (__GLfloat*)((char *)(pfColor) + ibytesColor);
|
|
prxVertex++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Fast 3dddi DrawArray & ElementArray primitive function
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL FASTCALL Draw3dddiTriangles(
|
|
__GLcontext *gc,
|
|
GLenum mode,
|
|
GLint first,
|
|
GLsizei count,
|
|
GLint* pindex)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
GENDRVACCEL *pDrvAccel = gengc->pDrvAccel;
|
|
GLint vertexcount;
|
|
|
|
if (pindex != NULL) {
|
|
vertexcount = gc->apVertex.count;
|
|
} else {
|
|
vertexcount = count;
|
|
}
|
|
|
|
//
|
|
// Make sure we have enough memory.
|
|
//
|
|
#ifdef RXENABLED
|
|
|
|
{
|
|
GLint ibytes = sizeof(RXVERTEX) * vertexcount + sizeof(PRXVERTEX) * (count - 2) * 3;
|
|
if (ibytes > gc->arxm.ibytesRX) {
|
|
RXHDR *ddiHdr;
|
|
RXMAPMEM *ddiMapMemCmd;
|
|
|
|
if (gc->arxm.ibytesRX != 0) {
|
|
//
|
|
// Free the old RX buffer.
|
|
//
|
|
UnmapViewOfFile(gengc->gc.arxm.pdataRX);
|
|
CloseHandle(gengc->gc.arxm.hmemRX);
|
|
}
|
|
|
|
//
|
|
// Reallocate the rx buffer.
|
|
//
|
|
|
|
gengc->gc.arxm.hmemRX = CreateFileMapping(
|
|
(HANDLE)0xffffffff, NULL,
|
|
PAGE_READWRITE | SEC_COMMIT, 0,
|
|
ibytes, NULL);
|
|
|
|
if (gengc->gc.arxm.hmemRX == NULL) {
|
|
gc->arxm.ibytesRX = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
gengc->gc.arxm.pdataRX = MapViewOfFile(
|
|
gengc->gc.arxm.hmemRX,
|
|
FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
|
|
|
if (gengc->gc.arxm.pdataRX == NULL) {
|
|
CloseHandle(gengc->gc.arxm.hmemRX);
|
|
gc->arxm.ibytesRX = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
ddiHdr = (RXHDR *)(pDrvAccel->pCmd);
|
|
ddiHdr->hrxRC = NULL;
|
|
ddiHdr->hrxSharedMem = NULL;
|
|
ddiHdr->pSharedMem = (VOID *)NULL;
|
|
ddiHdr->flags = RX_FL_MAP_MEM;
|
|
|
|
ddiMapMemCmd = (RXMAPMEM *)(ddiHdr + 1);
|
|
ddiMapMemCmd->command = RXCMD_MAP_MEM;
|
|
ddiMapMemCmd->action = RX_CREATE_MEM_MAP;
|
|
ddiMapMemCmd->shareMem.sourceProcessID = GetCurrentProcessId();
|
|
ddiMapMemCmd->shareMem.hSource = gengc->gc.arxm.hmemRX;
|
|
ddiMapMemCmd->shareMem.offset = 0;
|
|
ddiMapMemCmd->shareMem.size = ibytes;
|
|
ddiMapMemCmd->shareMem.clientBaseAddress = (ULONG)gengc->gc.arxm.pdataRX;
|
|
|
|
gengc->gc.arxm.hddimem = (RXHANDLE)wgl3dDDIEscape(
|
|
gengc->CurrentDC, gengc->pwo,
|
|
sizeof(RXHDR) + sizeof(RXMAPMEM),
|
|
ddiHdr, 0, NULL);
|
|
|
|
if (gengc->gc.arxm.hddimem == NULL) {
|
|
UnmapViewOfFile(gengc->gc.arxm.pdataRX);
|
|
CloseHandle(gengc->gc.arxm.hmemRX);
|
|
gc->arxm.ibytesRX = 0;
|
|
return FALSE;
|
|
}
|
|
gengc->gc.arxm.ibytesRX = ibytes;
|
|
}
|
|
}
|
|
|
|
//
|
|
// fill in the RXVERTEX structures
|
|
//
|
|
|
|
if (Transform3dddiVertices(
|
|
gc,
|
|
(PRXVERTEX)(gengc->gc.arxm.pdataRX),
|
|
(__GLfloat*)(gengc->gc.apVertex.pointer + first * gengc->gc.apVertex.ibytes),
|
|
(__GLfloat*)(gengc->gc.apNormal.pointer + first * gengc->gc.apNormal.ibytes),
|
|
(gengc->gc.ad.dwArrayEnable & ENABLE_INDEXMODE)
|
|
? (__GLfloat*)(gengc->gc.apIndex.pointer + first * gengc->gc.apIndex.ibytes)
|
|
: (__GLfloat*)(gengc->gc.apColor.pointer + first * gengc->gc.apColor.ibytes),
|
|
gengc->gc.apVertex.ibytes,
|
|
gengc->gc.apNormal.ibytes,
|
|
(gengc->gc.ad.dwArrayEnable & ENABLE_INDEXMODE) ? gengc->gc.apIndex.ibytes : gengc->gc.apColor.ibytes,
|
|
gengc->gc.ad.pfn3dddiCalcColor,
|
|
&gengc->gc.transform.modelView->mvp,
|
|
vertexcount)
|
|
) {
|
|
RXDRAWPRIM *ddiCmd;
|
|
PRXVERTEX prxVertex = (PRXVERTEX)(gengc->gc.arxm.pdataRX);
|
|
PRXVERTEX *pprxVertex = (PRXVERTEX*)(gengc->gc.arxm.pdataRX + sizeof(RXVERTEX) * vertexcount);
|
|
PRXVERTEX *pprxv = pprxVertex;
|
|
GLint i;
|
|
|
|
//
|
|
// There weren't any problems transforming the vertices so render them.
|
|
// Fill in the pointers to vertices.
|
|
//
|
|
|
|
if (pindex != NULL) {
|
|
//
|
|
// ArrayElementArray()
|
|
//
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (pindex[i] >= vertexcount) return FALSE;
|
|
}
|
|
switch (mode) {
|
|
case GL_TRIANGLES:
|
|
pprxv += count;
|
|
for (i = 0; i < count; i++) {
|
|
pprxVertex[i] = prxVertex + pindex[i];
|
|
}
|
|
break;
|
|
|
|
case GL_TRIANGLE_STRIP:
|
|
count -= 2;
|
|
i = 0;
|
|
while (i < (count-1)) {
|
|
pprxv[0] = prxVertex + pindex[i ];
|
|
pprxv[1] = prxVertex + pindex[i + 1];
|
|
pprxv[2] = prxVertex + pindex[i + 2];
|
|
|
|
i++;
|
|
pprxv += 3;
|
|
|
|
pprxv[0] = prxVertex + pindex[i ];
|
|
pprxv[1] = prxVertex + pindex[i + 2];
|
|
pprxv[2] = prxVertex + pindex[i + 1];
|
|
|
|
i++;
|
|
pprxv += 3;
|
|
}
|
|
if( count & 1 ) {
|
|
pprxv[0] = prxVertex + pindex[i ];
|
|
pprxv[1] = prxVertex + pindex[i + 1];
|
|
pprxv[2] = prxVertex + pindex[i + 2];
|
|
}
|
|
break;
|
|
|
|
case GL_TRIANGLE_FAN:
|
|
count -= 2;
|
|
i = 0;
|
|
while (i < count) {
|
|
pprxv[0] = prxVertex + pindex[0 ];
|
|
pprxv[1] = prxVertex + pindex[i + 1];
|
|
pprxv[2] = prxVertex + pindex[i + 2];
|
|
|
|
i++;
|
|
pprxv += 3;
|
|
}
|
|
break;
|
|
|
|
case GL_QUADS:
|
|
count -= 3;
|
|
i = 0;
|
|
while (i < count) {
|
|
pprxv[0] = prxVertex + pindex[i ];
|
|
pprxv[1] = prxVertex + pindex[i + 1];
|
|
pprxv[2] = prxVertex + pindex[i + 2];
|
|
|
|
pprxv[3] = prxVertex + pindex[i ];
|
|
pprxv[4] = prxVertex + pindex[i + 2];
|
|
pprxv[5] = prxVertex + pindex[i + 3];
|
|
|
|
i += 4;
|
|
pprxv += 6;
|
|
}
|
|
break;
|
|
|
|
case GL_QUAD_STRIP:
|
|
count -= 3;
|
|
i = 0;
|
|
while (i < count) {
|
|
pprxv[0] = prxVertex + pindex[i ];
|
|
pprxv[1] = prxVertex + pindex[i + 1];
|
|
pprxv[2] = prxVertex + pindex[i + 2];
|
|
|
|
pprxv[3] = prxVertex + pindex[i + 1];
|
|
pprxv[4] = prxVertex + pindex[i + 3];
|
|
pprxv[5] = prxVertex + pindex[i + 2];
|
|
|
|
i += 2;
|
|
pprxv += 6;
|
|
}
|
|
break;
|
|
}
|
|
} else {
|
|
//
|
|
// DrawArrays()
|
|
//
|
|
|
|
switch (mode) {
|
|
case GL_TRIANGLES:
|
|
pprxv += count;
|
|
for (i = 0; i < count; i++) {
|
|
pprxVertex[i] = prxVertex + i;
|
|
}
|
|
break;
|
|
|
|
case GL_TRIANGLE_STRIP:
|
|
count -= 2;
|
|
i = 0;
|
|
while (i < (count-1)) {
|
|
pprxv[0] = prxVertex + i ;
|
|
pprxv[1] = prxVertex + i + 1;
|
|
pprxv[2] = prxVertex + i + 2;
|
|
|
|
i++;
|
|
pprxv += 3;
|
|
|
|
pprxv[0] = prxVertex + i ;
|
|
pprxv[1] = prxVertex + i + 2;
|
|
pprxv[2] = prxVertex + i + 1;
|
|
|
|
i++;
|
|
pprxv += 3;
|
|
}
|
|
if( count & 1 ) {
|
|
pprxv[0] = prxVertex + i ;
|
|
pprxv[1] = prxVertex + i + 1;
|
|
pprxv[2] = prxVertex + i + 2;
|
|
}
|
|
break;
|
|
|
|
case GL_TRIANGLE_FAN:
|
|
count -= 2;
|
|
i = 0;
|
|
while (i < count) {
|
|
pprxv[0] = prxVertex + 0 ;
|
|
pprxv[1] = prxVertex + i + 1;
|
|
pprxv[2] = prxVertex + i + 2;
|
|
|
|
i++;
|
|
pprxv += 3;
|
|
}
|
|
break;
|
|
|
|
case GL_QUADS:
|
|
count -= 3;
|
|
i = 0;
|
|
while (i < count) {
|
|
pprxv[0] = prxVertex + i ;
|
|
pprxv[1] = prxVertex + i + 1;
|
|
pprxv[2] = prxVertex + i + 2;
|
|
|
|
pprxv[3] = prxVertex + i ;
|
|
pprxv[4] = prxVertex + i + 2;
|
|
pprxv[5] = prxVertex + i + 3;
|
|
|
|
i += 4;
|
|
pprxv += 6;
|
|
}
|
|
break;
|
|
|
|
case GL_QUAD_STRIP:
|
|
count -= 3;
|
|
i = 0;
|
|
while (i < count) {
|
|
pprxv[0] = prxVertex + i ;
|
|
pprxv[1] = prxVertex + i + 1;
|
|
pprxv[2] = prxVertex + i + 2;
|
|
|
|
pprxv[3] = prxVertex + i + 1;
|
|
pprxv[4] = prxVertex + i + 3;
|
|
pprxv[5] = prxVertex + i + 2;
|
|
|
|
i += 2;
|
|
pprxv += 6;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Flush all the batched up commands.
|
|
//
|
|
|
|
GenDrvFlush(gengc);
|
|
|
|
//
|
|
// Set culling.
|
|
//
|
|
|
|
if (gengc->gc.polygon.shader.modeFlags & __GL_SHADE_CULL_FACE) {
|
|
switch (gengc->gc.state.polygon.cull) {
|
|
case GL_FRONT: BATCHED_DRV_STATE(RX_CULL_MODE, RX_CULL_CCW); break;
|
|
case GL_BACK: BATCHED_DRV_STATE(RX_CULL_MODE, RX_CULL_CW); break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fill in the command structure.
|
|
//
|
|
|
|
ddiCmd = (RXDRAWPRIM *)(pDrvAccel->pCmd);
|
|
ddiCmd->command = RXCMD_DRAW_PRIM;
|
|
ddiCmd->primType = RX_PRIM_TRILIST;
|
|
ddiCmd->hrxSharedMemVertexData = gengc->gc.arxm.hddimem;
|
|
ddiCmd->hrxSharedMemVertexPtr = gengc->gc.arxm.hddimem;
|
|
ddiCmd->numVertices = ((char*)pprxv - (char*)pprxVertex) / sizeof(PRXVERTEX);
|
|
ddiCmd->pSharedMem = (VOID *)pprxVertex;
|
|
|
|
pDrvAccel->pCmd += sizeof(RXDRAWPRIM);
|
|
|
|
if (gengc->gc.polygon.shader.modeFlags & __GL_SHADE_CULL_FACE) {
|
|
BATCHED_DRV_STATE(RX_CULL_MODE, RX_CULL_NONE);
|
|
}
|
|
|
|
GenDrvFlush(gengc);
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
//
|
|
// There was a problem so go through the slow path.
|
|
//
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// The api entry points and state validation
|
|
//
|
|
//***************************************************************************
|
|
|
|
static BOOL FASTCALL FastDlistData(
|
|
__GLcontext *gc)
|
|
{
|
|
//
|
|
// Check if current array data is of the fast variety, or can be
|
|
// *converted* to fast data during dlist compilation
|
|
//
|
|
|
|
BOOL fVertexOK = (gc->apVertex.size != 4);
|
|
|
|
BOOL fColorOK =
|
|
( gc->ad.dwArrayEnable & ENABLE_COLOR
|
|
&& gc->apColor.size != 4
|
|
)
|
|
|| (!(gc->ad.dwArrayEnable & ENABLE_COLOR));
|
|
|
|
BOOL fTextureOK = !(gc->ad.dwArrayEnable & ENABLE_TEXCOORD);
|
|
|
|
BOOL fEdgeFlagOK = !(gc->ad.dwArrayEnable & ENABLE_EDGEFLAG);
|
|
|
|
if (
|
|
fVertexOK
|
|
&& fColorOK
|
|
&& fTextureOK
|
|
&& fEdgeFlagOK
|
|
)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
|
|
static BOOL FASTCALL FastData(
|
|
__GLcontext *gc)
|
|
{
|
|
//
|
|
// check if current array data is of the fast variety
|
|
//
|
|
|
|
BOOL fVertexOK =
|
|
gc->apVertex.size == 3
|
|
&& gc->apVertex.type == GL_FLOAT;
|
|
|
|
BOOL fNormalOK =
|
|
( gc->ad.dwArrayEnable & ENABLE_NORMAL
|
|
&& gc->apNormal.type == GL_FLOAT
|
|
)
|
|
|| (!(gc->ad.dwArrayEnable & ENABLE_NORMAL));
|
|
|
|
BOOL fIndexOK =
|
|
( gc->ad.dwArrayEnable & ENABLE_INDEX
|
|
&& gc->apIndex.type == GL_FLOAT
|
|
)
|
|
|| (!(gc->ad.dwArrayEnable & ENABLE_INDEX));
|
|
|
|
BOOL fColorOK =
|
|
( gc->ad.dwArrayEnable & ENABLE_COLOR
|
|
&& gc->apColor.size == 3
|
|
&& gc->apColor.type == GL_FLOAT
|
|
)
|
|
|| (!(gc->ad.dwArrayEnable & ENABLE_COLOR));
|
|
|
|
BOOL fTextureOK = !(gc->ad.dwArrayEnable & ENABLE_TEXCOORD);
|
|
|
|
BOOL fEdgeFlagOK = !(gc->ad.dwArrayEnable & ENABLE_EDGEFLAG);
|
|
|
|
if (
|
|
fVertexOK
|
|
&& fNormalOK
|
|
&& fIndexOK
|
|
&& fColorOK
|
|
&& fTextureOK
|
|
&& fEdgeFlagOK
|
|
)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void FASTCALL CheckFastState(
|
|
__GLcontext *gc,
|
|
PARRAYDATA pad )
|
|
{
|
|
//
|
|
// Check if currrent state supports fast formats
|
|
//
|
|
|
|
BOOL fProcOK =
|
|
gc->procs.renderTriangle == __glRenderSmoothTriangle
|
|
|| gc->procs.renderTriangle == __glRenderFlatTriangle;
|
|
|
|
BOOL fNeedsOK =
|
|
( (gc->vertex.faceNeeds[__GL_FRONTFACE] | gc->vertex.needs)
|
|
& (__GL_HAS_EYE | __GL_HAS_FOG | __GL_HAS_TEXTURE)
|
|
) == 0;
|
|
|
|
BOOL fClippingOK = !(gc->state.enables.clipPlanes);
|
|
|
|
if (
|
|
fProcOK
|
|
&& fNeedsOK
|
|
&& fClippingOK
|
|
) {
|
|
|
|
#define CC_ARRAYENABLE 1
|
|
#define CC_LIGHTING 2
|
|
#define CC_INDEX 4
|
|
|
|
static PFNCALCCOLOR apfnColor[] = {
|
|
MyCalcRGB,
|
|
MyCalcRGBArray,
|
|
MyCalcRGBLight,
|
|
MyCalcRGBLightArray,
|
|
|
|
MyCalcCI,
|
|
MyCalcCIArray,
|
|
MyCalcCILight,
|
|
MyCalcCILight,
|
|
};
|
|
static PFNCALC3DDDICOLOR apfn3dddiColor[] = {
|
|
Calc3dddiRGB,
|
|
Calc3dddiRGBArray,
|
|
Calc3dddiRGBLight,
|
|
Calc3dddiRGBLightArray,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
//Calc3dddiCI,
|
|
//Calc3dddiCIArray,
|
|
//Calc3dddiCILight,
|
|
//Calc3dddiCILight,
|
|
};
|
|
__GLlightSourceMachine *lsm;
|
|
int icc = 0;
|
|
|
|
if (gc->modes.colorIndexMode) {
|
|
pad->dwArrayEnable |= ENABLE_INDEXMODE;
|
|
icc |= CC_INDEX;
|
|
if (pad->dwArrayEnable & ENABLE_INDEX) { icc |= CC_ARRAYENABLE; }
|
|
} else {
|
|
pad->dwArrayEnable &= ~ENABLE_INDEXMODE;
|
|
if (pad->dwArrayEnable & ENABLE_COLOR) { icc |= CC_ARRAYENABLE; }
|
|
}
|
|
|
|
if (gc->state.enables.general & __GL_LIGHTING_ENABLE) {
|
|
icc |= CC_LIGHTING;
|
|
|
|
if ( (gc->state.light.colorMaterialFace == GL_BACK)
|
|
|| (gc->polygon.shader.modeFlags & __GL_SHADE_TWOSIDED)
|
|
|| ( !gc->modes.colorIndexMode
|
|
&& pad->dwArrayEnable & ENABLE_COLOR
|
|
&& ( (gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE)
|
|
&& (gc->state.light.colorMaterialParam != GL_AMBIENT_AND_DIFFUSE)
|
|
)
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
//
|
|
// if there are any slow lights use the slow path
|
|
//
|
|
|
|
for (lsm = gc->light.sources; lsm; lsm = lsm->next) {
|
|
if (lsm->slowPath) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Ignore color array if vertex colors enabled w/o color material
|
|
if( ( pad->dwArrayEnable & ENABLE_COLOR )
|
|
&& ( !(gc->state.enables.general & __GL_COLOR_MATERIAL_ENABLE))
|
|
) {
|
|
icc &= ~CC_ARRAYENABLE;
|
|
}
|
|
|
|
// If no normal array, use current normal
|
|
if( !(pad->dwArrayEnable & ENABLE_NORMAL) ) {
|
|
if( pad->dwArrayEnable & ENABLE_INDEXMODE )
|
|
return; // maybe later
|
|
pad->dwArrayEnable |= ENABLE_PRECALCCOLOR;
|
|
}
|
|
}
|
|
|
|
pad->pfnCalcColor = apfnColor[icc];
|
|
pad->dwArrayEnable |= ENABLE_FASTFORMATS;
|
|
|
|
if (gc->procs.fillTriangle == GenDrvTriangle) {
|
|
pad->pfn3dddiCalcColor = apfn3dddiColor[icc];
|
|
if (pad->pfn3dddiCalcColor != NULL) {
|
|
pad->dwArrayEnable |= ENABLE_3DDDIFORMATS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void FASTCALL CheckFastFormats(
|
|
__GLcontext *gc)
|
|
{
|
|
//
|
|
// See if we can use fast formats for both immediate mode and dlist states
|
|
//
|
|
|
|
// Check immediate mode state
|
|
gc->ad.dwArrayEnable &= ENABLE_POINTER_MASK; // mask out any fast bits
|
|
if( FastData( gc ) )
|
|
CheckFastState( gc, &gc->ad );
|
|
|
|
// Check dlist state (assuming fast dlist data)
|
|
if( gc->adDlist.dwArrayEnable ) {
|
|
gc->adDlist.dwArrayEnable &= ENABLE_POINTER_MASK;
|
|
CheckFastState( gc, &gc->adDlist );
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void FASTCALL PreCalcRGBColor(
|
|
__GLcontext *gc,
|
|
BOOL bLight )
|
|
{
|
|
if( bLight ) { // normal lighting
|
|
ComputeRGBLightColor( gc, (GLfloat *) &gc->state.current.normal,
|
|
&gc->ac.color );
|
|
// patch in current alpha
|
|
gc->ac.color.a = gc->light.front.alpha;
|
|
} else { // LightArray
|
|
ComputeCMRGBLightColor( gc, (GLfloat *) &gc->state.current.normal,
|
|
&gc->ac.color,
|
|
&gc->ac.mcolor );
|
|
}
|
|
|
|
// turn off lighting color computations
|
|
gc->ac.bComputeColor = FALSE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void APIPRIVATE __glim_DrawArraysEXT(
|
|
GLenum mode,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
|
|
|
|
if (count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_VERTEX == 0) {
|
|
//
|
|
// Nothing drawn if glVertex*() is not called
|
|
//
|
|
return;
|
|
}
|
|
|
|
switch (mode) {
|
|
case GL_POINTS:
|
|
case GL_LINE_STRIP:
|
|
case GL_LINE_LOOP:
|
|
case GL_LINES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_TRIANGLES:
|
|
case GL_QUAD_STRIP:
|
|
case GL_QUADS:
|
|
case GL_POLYGON:
|
|
break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (gc->transform.modelView->updateInverse) {
|
|
__glComputeInverseTranspose(gc, gc->transform.modelView);
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_3DDDIFORMATS) {
|
|
gc->ac.bComputeColor = TRUE;
|
|
if (gc->ad.dwArrayEnable & ENABLE_PRECALCCOLOR) {
|
|
PreCalcRGBColor( gc,
|
|
gc->ad.pfn3dddiCalcColor == Calc3dddiRGBLight );
|
|
// will turn off bComputeColor
|
|
}
|
|
switch (mode) {
|
|
case GL_TRIANGLES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_QUADS:
|
|
case GL_QUAD_STRIP:
|
|
if (Draw3dddiTriangles(gc, mode, first, count, NULL)) return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_FASTFORMATS) {
|
|
gc->ac.bComputeColor = TRUE;
|
|
if (gc->ad.dwArrayEnable & ENABLE_PRECALCCOLOR) {
|
|
PreCalcRGBColor( gc,
|
|
gc->ad.pfnCalcColor == MyCalcRGBLight );
|
|
// will turn off bComputeColor
|
|
}
|
|
switch (mode) {
|
|
case GL_TRIANGLES: ArrayDrawTriangles(gc, first, count); return;
|
|
case GL_TRIANGLE_STRIP: ArrayDrawTStrip(gc, first, count); return;
|
|
case GL_TRIANGLE_FAN: ArrayDrawTFan(gc, first, count); return;
|
|
case GL_QUADS: ArrayDrawQuads(gc, first, count); return;
|
|
case GL_QUAD_STRIP: ArrayDrawQStrip(gc, first, count); return;
|
|
}
|
|
}
|
|
|
|
__glim_Begin(mode);
|
|
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
ArrayElementEXTInternal(gc, first + i);
|
|
}
|
|
}
|
|
|
|
__glim_End();
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void APIPRIVATE __glim_ArrayElementArrayEXT(
|
|
GLenum mode,
|
|
GLsizei count,
|
|
const GLvoid* pi)
|
|
{
|
|
GLint* pindex = (GLint*)pi;
|
|
|
|
__GL_SETUP_NOT_IN_BEGIN_VALIDATE();
|
|
|
|
if (count < 0) {
|
|
__glSetError(GL_INVALID_VALUE);
|
|
return;
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_VERTEX == 0) {
|
|
//
|
|
// Nothing drawn if glVertex*() is not called
|
|
//
|
|
return;
|
|
}
|
|
|
|
switch (mode) {
|
|
case GL_POINTS:
|
|
case GL_LINE_STRIP:
|
|
case GL_LINE_LOOP:
|
|
case GL_LINES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_TRIANGLES:
|
|
case GL_QUAD_STRIP:
|
|
case GL_QUADS:
|
|
case GL_POLYGON:
|
|
break;
|
|
default:
|
|
__glSetError(GL_INVALID_ENUM);
|
|
return;
|
|
}
|
|
|
|
if (gc->transform.modelView->updateInverse) {
|
|
__glComputeInverseTranspose(gc, gc->transform.modelView);
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_3DDDIFORMATS) {
|
|
gc->ac.bComputeColor = TRUE;
|
|
if (gc->ad.dwArrayEnable & ENABLE_PRECALCCOLOR) {
|
|
PreCalcRGBColor( gc,
|
|
gc->ad.pfn3dddiCalcColor == Calc3dddiRGBLight );
|
|
// will turn off bComputeColor
|
|
}
|
|
switch (mode) {
|
|
case GL_TRIANGLES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_QUADS:
|
|
case GL_QUAD_STRIP:
|
|
if (Draw3dddiTriangles(gc, mode, 0, count, pindex)) return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_FASTFORMATS) {
|
|
gc->ac.bComputeColor = TRUE;
|
|
if (gc->ad.dwArrayEnable & ENABLE_PRECALCCOLOR) {
|
|
PreCalcRGBColor( gc,
|
|
gc->ad.pfnCalcColor == MyCalcRGBLight );
|
|
// will turn off bComputeColor
|
|
}
|
|
switch (mode) {
|
|
case GL_TRIANGLES: ArrayElementDrawTriangles(gc, count, pindex); return;
|
|
case GL_TRIANGLE_STRIP: ArrayElementDrawTStrip (gc, count, pindex); return;
|
|
case GL_TRIANGLE_FAN: ArrayElementDrawTFan (gc, count, pindex); return;
|
|
case GL_QUADS: ArrayElementDrawQuads (gc, count, pindex); return;
|
|
case GL_QUAD_STRIP: ArrayElementDrawQStrip (gc, count, pindex); return;
|
|
}
|
|
}
|
|
|
|
__glim_Begin(mode);
|
|
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
ArrayElementEXTInternal(gc, pindex[i]);
|
|
}
|
|
}
|
|
|
|
__glim_End();
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
// Display list versions
|
|
|
|
/****************************************************************************/
|
|
|
|
// a lot of this parallels info in the gc...
|
|
|
|
typedef struct _ARRAY_DLIST_HDR {
|
|
GLuint dwArrayEnable;
|
|
GLenum mode;
|
|
GLsizei count;
|
|
GLint arraySize; // size in bytes of entire array block
|
|
BOOL bOffsets; // TRUE if pointer values are offsets
|
|
ARRAYPOINTER apVertex;
|
|
ARRAYPOINTER apNormal;
|
|
ARRAYPOINTER apColor;
|
|
ARRAYPOINTER apIndex;
|
|
ARRAYPOINTER apTexCoord;
|
|
ARRAYPOINTER apEdgeFlag;
|
|
} ARRAY_DLIST_HDR;
|
|
|
|
#define __GL_SETUP_NOT_IN_BEGIN_VALIDATE_DLIST( size )\
|
|
__GL_SETUP(); \
|
|
__GLbeginMode beginMode = gc->beginMode; \
|
|
if (beginMode != __GL_NOT_IN_BEGIN) { \
|
|
if (beginMode == __GL_NEED_VALIDATE) { \
|
|
(*gc->procs.validate)(gc); \
|
|
gc->beginMode = __GL_NOT_IN_BEGIN; \
|
|
} else { \
|
|
__glSetError(GL_INVALID_OPERATION); \
|
|
return PC + size; \
|
|
} \
|
|
}
|
|
|
|
// convert offsets to ptrs for list execute functions
|
|
#define SETUP_DATAPTR( ap, flag ) \
|
|
if( padh->dwArrayEnable & flag ) \
|
|
(ap).pointer = (GLint) basePtr + (ap).pointer;
|
|
|
|
/****************************************************************************/
|
|
|
|
static void ConvertOffsetsToPtrs(
|
|
ARRAY_DLIST_HDR *padh,
|
|
GLubyte *basePtr )
|
|
{
|
|
SETUP_DATAPTR( padh->apNormal, ENABLE_NORMAL );
|
|
SETUP_DATAPTR( padh->apColor, ENABLE_COLOR );
|
|
SETUP_DATAPTR( padh->apIndex, ENABLE_INDEX );
|
|
SETUP_DATAPTR( padh->apTexCoord, ENABLE_TEXCOORD );
|
|
SETUP_DATAPTR( padh->apEdgeFlag, ENABLE_EDGEFLAG );
|
|
SETUP_DATAPTR( padh->apVertex, ENABLE_VERTEX );
|
|
padh->bOffsets = FALSE;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static GLuint FASTCALL DlistDataSize(
|
|
__GLcontext *gc,
|
|
GLenum flag,
|
|
PARRAYPOINTER pap,
|
|
BOOL bFastData )
|
|
{
|
|
if( bFastData ) {
|
|
switch( flag ) {
|
|
case ENABLE_NORMAL:
|
|
case ENABLE_COLOR:
|
|
case ENABLE_VERTEX:
|
|
return sizeof(GLfloat) * 3;
|
|
case ENABLE_INDEX:
|
|
return sizeof(GLfloat);
|
|
}
|
|
}
|
|
return __glTypeSize( pap->type ) * pap->size;
|
|
}
|
|
|
|
|
|
// size of a block of array data
|
|
#define ARRAYPOINTER_DATA_SIZE( flag, ap ) \
|
|
( gc->ad.dwArrayEnable & flag ? \
|
|
(count * DlistDataSize( gc, flag, &(ap), bFastData )) : 0 )
|
|
|
|
/****************************************************************************/
|
|
|
|
static void FASTCALL ConvertElement(
|
|
GLenum flag,
|
|
GLint size,
|
|
GLenum type,
|
|
GLfloat **ppDst,
|
|
GLubyte *pSrc )
|
|
{
|
|
GLint i;
|
|
GLfloat *pDst = *ppDst;
|
|
|
|
for( i = 0; i < size; i ++ ) {
|
|
switch( type ) {
|
|
case GL_BYTE:
|
|
*pDst++ = (GLfloat) *(((GLbyte *)pSrc)++); break;
|
|
case GL_UNSIGNED_BYTE:
|
|
*pDst++ = (GLfloat) *(((GLubyte *)pSrc)++); break;
|
|
case GL_SHORT:
|
|
*pDst++ = (GLfloat) *(((GLshort *)pSrc)++); break;
|
|
case GL_UNSIGNED_SHORT:
|
|
*pDst++ = (GLfloat) *(((GLushort *)pSrc)++); break;
|
|
case GL_INT:
|
|
*pDst++ = (GLfloat) *(((GLint *)pSrc)++); break;
|
|
case GL_UNSIGNED_INT:
|
|
*pDst++ = (GLfloat) *(((GLuint *)pSrc)++); break;
|
|
case GL_FLOAT:
|
|
*pDst++ = (GLfloat) *(((GLfloat *)pSrc)++); break;
|
|
case GL_DOUBLE_EXT:
|
|
*pDst++ = (GLfloat) *(((GLdouble *)pSrc)++); break;
|
|
}
|
|
}
|
|
*ppDst += size;
|
|
|
|
if( (flag == ENABLE_VERTEX) && (size == 2) ) {
|
|
// add z=0.0
|
|
*pDst = 0.0f;
|
|
**ppDst += 1;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void __glConvertArray(
|
|
GLenum flag,
|
|
GLint first,
|
|
GLsizei count,
|
|
PARRAYPOINTER pap,
|
|
GLfloat *newData )
|
|
{
|
|
GLint bytes_per_element, skip;
|
|
GLubyte *oldData;
|
|
|
|
bytes_per_element = pap->size * __glTypeSize(pap->type);
|
|
skip = pap->stride ? pap->stride : bytes_per_element;
|
|
oldData = (GLubyte *)pap->pointer + first * skip;
|
|
|
|
// XXX: could use function ptr to a conversion function if need more speed
|
|
|
|
for ( ; count; count-- ) {
|
|
ConvertElement( flag, pap->size, pap->type, &newData, oldData );
|
|
oldData += skip;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void __glConvertIndexedArray(
|
|
GLenum flag,
|
|
GLsizei count,
|
|
GLint *pindex,
|
|
PARRAYPOINTER pap,
|
|
GLfloat *newData )
|
|
{
|
|
GLubyte *oldData;
|
|
|
|
for( ; count; count-- ) {
|
|
oldData = pap->pointer + (*pindex++ * pap->stride);
|
|
ConvertElement( flag, pap->size, pap->type, &newData, oldData );
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void __glFillArray(
|
|
GLint first,
|
|
GLsizei count,
|
|
PARRAYPOINTER pap,
|
|
GLubyte *newData )
|
|
{
|
|
GLint bytes_per_element, array_size, skip;
|
|
GLubyte *oldData;
|
|
|
|
bytes_per_element = pap->size * __glTypeSize(pap->type);
|
|
array_size = bytes_per_element * count;
|
|
skip = pap->stride ? pap->stride : bytes_per_element;
|
|
|
|
oldData = (GLubyte *)pap->pointer + first * skip;
|
|
|
|
/* Tightly packed data - copy the whole thing */
|
|
if (pap->stride == 0 || pap->stride == bytes_per_element) {
|
|
RtlCopyMemory( newData, oldData, array_size);
|
|
} else {
|
|
/* Copy only relevant data */
|
|
for( ; count; count-- ) {
|
|
RtlCopyMemory(newData, oldData, bytes_per_element);
|
|
newData += bytes_per_element;
|
|
oldData += skip;
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void __glFillIndexedArray(
|
|
GLsizei count,
|
|
GLint *pindex,
|
|
PARRAYPOINTER pap,
|
|
GLubyte *newData )
|
|
{
|
|
GLint bytes_per_element;
|
|
GLubyte *oldData;
|
|
|
|
bytes_per_element = pap->size * __glTypeSize(pap->type);
|
|
|
|
for( ; count; count-- ) {
|
|
oldData = pap->pointer + (*pindex++ * pap->stride);
|
|
RtlCopyMemory(newData, oldData, bytes_per_element);
|
|
newData += bytes_per_element;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#define CALLARRAYPOINTER_DLIST(flag, ap) \
|
|
if( adh->dwArrayEnable & flag ) \
|
|
(((ap).pfn)((ap).pointer + i * (ap).ibytes))
|
|
|
|
static void FASTCALL ArrayElementEXTInternalDlist(
|
|
ARRAY_DLIST_HDR *adh,
|
|
GLint i)
|
|
{
|
|
CALLARRAYPOINTER_DLIST(ENABLE_NORMAL, adh->apNormal);
|
|
CALLARRAYPOINTER_DLIST(ENABLE_COLOR, adh->apColor);
|
|
CALLARRAYPOINTER_DLIST(ENABLE_INDEX, adh->apIndex);
|
|
CALLARRAYPOINTER_DLIST(ENABLE_TEXCOORD, adh->apTexCoord);
|
|
CALLARRAYPOINTER_DLIST(ENABLE_EDGEFLAG, adh->apEdgeFlag);
|
|
CALLARRAYPOINTER_DLIST(ENABLE_VERTEX, adh->apVertex);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void FASTCALL
|
|
SetupArrayDlistPointer(
|
|
GLenum flag,
|
|
ARRAYPOINTER *apDst,
|
|
ARRAYPOINTER *apSrc,
|
|
GLint offset,
|
|
BOOL bFastData )
|
|
{
|
|
// We overload the pointer as an offset here (can't use mem pointer, cuz
|
|
// dlist compile processing can move things around in memory)
|
|
// The offset will be converted to mem ptr first time dlist is run
|
|
apDst->pointer = (GLubyte *) offset;
|
|
apDst->count = apSrc->count;
|
|
|
|
if( bFastData ) {
|
|
apDst->type = GL_FLOAT;
|
|
apDst->size = 3;
|
|
apDst->ibytes = 3 * sizeof( GL_FLOAT );
|
|
switch( flag ) {
|
|
case ENABLE_NORMAL:
|
|
apDst->pfn = (PFNVECTOR) __glim_Normal3fv;
|
|
break;
|
|
case ENABLE_COLOR:
|
|
apDst->pfn = (PFNVECTOR) __glim_Color3fv;
|
|
break;
|
|
case ENABLE_VERTEX:
|
|
apDst->pfn = (PFNVECTOR) __glim_Vertex3fv;
|
|
break;
|
|
case ENABLE_INDEX:
|
|
apDst->pfn = (PFNVECTOR) __glim_Indexfv;
|
|
apDst->size = 1;
|
|
apDst->ibytes = sizeof( GL_FLOAT );
|
|
}
|
|
|
|
} else {
|
|
// Make sure ibytes is set for a packed array
|
|
if( apSrc->stride == 0 )
|
|
apDst->ibytes = apSrc->ibytes;
|
|
else
|
|
apDst->ibytes = __glTypeSize(apSrc->type) * apSrc->size;
|
|
apDst->pfn = apSrc->pfn;
|
|
|
|
apDst->size = apSrc->size;
|
|
apDst->type = apSrc->type;
|
|
}
|
|
apDst->stride = apDst->ibytes; // cuz it's packed
|
|
}
|
|
|
|
#define SETUP_ARRAY_DLIST_DATA( flag, papDst, papSrc, Size ) \
|
|
if( gc->ad.dwArrayEnable & flag ) { \
|
|
SetupArrayDlistPointer( flag, (papDst), (papSrc), offset, bFastData ); \
|
|
if( bFastData && \
|
|
(((papDst)->type != (papSrc)->type) || ((papDst)->size != (papSrc)->size)) ) \
|
|
__glConvertArray( flag, first, count, (papSrc), (GLfloat *) dataPtr ); \
|
|
else \
|
|
__glFillArray( first, count, (papSrc), dataPtr ); \
|
|
offset += Size; \
|
|
dataPtr += Size; \
|
|
}
|
|
|
|
|
|
#define SETUP_ARRAY_DLIST_DATA_INDEXED( flag, papDst, papSrc, Size ) \
|
|
if( gc->ad.dwArrayEnable & flag ) { \
|
|
SetupArrayDlistPointer( flag, (papDst), (papSrc), offset, bFastData ); \
|
|
if( bFastData && \
|
|
(((papDst)->type != (papSrc)->type) || ((papDst)->size != (papSrc)->size)) ) \
|
|
__glConvertIndexedArray( flag, count, pindex, (papSrc), (GLfloat *) dataPtr ); \
|
|
else \
|
|
__glFillIndexedArray( count, pindex, (papSrc), dataPtr ); \
|
|
offset += Size; \
|
|
dataPtr += Size; \
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void __gllc_ArrayElementEXT(
|
|
GLint i )
|
|
{
|
|
ARRAY_DLIST_HDR *adh;
|
|
GLubyte *dataPtr;
|
|
GLint offset; // individal array data offset
|
|
GLint naSize, caSize, iaSize, tcaSize, efaSize, vaSize;
|
|
GLint arraySize;
|
|
GLint count = 1;
|
|
GLint first = i; // for SETUP_ARRAY_DLIST_DATA macro
|
|
BOOL bFastData = FALSE; // "
|
|
__GL_SETUP();
|
|
|
|
// calculate size requirements for data - in bytes
|
|
naSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_NORMAL, gc->apNormal ));
|
|
caSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_COLOR, gc->apColor ));
|
|
iaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_INDEX, gc->apIndex ));
|
|
tcaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_TEXCOORD, gc->apTexCoord ));
|
|
efaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_EDGEFLAG, gc->apEdgeFlag ));
|
|
vaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_VERTEX, gc->apVertex ));
|
|
arraySize = naSize + caSize + iaSize + tcaSize + efaSize + vaSize;
|
|
|
|
// allocate dlist memory
|
|
|
|
adh = (ARRAY_DLIST_HDR *)
|
|
__glDlistAddOpUnaligned(gc, DLIST_SIZE(sizeof(ARRAY_DLIST_HDR) + arraySize),
|
|
DLIST_GENERIC_OP(ArrayElementEXT));
|
|
if (adh == NULL) return;
|
|
|
|
// set header info
|
|
|
|
adh->count = count;
|
|
adh->dwArrayEnable = gc->ad.dwArrayEnable & ENABLE_POINTER_MASK;
|
|
adh->arraySize = arraySize;
|
|
adh->bOffsets = TRUE;
|
|
|
|
// set dlist array pointer structs, and copy over data
|
|
|
|
// dataPtr points to destination array block
|
|
// both dataPtr and offset are incremented by the macro
|
|
dataPtr = (GLubyte *)adh + sizeof( ARRAY_DLIST_HDR );
|
|
offset = 0;
|
|
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_NORMAL, (&(adh->apNormal)), (&(gc->apNormal)), naSize );
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_COLOR, &adh->apColor, &gc->apColor, caSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_INDEX, &adh->apIndex, &gc->apIndex, iaSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_TEXCOORD, &adh->apTexCoord, &gc->apTexCoord, tcaSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_EDGEFLAG, &adh->apEdgeFlag, &gc->apEdgeFlag, efaSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_VERTEX, &adh->apVertex, &gc->apVertex, vaSize);
|
|
|
|
__glDlistAppendOp(gc, adh, __glle_ArrayElementEXT);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
const GLubyte * FASTCALL __glle_ArrayElementEXT( __GLcontext *gc, const GLubyte *PC )
|
|
{
|
|
ARRAY_DLIST_HDR *adh = (ARRAY_DLIST_HDR *) PC;
|
|
GLint size = sizeof(ARRAY_DLIST_HDR) + adh->arraySize;
|
|
|
|
if( adh->bOffsets )
|
|
ConvertOffsetsToPtrs( adh, (GLubyte *) PC + sizeof(ARRAY_DLIST_HDR) );
|
|
|
|
ArrayElementEXTInternalDlist( adh, 0 );
|
|
|
|
return PC + size;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void __gllc_DrawArraysEXT(
|
|
GLenum mode,
|
|
GLint first,
|
|
GLsizei count)
|
|
{
|
|
ARRAY_DLIST_HDR *adh;
|
|
GLubyte *dataPtr;
|
|
GLint offset; // individal array data offset
|
|
GLint naSize, caSize, iaSize, tcaSize, efaSize, vaSize;
|
|
GLint arraySize;
|
|
BOOL bFastData;
|
|
__GL_SETUP();
|
|
|
|
if (count < 0) {
|
|
__gllc_InvalidEnum();
|
|
return;
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_VERTEX == 0) {
|
|
//
|
|
// Nothing drawn if glVertex*() is not called
|
|
//
|
|
return;
|
|
}
|
|
|
|
switch(mode) {
|
|
case GL_POINTS:
|
|
case GL_LINE_STRIP:
|
|
case GL_LINE_LOOP:
|
|
case GL_LINES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_TRIANGLES:
|
|
case GL_QUAD_STRIP:
|
|
case GL_QUADS:
|
|
case GL_POLYGON:
|
|
break;
|
|
default:
|
|
__gllc_InvalidEnum();
|
|
return;
|
|
}
|
|
|
|
// Check for fast data
|
|
bFastData = FastDlistData( gc );
|
|
|
|
// calculate size requirements for data - in bytes
|
|
naSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_NORMAL, gc->apNormal ) );
|
|
caSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_COLOR, gc->apColor ));
|
|
iaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_INDEX, gc->apIndex ));
|
|
tcaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_TEXCOORD, gc->apTexCoord ));
|
|
efaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_EDGEFLAG, gc->apEdgeFlag ));
|
|
vaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_VERTEX, gc->apVertex ));
|
|
arraySize = naSize + caSize + iaSize + tcaSize + efaSize + vaSize;
|
|
|
|
// allocate dlist memory
|
|
|
|
adh = (ARRAY_DLIST_HDR *)
|
|
__glDlistAddOpUnaligned(gc, DLIST_SIZE(sizeof(ARRAY_DLIST_HDR) + arraySize),
|
|
DLIST_GENERIC_OP(DrawArraysEXT));
|
|
if (adh == NULL) return;
|
|
|
|
// set header info
|
|
|
|
adh->mode = mode;
|
|
adh->count = count;
|
|
adh->dwArrayEnable = gc->ad.dwArrayEnable & ENABLE_POINTER_MASK;
|
|
if( bFastData )
|
|
// Overload dwArrayEnable bit to indicate fast data
|
|
adh->dwArrayEnable |= ENABLE_FASTFORMATS;
|
|
adh->arraySize = arraySize;
|
|
adh->bOffsets = TRUE;
|
|
|
|
// set dlist array pointer structs, and copy over data
|
|
|
|
// dataPtr points to destination array block
|
|
dataPtr = (GLubyte *)adh + sizeof( ARRAY_DLIST_HDR );
|
|
offset = 0;
|
|
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_NORMAL, &adh->apNormal, &gc->apNormal, naSize );
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_COLOR, &adh->apColor, &gc->apColor, caSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_INDEX, &adh->apIndex, &gc->apIndex, iaSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_TEXCOORD, &adh->apTexCoord, &gc->apTexCoord, tcaSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_EDGEFLAG, &adh->apEdgeFlag, &gc->apEdgeFlag, efaSize);
|
|
SETUP_ARRAY_DLIST_DATA( ENABLE_VERTEX, &adh->apVertex, &gc->apVertex, vaSize);
|
|
|
|
__glDlistAppendOp(gc, adh, __glle_DrawArraysEXT);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
const GLubyte * FASTCALL__glle_DrawArraysEXT( __GLcontext *gc, const GLubyte *PC )
|
|
{
|
|
ARRAYPOINTER apSave[ARRAY_POINTER_COUNT];
|
|
BOOL b3dddiDraw = FALSE;
|
|
ARRAY_DLIST_HDR *adh = (ARRAY_DLIST_HDR *) PC;
|
|
GLint size = sizeof(ARRAY_DLIST_HDR) + adh->arraySize;
|
|
//!!! gc is now given
|
|
__GL_SETUP_NOT_IN_BEGIN_VALIDATE_DLIST( size );
|
|
|
|
// Convert offsets to ptrs first time through
|
|
|
|
if( adh->bOffsets )
|
|
ConvertOffsetsToPtrs( adh, (GLubyte *) PC + sizeof(ARRAY_DLIST_HDR) );
|
|
|
|
// Save current array pointer state
|
|
|
|
RtlCopyMemory( apSave, &gc->apVertex, ARRAY_POINTER_COUNT *
|
|
sizeof( ARRAYPOINTER ) );
|
|
|
|
// Patch in dlist array pointer state (this is so existing code,
|
|
// which acts on gc array state, can be used)
|
|
// Could use ptrs to switch between states, but this would use extra
|
|
// register in the drawing func.
|
|
|
|
RtlCopyMemory( &gc->apVertex, &adh->apVertex, ARRAY_POINTER_COUNT *
|
|
sizeof( ARRAYPOINTER ) );
|
|
|
|
if (gc->transform.modelView->updateInverse)
|
|
__glComputeInverseTranspose(gc, gc->transform.modelView);
|
|
|
|
// Avoid validation if not fast dlist data
|
|
|
|
if( !(adh->dwArrayEnable & ENABLE_FASTFORMATS) )
|
|
goto slow_path;
|
|
|
|
// Validate gc dlist array state
|
|
|
|
if( (gc->adDlist.dwArrayEnable & ENABLE_POINTER_MASK) !=
|
|
(adh->dwArrayEnable & ENABLE_POINTER_MASK) )
|
|
{
|
|
// copy dlist's enable bits into gc
|
|
gc->adDlist.dwArrayEnable = adh->dwArrayEnable & ENABLE_POINTER_MASK;
|
|
// validate
|
|
CheckFastState( gc, &gc->adDlist );
|
|
}
|
|
|
|
// draw stuff according to fastpath state
|
|
|
|
if (gc->adDlist.dwArrayEnable & ENABLE_3DDDIFORMATS) {
|
|
PFNCALC3DDDICOLOR pfn3dddiCalcColorSave = gc->ad.pfn3dddiCalcColor;
|
|
|
|
gc->ad.pfn3dddiCalcColor = gc->adDlist.pfn3dddiCalcColor;
|
|
gc->ac.bComputeColor = TRUE;
|
|
if (gc->ad.dwArrayEnable & ENABLE_PRECALCCOLOR) {
|
|
PreCalcRGBColor( gc,
|
|
gc->ad.pfn3dddiCalcColor == Calc3dddiRGBLight );
|
|
// will turn off bComputeColor
|
|
}
|
|
switch (adh->mode) {
|
|
case GL_TRIANGLES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_QUADS:
|
|
case GL_QUAD_STRIP:
|
|
b3dddiDraw = Draw3dddiTriangles(gc, adh->mode, 0, adh->count, NULL);
|
|
break;
|
|
}
|
|
gc->ad.pfn3dddiCalcColor = pfn3dddiCalcColorSave;
|
|
}
|
|
|
|
if( !b3dddiDraw && (gc->adDlist.dwArrayEnable & ENABLE_FASTFORMATS) ) {
|
|
PFNCALCCOLOR pfnCalcColorSave = gc->ad.pfnCalcColor;
|
|
|
|
gc->ad.pfnCalcColor = gc->adDlist.pfnCalcColor;
|
|
|
|
gc->ac.bComputeColor = TRUE;
|
|
if (gc->adDlist.dwArrayEnable & ENABLE_PRECALCCOLOR) {
|
|
PreCalcRGBColor( gc,
|
|
gc->ad.pfnCalcColor == MyCalcRGBLight );
|
|
// will turn off bComputeColor
|
|
}
|
|
switch (adh->mode) {
|
|
case GL_TRIANGLES: ArrayDrawTriangles(gc, 0, adh->count); break;
|
|
case GL_TRIANGLE_STRIP: ArrayDrawTStrip(gc, 0, adh->count); break;
|
|
case GL_TRIANGLE_FAN: ArrayDrawTFan(gc, 0, adh->count); break;
|
|
case GL_QUADS: ArrayDrawQuads(gc, 0, adh->count); break;
|
|
case GL_QUAD_STRIP: ArrayDrawQStrip(gc, 0, adh->count); break;
|
|
}
|
|
gc->ad.pfnCalcColor = pfnCalcColorSave;
|
|
}
|
|
|
|
else {
|
|
slow_path:
|
|
__glim_Begin( adh->mode );
|
|
{
|
|
int i;
|
|
|
|
for( i = 0; i < adh->count; i ++ ) {
|
|
ArrayElementEXTInternalDlist( adh, i );
|
|
}
|
|
}
|
|
__glim_End();
|
|
}
|
|
|
|
// restore array pointer state
|
|
|
|
RtlCopyMemory( &gc->apVertex, apSave, ARRAY_POINTER_COUNT *
|
|
sizeof( ARRAYPOINTER ) );
|
|
return PC + size;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
void __gllc_ArrayElementArrayEXT(
|
|
GLenum mode,
|
|
GLsizei count,
|
|
const GLvoid* pi)
|
|
{
|
|
ARRAY_DLIST_HDR *adh;
|
|
GLubyte *dataPtr;
|
|
GLint offset; // individal array data offset
|
|
GLint naSize, caSize, iaSize, tcaSize, efaSize, vaSize;
|
|
GLint arraySize;
|
|
GLint *pindex = (GLint*) pi;
|
|
BOOL bFastData;
|
|
__GL_SETUP();
|
|
|
|
if (count < 0) {
|
|
__gllc_InvalidEnum();
|
|
return;
|
|
}
|
|
|
|
if (gc->ad.dwArrayEnable & ENABLE_VERTEX == 0) {
|
|
//
|
|
// Nothing drawn if glVertex*() is not called
|
|
//
|
|
return;
|
|
}
|
|
|
|
// Note: this function generates a *DrawArrays* opcode in the display list
|
|
|
|
switch(mode) {
|
|
case GL_POINTS:
|
|
case GL_LINE_STRIP:
|
|
case GL_LINE_LOOP:
|
|
case GL_LINES:
|
|
case GL_TRIANGLE_STRIP:
|
|
case GL_TRIANGLE_FAN:
|
|
case GL_TRIANGLES:
|
|
case GL_QUAD_STRIP:
|
|
case GL_QUADS:
|
|
case GL_POLYGON:
|
|
break;
|
|
default:
|
|
__gllc_InvalidEnum();
|
|
return;
|
|
}
|
|
|
|
// Check for fast data
|
|
bFastData = FastDlistData( gc );
|
|
|
|
// calculate size requirements for data - in bytes
|
|
naSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_NORMAL, gc->apNormal ));
|
|
caSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_COLOR, gc->apColor ));
|
|
iaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_INDEX, gc->apIndex ));
|
|
tcaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_TEXCOORD, gc->apTexCoord ));
|
|
efaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_EDGEFLAG, gc->apEdgeFlag ));
|
|
vaSize = __GL_PAD( ARRAYPOINTER_DATA_SIZE( ENABLE_VERTEX, gc->apVertex ));
|
|
arraySize = naSize + caSize + iaSize + tcaSize + efaSize + vaSize;
|
|
|
|
// allocate dlist memory
|
|
|
|
adh = __glDlistAddOpUnaligned(gc, DLIST_SIZE(sizeof(ARRAY_DLIST_HDR) + arraySize),
|
|
DLIST_GENERIC_OP(DrawArraysEXT));
|
|
if (adh == NULL) return;
|
|
|
|
// set header info
|
|
|
|
adh->mode = mode;
|
|
adh->count = count;
|
|
adh->dwArrayEnable = gc->ad.dwArrayEnable & ENABLE_POINTER_MASK;
|
|
if( bFastData )
|
|
// Overload dwArrayEnable to indicate fast data
|
|
adh->dwArrayEnable |= ENABLE_FASTFORMATS;
|
|
adh->arraySize = arraySize;
|
|
adh->bOffsets = TRUE;
|
|
|
|
// set dlist array pointer structs, and copy over data
|
|
|
|
// dataPtr points to destination array block
|
|
dataPtr = (GLubyte *)adh + sizeof( ARRAY_DLIST_HDR );
|
|
offset = 0;
|
|
|
|
SETUP_ARRAY_DLIST_DATA_INDEXED( ENABLE_NORMAL, &adh->apNormal, &gc->apNormal, naSize );
|
|
SETUP_ARRAY_DLIST_DATA_INDEXED( ENABLE_COLOR, &adh->apColor, &gc->apColor, caSize);
|
|
SETUP_ARRAY_DLIST_DATA_INDEXED( ENABLE_INDEX, &adh->apIndex, &gc->apIndex, iaSize);
|
|
SETUP_ARRAY_DLIST_DATA_INDEXED( ENABLE_TEXCOORD, &adh->apTexCoord, &gc->apTexCoord, tcaSize);
|
|
SETUP_ARRAY_DLIST_DATA_INDEXED( ENABLE_EDGEFLAG, &adh->apEdgeFlag, &gc->apEdgeFlag, efaSize);
|
|
SETUP_ARRAY_DLIST_DATA_INDEXED( ENABLE_VERTEX, &adh->apVertex, &gc->apVertex, vaSize);
|
|
|
|
__glDlistAppendOp(gc, adh, __glle_DrawArraysEXT);
|
|
}
|