1cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell/* 2cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * Mesa 3-D graphics library 3cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * 4a2ea606377ed5679dc513eabcf2d398216b47d61Michal Krol * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 5cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * 6cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a 7cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * copy of this software and associated documentation files (the "Software"), 8cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * to deal in the Software without restriction, including without limitation 9cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * and/or sell copies of the Software, and to permit persons to whom the 11cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * Software is furnished to do so, subject to the following conditions: 12cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * 13cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * The above copyright notice and this permission notice shall be included 14cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * in all copies or substantial portions of the Software. 15cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * 16cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 193d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 203d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 213d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 223d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER DEALINGS IN THE SOFTWARE. 23cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell * 2422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * Authors: 25877128505431adaf817dc8069172ebe4a1cdf5d8José Fonseca * Keith Whitwell <keithw@vmware.com> 26cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell */ 27cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 28cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 29bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h" 30bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/macros.h" 31bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/imports.h" 32bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/mtypes.h" 33cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 34cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell#include "math/m_xform.h" 35cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 36cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell#include "t_context.h" 37cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell#include "t_pipeline.h" 38cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 39cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 40cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwellstruct normal_stage_data { 415e23af22f708a66695c0e44e599c26f02d8d4dcdGareth Hughes normal_func NormalTransform; 42bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul GLvector4f normal; 43cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell}; 44cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 45b51b0a847d7e7daaea69f77ab569086ef81c24a2Brian Paul#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr) 46cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 47cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 48b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paulstatic GLboolean 49f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergrun_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage) 50cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell{ 51cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); 52cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 536f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell const GLfloat *lengths; 54cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 556f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell if (!store->NormalTransform) 566f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell return GL_TRUE; 576f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell 586f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell /* We can only use the display list's saved normal lengths if we've 596f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell * got a transformation matrix with uniform scaling. 606f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell */ 61049e320f46f3a3daaa36ef67cc680dc504c124d5Brian Paul if (_math_matrix_is_general_scale(ctx->ModelviewMatrixStack.Top)) 626f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell lengths = NULL; 636f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell else 646f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell lengths = VB->NormalLengthPtr; 656f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell 666f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell store->NormalTransform( ctx->ModelviewMatrixStack.Top, 676f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell ctx->_ModelViewInvScale, 6862e1fae858509615c6e54e0b9388cfa2691a5919Brian Paul VB->AttribPtr[_TNL_ATTRIB_NORMAL], /* input normals */ 696f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell lengths, 706f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell &store->normal ); /* resulting normals */ 716f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell 7262e1fae858509615c6e54e0b9388cfa2691a5919Brian Paul if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count > 1) { 73b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul store->normal.stride = 4 * sizeof(GLfloat); 746f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell } 756f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell else { 766f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell store->normal.stride = 0; 77c030a18ea6a07f10fc0873695fb34c11d8239423Brian Paul } 78cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 7962e1fae858509615c6e54e0b9388cfa2691a5919Brian Paul VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &store->normal; 80790734045b69c47b1525fbf9106a7ca5a8eb7416Keith Whitwell 81b97e478fe90f612041e27852eb8c95f45467bde8Keith Whitwell VB->NormalLengthPtr = NULL; /* no longer valid */ 82cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell return GL_TRUE; 83cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell} 84cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 85cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 86b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul/** 87b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * Examine current GL state and set the store->NormalTransform pointer 88b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * to point to the appropriate normal transformation routine. 89b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul */ 90b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paulstatic void 91f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergvalidate_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage) 92cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell{ 93cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); 94cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 95a328e469d328f8b6fd5afdfc21d576fa1a2c43fcBrian Paul if (ctx->VertexProgram._Current || 966f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell (!ctx->Light.Enabled && 976f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell !(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) { 986f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell store->NormalTransform = NULL; 996f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell return; 1006f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell } 101b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul 102cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell if (ctx->_NeedEyeCoords) { 103b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul /* Eye coordinates are needed, for whatever reasons. 104b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * Do lighting in eye coordinates, as the GL spec says. 105b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul */ 106cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell GLuint transform = NORM_TRANSFORM_NO_ROT; 107cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 108049e320f46f3a3daaa36ef67cc680dc504c124d5Brian Paul if (_math_matrix_has_rotation(ctx->ModelviewMatrixStack.Top)) { 109b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul /* need to do full (3x3) matrix transform */ 110cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell transform = NORM_TRANSFORM; 111b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul } 11222144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes 113cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell if (ctx->Transform.Normalize) { 114188f2949eaf181f4aab041a6dad26fa76e746eeeBrian Paul store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE]; 115cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 116cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell else if (ctx->Transform.RescaleNormals && 117c92b2a1d7b286de8641512970a87c94809fbbc3fMatt Turner ctx->_ModelViewInvScale != 1.0F) { 118188f2949eaf181f4aab041a6dad26fa76e746eeeBrian Paul store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE]; 119cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 120cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell else { 121188f2949eaf181f4aab041a6dad26fa76e746eeeBrian Paul store->NormalTransform = _mesa_normal_tab[transform]; 122cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 123cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 124cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell else { 125b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul /* We don't need eye coordinates. 126b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * Do lighting in object coordinates. Thus, we don't need to fully 127b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * transform normal vectors (just leave them in object coordinates) 128b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * but we still need to do normalization/rescaling if enabled. 129b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul */ 130cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell if (ctx->Transform.Normalize) { 131188f2949eaf181f4aab041a6dad26fa76e746eeeBrian Paul store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE]; 132cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 133cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell else if (!ctx->Transform.RescaleNormals && 134c92b2a1d7b286de8641512970a87c94809fbbc3fMatt Turner ctx->_ModelViewInvScale != 1.0F) { 135188f2949eaf181f4aab041a6dad26fa76e746eeeBrian Paul store->NormalTransform = _mesa_normal_tab[NORM_RESCALE]; 136cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 137cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell else { 138b97e478fe90f612041e27852eb8c95f45467bde8Keith Whitwell store->NormalTransform = NULL; 139cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 140cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 141cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell} 142cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 143cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 144b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul/** 145b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * Allocate stage's private data (storage for transformed normals). 146b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul */ 147b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paulstatic GLboolean 148f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergalloc_normal_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage) 149cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell{ 150cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell TNLcontext *tnl = TNL_CONTEXT(ctx); 151cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell struct normal_stage_data *store; 152b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul 15332f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg stage->privatePtr = malloc(sizeof(*store)); 154cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell store = NORMAL_STAGE_DATA(stage); 155cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell if (!store) 156cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell return GL_FALSE; 157cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 158bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 ); 1596f973f33679e034b7cb63806f1ddfabdbdd70123Keith Whitwell return GL_TRUE; 160cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell} 161cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 162cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 163b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul/** 164b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul * Free stage's private data. 165b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul */ 166b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paulstatic void 167b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paulfree_normal_data(struct tnl_pipeline_stage *stage) 168cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell{ 169cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); 170cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell if (store) { 171bd1a9dacf6a45e6aa6954eeb490d55ebcc80ace8Brian Paul _mesa_vector4f_free( &store->normal ); 17232f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg free( store ); 173b51b0a847d7e7daaea69f77ab569086ef81c24a2Brian Paul stage->privatePtr = NULL; 174cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell } 175cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell} 176cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 177cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell 178ae0eaf93e092ac8e8b1c98f3e986de96940663faKeith Whitwellconst struct tnl_pipeline_stage _tnl_normal_transform_stage = 17922144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes{ 18086b842790b720cd6b1499ce8edca8a4e9c8dc029Brian Paul "normal transform", /* name */ 181b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul NULL, /* privatePtr */ 182b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul alloc_normal_data, /* create */ 183b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul free_normal_data, /* destroy */ 184b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul validate_normal_stage, /* validate */ 185b6c0d753fa6c68ae1cd27caa92627db238f877d2Brian Paul run_normal_stage /* run */ 186cab974cf6c2dbfbf5dd5d291e1aae0f8eeb34290Keith Whitwell}; 187