Header file clean-up:
[mesa.git] / src / mesa / tnl / t_vb_normals.c
1 /* $Id: t_vb_normals.c,v 1.16 2002/10/24 23:57:25 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Keith Whitwell <keithw@valinux.com>
28 */
29
30
31 #include "glheader.h"
32 #include "colormac.h"
33 #include "context.h"
34 #include "macros.h"
35 #include "imports.h"
36 #include "mmath.h"
37 #include "mtypes.h"
38
39 #include "math/m_xform.h"
40
41 #include "t_context.h"
42 #include "t_pipeline.h"
43
44
45
46 struct normal_stage_data {
47 normal_func NormalTransform;
48 GLvector4f normal;
49 };
50
51 #define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
52
53
54
55
56 static GLboolean run_normal_stage( GLcontext *ctx,
57 struct gl_pipeline_stage *stage )
58 {
59 struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
60 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
61
62 ASSERT(store->NormalTransform);
63
64 if (stage->changed_inputs) {
65 /* We can only use the display list's saved normal lengths if we've
66 * got a transformation matrix with uniform scaling.
67 */
68 const GLfloat *lengths;
69 if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE)
70 lengths = NULL;
71 else
72 lengths = VB->NormalLengthPtr;
73
74 store->NormalTransform( ctx->ModelviewMatrixStack.Top,
75 ctx->_ModelViewInvScale,
76 VB->NormalPtr, /* input normals */
77 lengths,
78 &store->normal ); /* resulting normals */
79 }
80
81 VB->NormalPtr = &store->normal;
82 VB->NormalLengthPtr = 0; /* no longer valid */
83 return GL_TRUE;
84 }
85
86
87 static GLboolean run_validate_normal_stage( GLcontext *ctx,
88 struct gl_pipeline_stage *stage )
89 {
90 struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
91
92 ASSERT(ctx->_NeedNormals);
93
94 if (ctx->_NeedEyeCoords) {
95 GLuint transform = NORM_TRANSFORM_NO_ROT;
96
97 if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_GENERAL |
98 MAT_FLAG_ROTATION |
99 MAT_FLAG_GENERAL_3D |
100 MAT_FLAG_PERSPECTIVE))
101 transform = NORM_TRANSFORM;
102
103
104 if (ctx->Transform.Normalize) {
105 store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
106 }
107 else if (ctx->Transform.RescaleNormals &&
108 ctx->_ModelViewInvScale != 1.0) {
109 store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
110 }
111 else {
112 store->NormalTransform = _mesa_normal_tab[transform];
113 }
114 }
115 else {
116 if (ctx->Transform.Normalize) {
117 store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
118 }
119 else if (!ctx->Transform.RescaleNormals &&
120 ctx->_ModelViewInvScale != 1.0) {
121 store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
122 }
123 else {
124 store->NormalTransform = 0;
125 }
126 }
127
128 if (store->NormalTransform) {
129 stage->run = run_normal_stage;
130 return stage->run( ctx, stage );
131 } else {
132 stage->active = GL_FALSE; /* !!! */
133 return GL_TRUE;
134 }
135 }
136
137
138 static void check_normal_transform( GLcontext *ctx,
139 struct gl_pipeline_stage *stage )
140 {
141 stage->active = ctx->_NeedNormals && !ctx->VertexProgram.Enabled;
142 /* Don't clobber the initialize function:
143 */
144 if (stage->privatePtr)
145 stage->run = run_validate_normal_stage;
146 }
147
148
149 static GLboolean alloc_normal_data( GLcontext *ctx,
150 struct gl_pipeline_stage *stage )
151 {
152 TNLcontext *tnl = TNL_CONTEXT(ctx);
153 struct normal_stage_data *store;
154 stage->privatePtr = MALLOC(sizeof(*store));
155 store = NORMAL_STAGE_DATA(stage);
156 if (!store)
157 return GL_FALSE;
158
159 _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
160
161 /* Now run the stage.
162 */
163 stage->run = run_validate_normal_stage;
164 return stage->run( ctx, stage );
165 }
166
167
168
169 static void free_normal_data( struct gl_pipeline_stage *stage )
170 {
171 struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
172 if (store) {
173 _mesa_vector4f_free( &store->normal );
174 FREE( store );
175 stage->privatePtr = NULL;
176 }
177 }
178
179 #define _TNL_NEW_NORMAL_TRANSFORM (_NEW_MODELVIEW| \
180 _NEW_TRANSFORM| \
181 _MESA_NEW_NEED_NORMALS| \
182 _MESA_NEW_NEED_EYE_COORDS)
183
184
185
186 const struct gl_pipeline_stage _tnl_normal_transform_stage =
187 {
188 "normal transform", /* name */
189 _TNL_NEW_NORMAL_TRANSFORM, /* re-check */
190 _TNL_NEW_NORMAL_TRANSFORM, /* re-run */
191 GL_FALSE, /* active? */
192 VERT_BIT_NORMAL, /* inputs */
193 VERT_BIT_NORMAL, /* outputs */
194 0, /* changed_inputs */
195 NULL, /* private data */
196 free_normal_data, /* destructor */
197 check_normal_transform, /* check */
198 alloc_normal_data /* run -- initially set to alloc */
199 };