added null pointer check in tnl_copy_to_current()
[mesa.git] / src / mesa / tnl / t_vb_light.c
index 043eb7302fcb98bb4e79f41b7483d4811a04c419..86755486343dcbcfa87b0c382bb1de5b2e365b5d 100644 (file)
@@ -1,10 +1,9 @@
-/* $Id: t_vb_light.c,v 1.2 2000/12/27 19:57:37 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  5.1
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 #include "colormac.h"
 #include "light.h"
 #include "macros.h"
-#include "mem.h"
-#include "mmath.h"
+#include "imports.h"
 #include "simple_list.h"
 #include "mtypes.h"
 
+#include "math/m_translate.h"
+
 #include "t_context.h"
 #include "t_pipeline.h"
 
@@ -49,14 +49,50 @@ typedef void (*light_func)( GLcontext *ctx,
                            GLvector4f *input );
 
 struct light_stage_data {
-   GLvector4ub LitColor[2];
+   struct gl_client_array FloatColor; 
+   struct gl_client_array LitColor[2];
+   struct gl_client_array LitSecondary[2];
    GLvector1ui LitIndex[2];
-   GLvector4ub LitSecondary[2];
-
    light_func *light_func_tab;
 };
 
-#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->private))
+
+#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr))
+
+
+static void import_color_material( GLcontext *ctx,
+                                  struct gl_pipeline_stage *stage )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct gl_client_array *to = &LIGHT_STAGE_DATA(stage)->FloatColor;
+   struct gl_client_array *from = VB->ColorPtr[0];
+   GLuint count = VB->Count;
+
+   if (!to->Ptr) {
+      to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 );
+      to->Type = GL_FLOAT;
+   }
+
+   /* No need to transform the same value 3000 times.
+    */
+   if (!from->StrideB) {
+      to->StrideB = 0;
+      count = 1;
+   }
+   else
+      to->StrideB = 4 * sizeof(GLfloat);
+   
+   _math_trans_4f( (GLfloat (*)[4]) to->Ptr,
+                  from->Ptr,
+                  from->StrideB,
+                  from->Type,
+                  from->Size,
+                  0,
+                  count);
+
+   VB->ColorPtr[0] = to;
+}
+
 
 /* Tables for all the shading functions.
  */
@@ -125,27 +161,33 @@ static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
    GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
    GLuint ind;
 
+/*     _tnl_print_vert_flags( __FUNCTION__, stage->changed_inputs ); */
+
    /* Make sure we can talk about elements 0..2 in the vector we are
-    * lighting.  TODO:  Don't repeat this in CVA!
+    * lighting.
     */
-   if (input->size <= 2) {
-      if (input->flags & VEC_NOT_WRITEABLE) {
-        ASSERT(VB->importable_data & VERT_OBJ);
-        VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE );
-        input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
-        ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0);
-      }
+   if (stage->changed_inputs & (VERT_BIT_EYE|VERT_BIT_POS)) {
+      if (input->size <= 2) {
+        if (input->flags & VEC_NOT_WRITEABLE) {
+           ASSERT(VB->importable_data & VERT_BIT_POS);
+
+           VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
+           input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
+
+           ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0);
+        }
 
-      gl_vector4f_clean_elem(input, VB->Count, 2);
+        _mesa_vector4f_clean_elem(input, VB->Count, 2);
+      }
    }
-      
+
    if (VB->Flag)
       ind = LIGHT_FLAGS;
-   else 
+   else
       ind = 0;
 
-   /* The individual tabs know about replaying side-effects vs. full
-    * re-execution.
+   /* The individual functions know about replaying side-effects
+    * vs. full re-execution. 
     */
    store->light_func_tab[ind]( ctx, VB, stage, input );
 
@@ -155,33 +197,32 @@ static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
 
 /* Called in place of do_lighting when the light table may have changed.
  */
