⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 texenvprogram.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/**************************************************************************
 * 
 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
 * 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, sub license, 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 (including the
 * next paragraph) 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 NON-INFRINGEMENT.
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
 * 
 **************************************************************************/

#include "glheader.h"
#include "macros.h"
#include "enums.h"
#include "texenvprogram.h"

#include "shader/program.h"
#include "shader/nvfragprog.h"
#include "shader/arbfragparse.h"


#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)

struct mode_opt {
   unsigned Source:4;
   unsigned Operand:3;
};

struct state_key {
   GLuint enabled_units;
   unsigned separate_specular:1;
   unsigned fog_enabled:1;
   unsigned fog_mode:2;

   struct {
      unsigned enabled:1;
      unsigned source_index:3;
      unsigned ScaleShiftRGB:2;
      unsigned ScaleShiftA:2;

      unsigned NumArgsRGB:2;
      unsigned ModeRGB:4;
      struct mode_opt OptRGB[3];

      unsigned NumArgsA:2;
      unsigned ModeA:4;
      struct mode_opt OptA[3];
   } unit[8];
};

#define FOG_LINEAR  0
#define FOG_EXP     1
#define FOG_EXP2    2
#define FOG_UNKNOWN 3

static GLuint translate_fog_mode( GLenum mode )
{
   switch (mode) {
   case GL_LINEAR: return FOG_LINEAR;
   case GL_EXP: return FOG_EXP;
   case GL_EXP2: return FOG_EXP2;
   default: return FOG_UNKNOWN;
   }
}

#define OPR_SRC_COLOR           0
#define OPR_ONE_MINUS_SRC_COLOR 1
#define OPR_SRC_ALPHA           2
#define OPR_ONE_MINUS_SRC_ALPHA	3
#define OPR_ZERO                4
#define OPR_ONE                 5
#define OPR_UNKNOWN             7

static GLuint translate_operand( GLenum operand )
{
   switch (operand) {
   case GL_SRC_COLOR: return OPR_SRC_COLOR;
   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
   case GL_ZERO: return OPR_ZERO;
   case GL_ONE: return OPR_ONE;
   default:	return OPR_UNKNOWN;
   }
}

#define SRC_TEXTURE  0
#define SRC_TEXTURE0 1
#define SRC_TEXTURE1 2
#define SRC_TEXTURE2 3
#define SRC_TEXTURE3 4
#define SRC_TEXTURE4 5
#define SRC_TEXTURE5 6
#define SRC_TEXTURE6 7
#define SRC_TEXTURE7 8
#define SRC_CONSTANT 9
#define SRC_PRIMARY_COLOR 10
#define SRC_PREVIOUS 11
#define SRC_UNKNOWN  15

static GLuint translate_source( GLenum src )
{
   switch (src) {
   case GL_TEXTURE: return SRC_TEXTURE;
   case GL_TEXTURE0:
   case GL_TEXTURE1:
   case GL_TEXTURE2:
   case GL_TEXTURE3:
   case GL_TEXTURE4:
   case GL_TEXTURE5:
   case GL_TEXTURE6:
   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
   case GL_CONSTANT: return SRC_CONSTANT;
   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
   case GL_PREVIOUS: return SRC_PREVIOUS;
   default: return SRC_UNKNOWN;
   }
}

#define MODE_REPLACE       0
#define MODE_MODULATE      1
#define MODE_ADD           2
#define MODE_ADD_SIGNED    3
#define MODE_INTERPOLATE   4
#define MODE_SUBTRACT      5
#define MODE_DOT3_RGB      6
#define MODE_DOT3_RGB_EXT  7
#define MODE_DOT3_RGBA     8
#define MODE_DOT3_RGBA_EXT 9
#define MODE_MODULATE_ADD_ATI           10
#define MODE_MODULATE_SIGNED_ADD_ATI    11
#define MODE_MODULATE_SUBTRACT_ATI      12
#define MODE_UNKNOWN       15

static GLuint translate_mode( GLenum mode )
{
   switch (mode) {
   case GL_REPLACE: return MODE_REPLACE;
   case GL_MODULATE: return MODE_MODULATE;
   case GL_ADD: return MODE_ADD;
   case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
   case GL_INTERPOLATE: return MODE_INTERPOLATE;
   case GL_SUBTRACT: return MODE_SUBTRACT;
   case GL_DOT3_RGB: return MODE_DOT3_RGB;
   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
   default: return MODE_UNKNOWN;
   }
}

#define TEXTURE_UNKNOWN_INDEX 7
static GLuint translate_tex_src_bit( GLuint bit )
{
   switch (bit) {
   case TEXTURE_1D_BIT:   return TEXTURE_1D_INDEX;
   case TEXTURE_2D_BIT:   return TEXTURE_2D_INDEX;
   case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
   case TEXTURE_3D_BIT:   return TEXTURE_3D_INDEX;
   case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
   default: return TEXTURE_UNKNOWN_INDEX;
   }
}

