2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
25 * Keith Whitwell <keith@tungstengraphics.com>
29 #include "main/glheader.h"
30 #include "main/colormac.h"
31 #include "main/context.h"
32 #include "main/macros.h"
33 #include "main/imports.h"
34 #include "main/mtypes.h"
36 #include "math/m_xform.h"
38 #include "t_context.h"
39 #include "t_pipeline.h"
42 struct normal_stage_data
{
43 normal_func NormalTransform
;
47 #define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
51 run_normal_stage(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
53 struct normal_stage_data
*store
= NORMAL_STAGE_DATA(stage
);
54 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
55 const GLfloat
*lengths
;
57 if (!store
->NormalTransform
)
60 /* We can only use the display list's saved normal lengths if we've
61 * got a transformation matrix with uniform scaling.
63 if (_math_matrix_is_general_scale(ctx
->ModelviewMatrixStack
.Top
))
66 lengths
= VB
->NormalLengthPtr
;
68 store
->NormalTransform( ctx
->ModelviewMatrixStack
.Top
,
69 ctx
->_ModelViewInvScale
,
70 VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
], /* input normals */
72 &store
->normal
); /* resulting normals */
74 if (VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
]->count
> 1) {
75 store
->normal
.stride
= 4 * sizeof(GLfloat
);
78 store
->normal
.stride
= 0;
81 VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
] = &store
->normal
;
83 VB
->NormalLengthPtr
= NULL
; /* no longer valid */
89 * Examine current GL state and set the store->NormalTransform pointer
90 * to point to the appropriate normal transformation routine.
93 validate_normal_stage(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
95 struct normal_stage_data
*store
= NORMAL_STAGE_DATA(stage
);
97 if (ctx
->VertexProgram
._Current
||
98 (!ctx
->Light
.Enabled
&&
99 !(ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
))) {
100 store
->NormalTransform
= NULL
;
104 if (ctx
->_NeedEyeCoords
) {
105 /* Eye coordinates are needed, for whatever reasons.
106 * Do lighting in eye coordinates, as the GL spec says.
108 GLuint transform
= NORM_TRANSFORM_NO_ROT
;
110 if (_math_matrix_has_rotation(ctx
->ModelviewMatrixStack
.Top
)) {
111 /* need to do full (3x3) matrix transform */
112 transform
= NORM_TRANSFORM
;
115 if (ctx
->Transform
.Normalize
) {
116 store
->NormalTransform
= _mesa_normal_tab
[transform
| NORM_NORMALIZE
];
118 else if (ctx
->Transform
.RescaleNormals
&&
119 ctx
->_ModelViewInvScale
!= 1.0) {
120 store
->NormalTransform
= _mesa_normal_tab
[transform
| NORM_RESCALE
];
123 store
->NormalTransform
= _mesa_normal_tab
[transform
];
127 /* We don't need eye coordinates.
128 * Do lighting in object coordinates. Thus, we don't need to fully
129 * transform normal vectors (just leave them in object coordinates)
130 * but we still need to do normalization/rescaling if enabled.
132 if (ctx
->Transform
.Normalize
) {
133 store
->NormalTransform
= _mesa_normal_tab
[NORM_NORMALIZE
];
135 else if (!ctx
->Transform
.RescaleNormals
&&
136 ctx
->_ModelViewInvScale
!= 1.0) {
137 store
->NormalTransform
= _mesa_normal_tab
[NORM_RESCALE
];
140 store
->NormalTransform
= NULL
;
147 * Allocate stage's private data (storage for transformed normals).
150 alloc_normal_data(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
152 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
153 struct normal_stage_data
*store
;
155 stage
->privatePtr
= _mesa_malloc(sizeof(*store
));
156 store
= NORMAL_STAGE_DATA(stage
);
160 _mesa_vector4f_alloc( &store
->normal
, 0, tnl
->vb
.Size
, 32 );
166 * Free stage's private data.
169 free_normal_data(struct tnl_pipeline_stage
*stage
)
171 struct normal_stage_data
*store
= NORMAL_STAGE_DATA(stage
);
173 _mesa_vector4f_free( &store
->normal
);
175 stage
->privatePtr
= NULL
;
180 const struct tnl_pipeline_stage _tnl_normal_transform_stage
=
182 "normal transform", /* name */
183 NULL
, /* privatePtr */
184 alloc_normal_data
, /* create */
185 free_normal_data
, /* destroy */
186 validate_normal_stage
, /* validate */
187 run_normal_stage
/* run */