1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Mesa 3-D graphics library
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Version:  6.5
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be included
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in all copies or substantial portions of the Software.
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Authors:
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    Keith Whitwell <keith@tungstengraphics.com>
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/glheader.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/colormac.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/macros.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/imports.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/mtypes.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "math/m_xform.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "t_context.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "t_pipeline.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct normal_stage_data {
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   normal_func NormalTransform;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLvector4f normal;
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic GLboolean
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgrun_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const GLfloat *lengths;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!store->NormalTransform)
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return GL_TRUE;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* We can only use the display list's saved normal lengths if we've
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * got a transformation matrix with uniform scaling.
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (_math_matrix_is_general_scale(ctx->ModelviewMatrixStack.Top))
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      lengths = NULL;
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      lengths = VB->NormalLengthPtr;
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   store->NormalTransform( ctx->ModelviewMatrixStack.Top,
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			   ctx->_ModelViewInvScale,
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			   VB->AttribPtr[_TNL_ATTRIB_NORMAL],  /* input normals */
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			   lengths,
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			   &store->normal ); /* resulting normals */
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count > 1) {
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      store->normal.stride = 4 * sizeof(GLfloat);
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      store->normal.stride = 0;
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &store->normal;
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   VB->NormalLengthPtr = NULL;	/* no longer valid */
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return GL_TRUE;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Examine current GL state and set the store->NormalTransform pointer
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to point to the appropriate normal transformation routine.
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvalidate_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->VertexProgram._Current ||
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       (!ctx->Light.Enabled &&
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	!(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) {
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      store->NormalTransform = NULL;
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->_NeedEyeCoords) {
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Eye coordinates are needed, for whatever reasons.
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * Do lighting in eye coordinates, as the GL spec says.
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      GLuint transform = NORM_TRANSFORM_NO_ROT;
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (_math_matrix_has_rotation(ctx->ModelviewMatrixStack.Top)) {
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* need to do full (3x3) matrix transform */
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 transform = NORM_TRANSFORM;
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ctx->Transform.Normalize) {
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (ctx->Transform.RescaleNormals &&
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               ctx->_ModelViewInvScale != 1.0) {
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 store->NormalTransform = _mesa_normal_tab[transform];
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* We don't need eye coordinates.
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * Do lighting in object coordinates.  Thus, we don't need to fully
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * transform normal vectors (just leave them in object coordinates)
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * but we still need to do normalization/rescaling if enabled.
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ctx->Transform.Normalize) {
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (!ctx->Transform.RescaleNormals &&
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       ctx->_ModelViewInvScale != 1.0) {
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else {
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 store->NormalTransform = NULL;
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Allocate stage's private data (storage for transformed normals).
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic GLboolean
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgalloc_normal_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   TNLcontext *tnl = TNL_CONTEXT(ctx);
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct normal_stage_data *store;
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   stage->privatePtr = malloc(sizeof(*store));
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   store = NORMAL_STAGE_DATA(stage);
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!store)
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return GL_FALSE;
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return GL_TRUE;
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Free stage's private data.
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfree_normal_data(struct tnl_pipeline_stage *stage)
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (store) {
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_vector4f_free( &store->normal );
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      free( store );
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      stage->privatePtr = NULL;
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconst struct tnl_pipeline_stage _tnl_normal_transform_stage =
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   "normal transform",		/* name */
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   NULL,			/* privatePtr */
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   alloc_normal_data,		/* create */
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free_normal_data,		/* destroy */
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   validate_normal_stage,	/* validate */
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   run_normal_stage             /* run */
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
188