2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keithw@vmware.com>
29 #include "main/glheader.h"
30 #include "main/macros.h"
31 #include "main/imports.h"
32 #include "main/mtypes.h"
34 #include "math/m_xform.h"
36 #include "t_context.h"
37 #include "t_pipeline.h"
40 struct normal_stage_data
{
41 normal_func NormalTransform
;
45 #define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
49 run_normal_stage(struct gl_context
*ctx
, struct tnl_pipeline_stage
*stage
)
51 struct normal_stage_data
*store
= NORMAL_STAGE_DATA(stage
);
52 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
53 const GLfloat
*lengths
;
55 if (!store
->NormalTransform
)
58 /* We can only use the display list's saved normal lengths if we've
59 * got a transformation matrix with uniform scaling.
61 if (_math_matrix_is_general_scale(ctx
->ModelviewMatrixStack
.Top
))
64 lengths
= VB
->NormalLengthPtr
;
66 store
->NormalTransform( ctx
->ModelviewMatrixStack
.Top
,
67 ctx
->_ModelViewInvScale
,
68 VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
], /* input normals */
70 &store
->normal
); /* resulting normals */
72 if (VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
]->count
> 1) {
73 store
->normal
.stride
= 4 * sizeof(GLfloat
);
76 store
->normal
.stride
= 0;
79 VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
] = &store
->normal
;
81 VB
->NormalLengthPtr
= NULL
; /* no longer valid */
87 * Examine current GL state and set the store->NormalTransform pointer
88 * to point to the appropriate normal transformation routine.
91 validate_normal_stage(struct gl_context
*ctx
, struct tnl_pipeline_stage
*stage
)
93 struct normal_stage_data
*store
= NORMAL_STAGE_DATA(stage
);
95 if (ctx
->VertexProgram
._Current
||
96 (!ctx
->Light
.Enabled
&&
97 !(ctx
->Texture
._GenFlags
& TEXGEN_NEED_NORMALS
))) {
98 store
->NormalTransform
= NULL
;
102 if (ctx
->_NeedEyeCoords
) {
103 /* Eye coordinates are needed, for whatever reasons.
104 * Do lighting in eye coordinates, as the GL spec says.
106 GLuint transform
= NORM_TRANSFORM_NO_ROT
;
108 if (_math_matrix_has_rotation(ctx
->ModelviewMatrixStack
.Top
)) {
109 /* need to do full (3x3) matrix transform */
110 transform
= NORM_TRANSFORM
;
113 if (ctx
->Transform
.Normalize
) {
114 store
->NormalTransform
= _mesa_normal_tab
[transform
| NORM_NORMALIZE
];
116 else if (ctx
->Transform
.RescaleNormals
&&
117 ctx
->_ModelViewInvScale
!= 1.0) {
118 store
->NormalTransform
= _mesa_normal_tab
[transform
| NORM_RESCALE
];
121 store
->NormalTransform
= _mesa_normal_tab
[transform
];
125 /* We don't need eye coordinates.
126 * Do lighting in object coordinates. Thus, we don't need to fully
127 * transform normal vectors (just leave them in object coordinates)
128 * but we still need to do normalization/rescaling if enabled.
130 if (ctx
->Transform
.Normalize
) {
131 store
->NormalTransform
= _mesa_normal_tab
[NORM_NORMALIZE
];
133 else if (!ctx
->Transform
.RescaleNormals
&&
134 ctx
->_ModelViewInvScale
!= 1.0) {
135 store
->NormalTransform
= _mesa_normal_tab
[NORM_RESCALE
];
138 store
->NormalTransform
= NULL
;
145 * Allocate stage's private data (storage for transformed normals).
148 alloc_normal_data(struct gl_context
*ctx
, struct tnl_pipeline_stage
*stage
)
150 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
151 struct normal_stage_data
*store
;
153 stage
->privatePtr
= malloc(sizeof(*store
));
154 store
= NORMAL_STAGE_DATA(stage
);
158 _mesa_vector4f_alloc( &store
->normal
, 0, tnl
->vb
.Size
, 32 );
164 * Free stage's private data.
167 free_normal_data(struct tnl_pipeline_stage
*stage
)
169 struct normal_stage_data
*store
= NORMAL_STAGE_DATA(stage
);
171 _mesa_vector4f_free( &store
->normal
);
173 stage
->privatePtr
= NULL
;
178 const struct tnl_pipeline_stage _tnl_normal_transform_stage
=
180 "normal transform", /* name */
181 NULL
, /* privatePtr */
182 alloc_normal_data
, /* create */
183 free_normal_data
, /* destroy */
184 validate_normal_stage
, /* validate */
185 run_normal_stage
/* run */