static struct state_key *make_state_key( GLcontext *ctx )
{
   struct state_key *key = CALLOC_STRUCT(state_key);
   GLuint i, j;
	
   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
		
      if (!texUnit->_ReallyEnabled)
         continue;

      key->unit[i].enabled = 1;
      key->enabled_units |= (1<<i);

      key->unit[i].source_index = 
	 translate_tex_src_bit(texUnit->_ReallyEnabled);		

      key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
      key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;

      key->unit[i].ModeRGB =
	 translate_mode(texUnit->_CurrentCombine->ModeRGB);
      key->unit[i].ModeA =
	 translate_mode(texUnit->_CurrentCombine->ModeA);
		
      key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
      key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftRGB;

      for (j=0;j<3;j++) {
         key->unit[i].OptRGB[j].Operand =
	    translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
         key->unit[i].OptA[j].Operand =
	    translate_operand(texUnit->_CurrentCombine->OperandA[j]);
         key->unit[i].OptRGB[j].Source =
	    translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
         key->unit[i].OptA[j].Source =
	    translate_source(texUnit->_CurrentCombine->SourceA[j]);
      }
   }
	
   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
      key->separate_specular = 1;

   if (ctx->Fog.Enabled) {
      key->fog_enabled = 1;
      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
   }
	
   return key;
}

/* Use uregs to represent registers internally, translate to Mesa's
 * expected formats on emit.  
 *
 * NOTE: These are passed by value extensively in this file rather
 * than as usual by pointer reference.  If this disturbs you, try
 * remembering they are just 32bits in size.
 *
 * GCC is smart enough to deal with these dword-sized structures in
 * much the same way as if I had defined them as dwords and was using
 * macros to access and set the fields.  This is much nicer and easier
 * to evolve.
 */
struct ureg {
   GLuint file:4;
   GLuint idx:8;
   GLuint negatebase:1;
   GLuint abs:1;
   GLuint negateabs:1;
   GLuint swz:12;
   GLuint pad:5;
};

const static struct ureg undef = { 
   ~0,
   ~0,
   0,
   0,
   0,
   0,
   0
};

#define X    0
#define Y    1
#define Z    2
#define W    3

/* State used to build the fragment program:
 */
struct texenv_fragment_program {
   struct fragment_program *program;
   GLcontext *ctx;
   struct state_key *state;

   GLuint alu_temps;		/* Track texture indirections, see spec. */
   GLuint temps_output;		/* Track texture indirections, see spec. */

   GLuint temp_in_use;		/* Tracks temporary regs which are in
				 * use.
				 */


   GLboolean error;

   struct ureg src_texture[MAX_TEXTURE_UNITS];   
   /* Reg containing each texture unit's sampled texture color,
    * else undef.
    */

   struct ureg src_previous;	/* Reg containing color from previous 
				 * stage.  May need to be decl'd.
				 */

   GLuint last_tex_stage;	/* Number of last enabled texture unit */

   struct ureg half;
   struct ureg one;
   struct ureg zero;
};



static struct ureg make_ureg(GLuint file, GLuint idx)
{
   struct ureg reg;
   reg.file = file;
   reg.idx = idx;
   reg.negatebase = 0;
   reg.abs = 0;
   reg.negateabs = 0;
   reg.swz = SWIZZLE_NOOP;
   reg.pad = 0;
   return reg;
}

static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
{
   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
			   GET_SWZ(reg.swz, y),
			   GET_SWZ(reg.swz, z),
			   GET_SWZ(reg.swz, w));

   return reg;
}

static struct ureg swizzle1( struct ureg reg, int x )
{
   return swizzle(reg, x, x, x, x);
}

static struct ureg negate( struct ureg reg )
{
   reg.negatebase ^= 1;
   return reg;
}

static GLboolean is_undef( struct ureg reg )
{
   return reg.file == 0xf;
}


static struct ureg get_temp( struct texenv_fragment_program *p )
{
   int bit;
   
   /* First try and reuse temps which have been used already:
    */
   bit = ffs( ~p->temp_in_use & p->alu_temps );

   /* Then any unused temporary:
    */
   if (!bit)
      bit = ffs( ~p->temp_in_use );

   if (!bit) {
      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
      exit(1);
   }

   p->temp_in_use |= 1<<(bit-1);
   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
}

static struct ureg get_tex_temp( struct texenv_fragment_program *p )
{
   int bit;
   
   /* First try to find availble temp not previously used (to avoid
    * starting a new texture indirection).  According to the spec, the
    * ~p->temps_output isn't necessary, but will keep it there for
    * now:
    */
   bit = ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );

   /* Then any unused temporary:
    */
   if (!bit) 
      bit = ffs( ~p->temp_in_use );

   if (!bit) {
      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
      exit(1);
   }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -