/****************************************************************************************/
/*  SHADER_BLEND.C                                                                      */
/*                                                                                      */
/*  Author: Timothy Roff	                                                            */
/*  Description:  Shader implementation                                                 */
/*                                                                                      */
/*  The contents of this file are subject to the Jet3D Public License                   */
/*  Version 1.02 (the "License"); you may not use this file except in                   */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.jet3d.com                                                                */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  This file was not part of the original Jet3D, released December 12, 1999.           */
/*                                                                                      */
/****************************************************************************************/

#include "jeShaderDefs.h"
#include "jeShader_h.h"

typedef struct {
   char* name;
   int   factor;
   int   is_src;
   int   is_dst;
   int   map_alpha;
} blend_parse_table_t;



blend_parse_table_t blend_parse_table[] = {
  /* name                      factor                     is_src is_dst map_alpha */
   { "GL_ONE",                 SH_BLEND_ONE,                 JE_TRUE,  JE_TRUE,  JE_FALSE },
   { "GL_ZERO",                SH_BLEND_ZERO,                JE_TRUE,  JE_TRUE,  JE_FALSE },
   { "GL_DST_COLOR",           SH_BLEND_DST_COLOR,           JE_TRUE,  JE_FALSE, JE_FALSE },
   { "GL_ONE_MINUS_DST_COLOR", SH_BLEND_ONE_MINUS_DST_COLOR, JE_TRUE,  JE_FALSE, JE_FALSE },
   { "GL_SRC_ALPHA",           SH_BLEND_SRC_ALPHA,           JE_TRUE,  JE_TRUE,  JE_TRUE  },
   { "GL_ONE_MINUS_SRC_ALPHA", SH_BLEND_ONE_MINUS_SRC_ALPHA, JE_TRUE,  JE_TRUE,  JE_TRUE  },
   { "GL_DST_ALPHA",           SH_BLEND_DST_ALPHA,           JE_TRUE,  JE_TRUE,  JE_FALSE },
   { "GL_ONE_MINUS_DST_ALPHA", SH_BLEND_ONE_MINUS_DST_ALPHA, JE_TRUE,  JE_TRUE,  JE_FALSE },
   { "GL_SRC_COLOR",           SH_BLEND_SRC_COLOR,           JE_FALSE, JE_TRUE,  JE_FALSE },
   { "GL_ONE_MINUS_SRC_COLOR", SH_BLEND_ONE_MINUS_SRC_COLOR, JE_FALSE, JE_TRUE,  JE_FALSE },
   { 0 }
};

int ParseBlendFunc(const char* arg, jeBoolean is_src, jeBoolean* map_alpha_out)
{
   blend_parse_table_t* table = blend_parse_table;

   while (table->name) {
      if (stricmp(table->name, arg) == 0) {
         if (is_src && !table->is_src) {
            jeShader_Error("'%s' is not a source blend factor");
            return -1;
         }

         if (!is_src && !table->is_dst) {
            jeShader_Error("'%s' is not a destination blend factor");
            return -1;
         }

         *map_alpha_out = table->map_alpha;

         return table->factor;
      }

      table++;
   }

   if (is_src) {
      jeShader_Error("unknown source factor '%s'", arg);
      return -1;
   }
   else {
      jeShader_Error("unknown destination factor '%s'", arg);
      return -1;
   }
}


//=====================================================================================
//	blendFuncParseFunc
//=====================================================================================
jeBoolean blendFuncParseFunc(int argc, char* argv[], shader_info_t *info)
{
	assert(info != NULL);

	#ifdef _DEBUG
	jeShader_Error("entering blendFuncParseFunc!!!");
	#endif

   if (argc == 2) {
      // blendfunc add
      if (stricmp(argv[1], "add") == 0) {
         info->stage.blend_src = SH_BLEND_ONE;
         info->stage.blend_dst = SH_BLEND_ONE;

         info->stage.flags &= ~SH_STAGE_MAP_NEEDS_ALPHA;
      }
      // blendfunc filter
      else if (stricmp(argv[1], "filter") == 0) {
         info->stage.blend_src = SH_BLEND_DST_COLOR;
         info->stage.blend_dst = SH_BLEND_ZERO;

         info->stage.flags &= ~SH_STAGE_MAP_NEEDS_ALPHA;
      }
      // blendfunc blend
      else if (stricmp(argv[1], "blend") == 0) {
         info->stage.blend_src = SH_BLEND_SRC_ALPHA;
         info->stage.blend_dst = SH_BLEND_ONE_MINUS_SRC_ALPHA;

         info->stage.flags |= SH_STAGE_MAP_NEEDS_ALPHA;
      }
      else {
         jeShader_Error(0, "unknown simplified blendFunc '%s'", argv[1]);
         return JE_TRUE;
      }
   }
   // blendfunc <src> <dst>
   else {
      jeBoolean src_alpha;
      jeBoolean dst_alpha;

      info->stage.blend_src = ParseBlendFunc(argv[1], JE_TRUE, &src_alpha);

      if (info->stage.blend_src < 0) return JE_TRUE;

      info->stage.blend_dst = ParseBlendFunc(argv[2], JE_FALSE, &dst_alpha);

      if (info->stage.blend_dst < 0) return JE_TRUE;

      if (src_alpha || dst_alpha) {
         info->stage.flags |= SH_STAGE_MAP_NEEDS_ALPHA;
      }
      else {
         info->stage.flags &= ~SH_STAGE_MAP_NEEDS_ALPHA;
      }

      info->stage.flags |= SH_STAGE_EXPLICIT_BLENDFUNC;
   }

   info->stage.flags |= SH_STAGE_BLENDFUNC;

   return JE_TRUE;
}
