Home | History | Annotate | Download | only in tnl
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5
      4  *
      5  * Copyright (C) 1999-2006  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 (at) tungstengraphics.com>
     26  */
     27 
     28 
     29 #include "main/glheader.h"
     30 #include "main/colormac.h"
     31 #include "main/macros.h"
     32 #include "main/imports.h"
     33 #include "main/mtypes.h"
     34 
     35 #include "math/m_xform.h"
     36 
     37 #include "t_context.h"
     38 #include "t_pipeline.h"
     39 
     40 
     41 struct normal_stage_data {
     42    normal_func NormalTransform;
     43    GLvector4f normal;
     44 };
     45 
     46 #define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
     47 
     48 
     49 static GLboolean
     50 run_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
     51 {
     52    struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
     53    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
     54    const GLfloat *lengths;
     55 
     56    if (!store->NormalTransform)
     57       return GL_TRUE;
     58 
     59    /* We can only use the display list's saved normal lengths if we've
     60     * got a transformation matrix with uniform scaling.
     61     */
     62    if (_math_matrix_is_general_scale(ctx->ModelviewMatrixStack.Top))
     63       lengths = NULL;
     64    else
     65       lengths = VB->NormalLengthPtr;
     66 
     67    store->NormalTransform( ctx->ModelviewMatrixStack.Top,
     68 			   ctx->_ModelViewInvScale,
     69 			   VB->AttribPtr[_TNL_ATTRIB_NORMAL],  /* input normals */
     70 			   lengths,
     71 			   &store->normal ); /* resulting normals */
     72 
     73    if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count > 1) {
     74       store->normal.stride = 4 * sizeof(GLfloat);
     75    }
     76    else {
     77       store->normal.stride = 0;
     78    }
     79 
     80    VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &store->normal;
     81 
     82    VB->NormalLengthPtr = NULL;	/* no longer valid */
     83    return GL_TRUE;
     84 }
     85 
     86 
     87 /**
     88  * Examine current GL state and set the store->NormalTransform pointer
     89  * to point to the appropriate normal transformation routine.
     90  */
     91 static void
     92 validate_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
     93 {
     94    struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
     95 
     96    if (ctx->VertexProgram._Current ||
     97        (!ctx->Light.Enabled &&
     98 	!(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) {
     99       store->NormalTransform = NULL;
    100       return;
    101    }
    102 
    103    if (ctx->_NeedEyeCoords) {
    104       /* Eye coordinates are needed, for whatever reasons.
    105        * Do lighting in eye coordinates, as the GL spec says.
    106        */
    107       GLuint transform = NORM_TRANSFORM_NO_ROT;
    108 
    109       if (_math_matrix_has_rotation(ctx->ModelviewMatrixStack.Top)) {
    110          /* need to do full (3x3) matrix transform */
    111 	 transform = NORM_TRANSFORM;
    112       }
    113 
    114       if (ctx->Transform.Normalize) {
    115 	 store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
    116       }
    117       else if (ctx->Transform.RescaleNormals &&
    118                ctx->_ModelViewInvScale != 1.0) {
    119 	 store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
    120       }
    121       else {
    122 	 store->NormalTransform = _mesa_normal_tab[transform];
    123       }
    124    }
    125    else {
    126       /* We don't need eye coordinates.
    127        * Do lighting in object coordinates.  Thus, we don't need to fully
    128        * transform normal vectors (just leave them in object coordinates)
    129        * but we still need to do normalization/rescaling if enabled.
    130        */
    131       if (ctx->Transform.Normalize) {
    132 	 store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
    133       }
    134       else if (!ctx->Transform.RescaleNormals &&
    135 	       ctx->_ModelViewInvScale != 1.0) {
    136 	 store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
    137       }
    138       else {
    139 	 store->NormalTransform = NULL;
    140       }
    141    }
    142 }
    143 
    144 
    145 /**
    146  * Allocate stage's private data (storage for transformed normals).
    147  */
    148 static GLboolean
    149 alloc_normal_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
    150 {
    151    TNLcontext *tnl = TNL_CONTEXT(ctx);
    152    struct normal_stage_data *store;
    153 
    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    return GL_TRUE;
    161 }
    162 
    163 
    164 /**
    165  * Free stage's private data.
    166  */
    167 static void
    168 free_normal_data(struct tnl_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 
    179 const struct tnl_pipeline_stage _tnl_normal_transform_stage =
    180 {
    181    "normal transform",		/* name */
    182    NULL,			/* privatePtr */
    183    alloc_normal_data,		/* create */
    184    free_normal_data,		/* destroy */
    185    validate_normal_stage,	/* validate */
    186    run_normal_stage             /* run */
    187 };
    188