/*
 * Mesa 3-D graphics library
 *
 * Copyright (C) 1999-2006  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"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *    Keith Whitwell <keithw@vmware.com>
 */


#include "c99_math.h"
#include "main/glheader.h"
#include "main/macros.h"
#include "main/imports.h"
#include "main/mtypes.h"

#include "math/m_xform.h"

#include "t_context.h"
#include "t_pipeline.h"


struct fog_stage_data {
   GLvector4f fogcoord;		/* has actual storage allocated */
};

#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)

#define FOG_EXP_TABLE_SIZE 256
#define FOG_MAX (10.0F)
#define EXP_FOG_MAX .0006595F
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
static GLfloat inited = 0;

#if 1
#define NEG_EXP( result, narg )						\
do {									\
   GLfloat f = (GLfloat) (narg * (1.0F / FOG_INCR));			\
   GLint k = (GLint) f;							\
   if (k > FOG_EXP_TABLE_SIZE-2) 					\
      result = (GLfloat) EXP_FOG_MAX;					\
   else									\
      result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]);	\
} while (0)
#else
#define NEG_EXP( result, narg )					\
do {								\
   result = exp(-narg);						\
} while (0)
#endif


/**
 * Initialize the exp_table[] lookup table for approximating exp().
 */
static void
init_static_data( void )
{
   GLfloat f = 0.0F;
   GLint i = 0;
   for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
      exp_table[i] = expf(-f);
   }
   inited = 1;
}


/**
 * Compute per-vertex fog blend factors from fog coordinates by
 * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
 * Fog coordinates are distances from the eye (typically between the
 * near and far clip plane distances).
 * Note that fogcoords may be negative, if eye z is source absolute
 * value must be taken earlier.
 * Fog blend factors are in the range [0,1].
 */
static void
compute_fog_blend_factors(struct gl_context *ctx, GLvector4f *out, const GLvector4f *in)
{
   GLfloat end  = ctx->Fog.End;
   GLfloat *v = in->start;
   GLuint stride = in->stride;
   GLuint n = in->count;
   GLfloat (*data)[4] = out->data;
   GLfloat d;
   GLuint i;

   out->count = in->count;

   switch (ctx->Fog.Mode) {
   case GL_LINEAR:
      if (ctx->Fog.Start == ctx->Fog.End)
         d = 1.0F;
      else
         d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
      for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
         const GLfloat z = *v;
         GLfloat f = (end - z) * d;
	 data[i][0] = CLAMP(f, 0.0F, 1.0F);
      }
      break;
   case GL_EXP:
      d = ctx->Fog.Density;
      for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
         const GLfloat z = *v;
         NEG_EXP( data[i][0], d * z );
      }
      break;
   case GL_EXP2:
      d = ctx->Fog.Density*ctx->Fog.Density;
      for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
         const GLfloat z = *v;
         NEG_EXP( data[i][0], d * z * z );
      }
      break;
   default:
      _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
      return;
   }
}


static GLboolean
run_fog_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct vertex_buffer *VB = &tnl->vb;
   struct fog_stage_data *store = FOG_STAGE_DATA(stage);
   GLvector4f *input;


   if (!ctx->Fog.Enabled)
      return GL_TRUE;

   if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) {
      GLuint i;
      GLfloat *coord;
      /* Fog is computed from vertex or fragment Z values */
      /* source = VB->AttribPtr[_TNL_ATTRIB_POS] or VB->EyePtr coords */
      /* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */
      VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;

      if (!ctx->_NeedEyeCoords) {
         /* compute fog coords from object coords */
	 const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
	 GLfloat plane[4];

	 /* Use this to store calculated eye z values:
	  */
	 input = &store->fogcoord;

	 plane[0] = m[2];
	 plane[1] = m[6];
	 plane[2] = m[10];
	 plane[3] = m[14];
	 /* Full eye coords weren't required, just calculate the
	  * eye Z values.
	  */
	 _mesa_dotprod_tab[VB->AttribPtr[_TNL_ATTRIB_POS]->size]
	    ( (GLfloat *) input->data,
	      4 * sizeof(GLfloat),
	      VB->AttribPtr[_TNL_ATTRIB_POS], plane );

	 input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;

	 /* make sure coords are really positive
	    NOTE should avoid going through array twice */
	 coord = input->start;
	 for (i = 0; i < input->count; i++) {
	    *coord = fabsf(*coord);
	    STRIDE_F(coord, input->stride);
	 }
      }
      else {
         /* fog coordinates = eye Z coordinates - need to copy for ABS */
	 input = &store->fogcoord;

	 if (VB->EyePtr->size < 2)
	    _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );

	 input->stride = 4 * sizeof(GLfloat);
	 input->count = VB->EyePtr->count;
	 coord = VB->EyePtr->start;
	 for (i = 0 ; i < VB->EyePtr->count; i++) {
	    input->data[i][0] = fabsf(coord[2]);
	    STRIDE_F(coord, VB->EyePtr->stride);
	 }
      }
   }
   else {
      /* use glFogCoord() coordinates */
      input = VB->AttribPtr[_TNL_ATTRIB_FOG];  /* source data */

      /* input->count may be one if glFogCoord was only called once
       * before glBegin.  But we need to compute fog for all vertices.
       */
      input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;

      VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;  /* dest data */
   }

   if (tnl->_DoVertexFog) {
      /* compute blend factors from fog coordinates */
      compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input );
   }
   else {
      /* results = incoming fog coords (compute fog per-fragment later) */
      VB->AttribPtr[_TNL_ATTRIB_FOG] = input;
   }

   return GL_TRUE;
}



/* Called the first time stage->run() is invoked.
 */
static GLboolean
alloc_fog_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct fog_stage_data *store;
   stage->privatePtr = malloc(sizeof(*store));
   store = FOG_STAGE_DATA(stage);
   if (!store)
      return GL_FALSE;

   _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );

   if (!inited)
      init_static_data();

   return GL_TRUE;
}


static void
free_fog_data(struct tnl_pipeline_stage *stage)
{
   struct fog_stage_data *store = FOG_STAGE_DATA(stage);
   if (store) {
      _mesa_vector4f_free( &store->fogcoord );
      free( store );
      stage->privatePtr = NULL;
   }
}


const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
{
   "build fog coordinates",	/* name */
   NULL,			/* private_data */
   alloc_fog_data,		/* dtr */
   free_fog_data,		/* dtr */
   NULL,		/* check */
   run_fog_stage		/* run -- initially set to init. */
};