-static GLboolean run_validate_lighting( GLcontext *ctx, 
+static GLboolean run_validate_lighting( GLcontext *ctx,
                                        struct gl_pipeline_stage *stage )
 {
    GLuint ind = 0;
-   light_func *tab;   
-   
-   if (ctx->Visual.RGBAflag) {
+   light_func *tab;
+
+   if (ctx->Visual.rgbMode) {
       if (ctx->Light._NeedVertices) {
-        if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) 
+        if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
            tab = _tnl_light_spec_tab;
         else
-           tab = _tnl_light_tab;        
-      }  
+           tab = _tnl_light_tab;
+      }
       else {
         if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
            tab = _tnl_light_fast_single_tab;
         else
            tab = _tnl_light_fast_tab;
       }
-/*         tab = _tnl_light_tab;         */
    }
    else
       tab = _tnl_light_ci_tab;
 
    if (ctx->Light.ColorMaterialEnabled)
       ind |= LIGHT_COLORMATERIAL;
-   
+
    if (ctx->Light.Model.TwoSide)
       ind |= LIGHT_TWOSIDE;
 
@@ -189,7 +230,7 @@ static GLboolean run_validate_lighting( GLcontext *ctx,
 
    /* This and the above should only be done on _NEW_LIGHT:
     */
-   gl_validate_all_lighting_tables( ctx );
+   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
 
    /* Now run the stage...
     */
@@ -197,17 +238,29 @@ static GLboolean run_validate_lighting( GLcontext *ctx,
    return stage->run( ctx, stage );
 }
 
+static void alloc_4chan( struct gl_client_array *a, GLuint sz )
+{
+   a->Ptr = ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 );
+   a->Size = 4;
+   a->Type = CHAN_TYPE;
+   a->Stride = 0;
+   a->StrideB = sizeof(GLchan) * 4;
+   a->Enabled = 0;
+   a->Flags = 0;
+}
+
+
 /* Called the first time stage->run is called.  In effect, don't
  * allocate data until the first time the stage is run.
  */
-static GLboolean run_init_lighting( GLcontext *ctx, 
+static GLboolean run_init_lighting( GLcontext *ctx,
                                    struct gl_pipeline_stage *stage )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct light_stage_data *store;
    GLuint size = tnl->vb.Size;
 
-   stage->private = MALLOC(sizeof(*store));
+   stage->privatePtr = MALLOC(sizeof(*store));
    store = LIGHT_STAGE_DATA(stage);
    if (!store)
       return GL_FALSE;
@@ -216,12 +269,15 @@ static GLboolean run_init_lighting( GLcontext *ctx,
     */
    init_lighting();
 
-   gl_vector4ub_alloc( &store->LitColor[0], 0, size, 32 );
-   gl_vector4ub_alloc( &store->LitColor[1], 0, size, 32 );
-   gl_vector4ub_alloc( &store->LitSecondary[0], 0, size, 32 );
-   gl_vector4ub_alloc( &store->LitSecondary[1], 0, size, 32 );
-   gl_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 );
-   gl_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 );
+   store->FloatColor.Ptr = 0;
+
+   alloc_4chan( &store->LitColor[0], size );
+   alloc_4chan( &store->LitColor[1], size );
+   alloc_4chan( &store->LitSecondary[0], size );
+   alloc_4chan( &store->LitSecondary[1], size );
+
+   _mesa_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 );
+   _mesa_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 );
 
    /* Now validate the stage derived data...
     */
@@ -237,15 +293,19 @@ static GLboolean run_init_lighting( GLcontext *ctx,
  */
 static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
 {
-   stage->active = ctx->Light.Enabled;
+   stage->active = ctx->Light.Enabled && !ctx->VertexProgram.Enabled;
    if (stage->active) {
-      if (stage->private)
+      if (stage->privatePtr)
         stage->run = run_validate_lighting;
-      stage->inputs = VERT_NORM|VERT_MATERIAL;
-      if (ctx->Light._NeedVertices) 
-        stage->inputs |= VERT_EYE; /* effectively, even when lighting in obj */
-      if (ctx->Light.ColorMaterialEnabled) 
-        stage->inputs |= VERT_RGBA;
+      stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
+      if (ctx->Light._NeedVertices)
+        stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
+      if (ctx->Light.ColorMaterialEnabled)
+        stage->inputs |= VERT_BIT_COLOR0;
+
+      stage->outputs = VERT_BIT_COLOR0;
+      if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
+        stage->outputs |= VERT_BIT_COLOR1;
    }
 }
 
@@ -255,28 +315,34 @@ static void dtr( struct gl_pipeline_stage *stage )
    struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
 
    if (store) {
-      gl_vector4ub_free( &store->LitColor[0] );      
-      gl_vector4ub_free( &store->LitColor[1] );      
-      gl_vector1ui_free( &store->LitIndex[0] );      
-      gl_vector1ui_free( &store->LitIndex[1] );      
-      gl_vector4ub_free( &store->LitSecondary[0] );  
-      gl_vector4ub_free( &store->LitSecondary[1] );  
+      ALIGN_FREE( store->LitColor[0].Ptr );
+      ALIGN_FREE( store->LitColor[1].Ptr );
+      ALIGN_FREE( store->LitSecondary[0].Ptr );
+      ALIGN_FREE( store->LitSecondary[1].Ptr );
+
+      if (store->FloatColor.Ptr)
+        ALIGN_FREE( store->FloatColor.Ptr );
+
+      _mesa_vector1ui_free( &store->LitIndex[0] );
+      _mesa_vector1ui_free( &store->LitIndex[1] );
       FREE( store );
-      stage->private = 0;
+      stage->privatePtr = 0;
    }
 }
 
-const struct gl_pipeline_stage _tnl_lighting_stage = 
-{ 
-   "lighting",
+const struct gl_pipeline_stage _tnl_lighting_stage =
+{
+   "lighting",                 /* name */
    _NEW_LIGHT,                 /* recheck */
    _NEW_LIGHT|_NEW_MODELVIEW,  /* recalc -- modelview dependency
                                 * otherwise not captured by inputs
-                                * (which may be VERT_OBJ) */
-   0,0,VERT_RGBA,              /* active, inputs, outputs */
-   0,0,                                /* changed_inputs, private_data */
+                                * (which may be VERT_BIT_POS) */
+   GL_FALSE,                   /* active? */
+   0,                          /* inputs */
+   0,                          /* outputs */
+   0,                          /* changed_inputs */
+   NULL,                       /* private_data */
    dtr,                                /* destroy */
    check_lighting,             /* check */
    run_init_lighting           /* run -- initially set to ctr */
 };
-