📄 texenvprogram.c
字号:
/************************************************************************** * * 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/program_instruction.h"#define MAX_INSTRUCTIONS 100#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)struct mode_opt { GLuint Source:4; GLuint Operand:3;};struct state_key { GLbitfield enabled_units; GLuint separate_specular:1; GLuint fog_enabled:1; GLuint fog_mode:2; struct { GLuint enabled:1; GLuint source_index:3; /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */ GLuint ScaleShiftRGB:2; GLuint ScaleShiftA:2; GLuint NumArgsRGB:2; GLuint ModeRGB:4; struct mode_opt OptRGB[3]; GLuint NumArgsA:2; GLuint ModeA:4; struct mode_opt OptA[3]; } unit[8];};#define FOG_LINEAR 0#define FOG_EXP 1#define FOG_EXP2 2#define FOG_UNKNOWN 3static 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 7static 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 15static 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 15static 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 7static GLuint translate_tex_src_bit( GLbitfield 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; }}/** * Examine current texture environment state and generate a unique * key to identify it. */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};/* State used to build the fragment program: */struct texenv_fragment_program { struct fragment_program *program; GLcontext *ctx; struct state_key *state; GLbitfield alu_temps; /* Track texture indirections, see spec. */ GLbitfield temps_output; /* Track texture indirections, see spec. */ GLbitfield 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 = _mesa_ffs( ~p->temp_in_use & p->alu_temps ); /* Then any unused temporary: */ if (!bit) bit = _mesa_ffs( ~p->temp_in_use ); if (!bit) { _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__); _mesa_exit(1); } if (bit > p->program->Base.NumTemporaries) p->program->Base.NumTemporaries = bit; 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 = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output ); /* Then any unused temporary: */ if (!bit) bit = _mesa_ffs( ~p->temp_in_use ); if (!bit) { _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__); _mesa_exit(1); } if (bit > p->program->Base.NumTemporaries) p->program->Base.NumTemporaries = bit; p->temp_in_use |= 1<<(bit-1); return make_ureg(PROGRAM_TEMPORARY, (bit-1));}static void release_temps( struct texenv_fragment_program *p ){ GLuint max_temp = p->ctx->Const.FragmentProgram.MaxTemps;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -