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