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