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