#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
#include "math/m_xform.h"
#include "t_context.h"
#include "t_pipeline.h"
struct normal_stage_data {
normal_func NormalTransform;
GLvector4f normal;
};
#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
static GLboolean run_normal_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
ASSERT(store->NormalTransform);
if (stage->changed_inputs) {
const GLfloat *lengths;
if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE)
lengths = NULL;
else
lengths = VB->NormalLengthPtr;
store->NormalTransform( ctx->ModelviewMatrixStack.Top,
ctx->_ModelViewInvScale,
VB->NormalPtr,
lengths,
&store->normal );
}
VB->NormalPtr = &store->normal;
VB->NormalLengthPtr = 0;
return GL_TRUE;
}
static GLboolean run_validate_normal_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
ASSERT(ctx->_NeedNormals);
if (ctx->_NeedEyeCoords) {
GLuint transform = NORM_TRANSFORM_NO_ROT;
if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_GENERAL |
MAT_FLAG_ROTATION |
MAT_FLAG_GENERAL_3D |
MAT_FLAG_PERSPECTIVE))
transform = NORM_TRANSFORM;
if (ctx->Transform.Normalize) {
store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
}
else if (ctx->Transform.RescaleNormals &&
ctx->_ModelViewInvScale != 1.0) {
store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
}
else {
store->NormalTransform = _mesa_normal_tab[transform];
}
}
else {
if (ctx->Transform.Normalize) {
store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
}
else if (!ctx->Transform.RescaleNormals &&
ctx->_ModelViewInvScale != 1.0) {
store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
}
else {
store->NormalTransform = 0;
}
}
if (store->NormalTransform) {
stage->run = run_normal_stage;
return stage->run( ctx, stage );
} else {
stage->active = GL_FALSE;
return GL_TRUE;
}
}
static void check_normal_transform( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
stage->active = ctx->_NeedNormals && !ctx->VertexProgram.Enabled;
if (stage->privatePtr)
stage->run = run_validate_normal_stage;
}
static GLboolean alloc_normal_data( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct normal_stage_data *store;
stage->privatePtr = MALLOC(sizeof(*store));
store = NORMAL_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
_mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
stage->run = run_validate_normal_stage;
return stage->run( ctx, stage );
}
static void free_normal_data( struct gl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
if (store) {
_mesa_vector4f_free( &store->normal );
FREE( store );
stage->privatePtr = NULL;
}
}
#define _TNL_NEW_NORMAL_TRANSFORM (_NEW_MODELVIEW| \
_NEW_TRANSFORM| \
_MESA_NEW_NEED_NORMALS| \
_MESA_NEW_NEED_EYE_COORDS)
const struct gl_pipeline_stage _tnl_normal_transform_stage =
{
"normal transform",
_TNL_NEW_NORMAL_TRANSFORM,
_TNL_NEW_NORMAL_TRANSFORM,
GL_FALSE,
VERT_BIT_NORMAL,
VERT_BIT_NORMAL,
0,
NULL,
free_normal_data,
check_normal_transform,
alloc_normal_data
};