t_vb_normals.c revision 6dc85575000127630489b407c50a4b3ea87c9acb
1 2/* 3 * Mesa 3-D graphics library 4 * Version: 5.1 5 * 6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Keith Whitwell <keith@tungstengraphics.com> 27 */ 28 29 30#include "glheader.h" 31#include "colormac.h" 32#include "context.h" 33#include "macros.h" 34#include "imports.h" 35#include "mtypes.h" 36 37#include "math/m_xform.h" 38 39#include "t_context.h" 40#include "t_pipeline.h" 41 42 43 44struct normal_stage_data { 45 normal_func NormalTransform; 46 GLvector4f normal; 47}; 48 49#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr) 50 51 52 53 54static GLboolean run_normal_stage( GLcontext *ctx, 55 struct gl_pipeline_stage *stage ) 56{ 57 struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); 58 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 59 60 ASSERT(store->NormalTransform); 61 62 if (stage->changed_inputs) { 63 /* We can only use the display list's saved normal lengths if we've 64 * got a transformation matrix with uniform scaling. 65 */ 66 const GLfloat *lengths; 67 if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE) 68 lengths = NULL; 69 else 70 lengths = VB->NormalLengthPtr; 71 72 store->NormalTransform( ctx->ModelviewMatrixStack.Top, 73 ctx->_ModelViewInvScale, 74 VB->NormalPtr, /* input normals */ 75 lengths, 76 &store->normal ); /* resulting normals */ 77 } 78 79 VB->NormalPtr = &store->normal; 80 VB->NormalLengthPtr = 0; /* no longer valid */ 81 return GL_TRUE; 82} 83 84 85static GLboolean run_validate_normal_stage( GLcontext *ctx, 86 struct gl_pipeline_stage *stage ) 87{ 88 struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); 89 90 91 if (ctx->_NeedEyeCoords) { 92 GLuint transform = NORM_TRANSFORM_NO_ROT; 93 94 if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_GENERAL | 95 MAT_FLAG_ROTATION | 96 MAT_FLAG_GENERAL_3D | 97 MAT_FLAG_PERSPECTIVE)) 98 transform = NORM_TRANSFORM; 99 100 101 if (ctx->Transform.Normalize) { 102 store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE]; 103 } 104 else if (ctx->Transform.RescaleNormals && 105 ctx->_ModelViewInvScale != 1.0) { 106 store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE]; 107 } 108 else { 109 store->NormalTransform = _mesa_normal_tab[transform]; 110 } 111 } 112 else { 113 if (ctx->Transform.Normalize) { 114 store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE]; 115 } 116 else if (!ctx->Transform.RescaleNormals && 117 ctx->_ModelViewInvScale != 1.0) { 118 store->NormalTransform = _mesa_normal_tab[NORM_RESCALE]; 119 } 120 else { 121 store->NormalTransform = 0; 122 } 123 } 124 125 if (store->NormalTransform) { 126 stage->run = run_normal_stage; 127 return stage->run( ctx, stage ); 128 } else { 129 stage->active = GL_FALSE; /* !!! */ 130 return GL_TRUE; 131 } 132} 133 134 135static void check_normal_transform( GLcontext *ctx, 136 struct gl_pipeline_stage *stage ) 137{ 138 stage->active = !ctx->VertexProgram.Enabled && 139 (ctx->Light.Enabled || (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)); 140 141 /* Don't clobber the initialize function: 142 */ 143 if (stage->privatePtr) 144 stage->run = run_validate_normal_stage; 145} 146 147 148static GLboolean alloc_normal_data( GLcontext *ctx, 149 struct gl_pipeline_stage *stage ) 150{ 151 TNLcontext *tnl = TNL_CONTEXT(ctx); 152 struct normal_stage_data *store; 153 stage->privatePtr = MALLOC(sizeof(*store)); 154 store = NORMAL_STAGE_DATA(stage); 155 if (!store) 156 return GL_FALSE; 157 158 _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 ); 159 160 /* Now run the stage. 161 */ 162 stage->run = run_validate_normal_stage; 163 return stage->run( ctx, stage ); 164} 165 166 167 168static void free_normal_data( struct gl_pipeline_stage *stage ) 169{ 170 struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); 171 if (store) { 172 _mesa_vector4f_free( &store->normal ); 173 FREE( store ); 174 stage->privatePtr = NULL; 175 } 176} 177 178#define _TNL_NEW_NORMAL_TRANSFORM (_NEW_MODELVIEW| \ 179 _NEW_TRANSFORM| \ 180 _MESA_NEW_NEED_NORMALS| \ 181 _MESA_NEW_NEED_EYE_COORDS) 182 183 184 185const struct gl_pipeline_stage _tnl_normal_transform_stage = 186{ 187 "normal transform", /* name */ 188 _TNL_NEW_NORMAL_TRANSFORM, /* re-check */ 189 _TNL_NEW_NORMAL_TRANSFORM, /* re-run */ 190 GL_FALSE, /* active? */ 191 VERT_BIT_NORMAL, /* inputs */ 192 VERT_BIT_NORMAL, /* outputs */ 193 0, /* changed_inputs */ 194 NULL, /* private data */ 195 free_normal_data, /* destructor */ 196 check_normal_transform, /* check */ 197 alloc_normal_data /* run -- initially set to alloc */ 198}; 199