📄 texenvprogram.c
字号:
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.MaxFragmentProgramTemps;
/* KW: To support tex_env_crossbar, don't release the registers in
* temps_output.
*/
if (max_temp >= sizeof(int) * 8)
p->temp_in_use = p->temps_output;
else
p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
}
static struct ureg register_param6( struct texenv_fragment_program *p,
GLint s0,
GLint s1,
GLint s2,
GLint s3,
GLint s4,
GLint s5)
{
GLint tokens[6];
GLuint idx;
tokens[0] = s0;
tokens[1] = s1;
tokens[2] = s2;
tokens[3] = s3;
tokens[4] = s4;
tokens[5] = s5;
idx = _mesa_add_state_reference( p->program->Parameters, tokens );
return make_ureg(PROGRAM_STATE_VAR, idx);
}
#define register_param1(p,s0) register_param6(p,s0,0,0,0,0,0)
#define register_param2(p,s0,s1) register_param6(p,s0,s1,0,0,0,0)
#define register_param3(p,s0,s1,s2) register_param6(p,s0,s1,s2,0,0,0)
#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
{
p->program->InputsRead |= (1<<input);
return make_ureg(PROGRAM_INPUT, input);
}
static void emit_arg( struct fp_src_register *reg,
struct ureg ureg )
{
reg->File = ureg.file;
reg->Index = ureg.idx;
reg->Swizzle = ureg.swz;
reg->NegateBase = ureg.negatebase;
reg->Abs = ureg.abs;
reg->NegateAbs = ureg.negateabs;
}
static void emit_dst( struct fp_dst_register *dst,
struct ureg ureg, GLuint mask )
{
dst->File = ureg.file;
dst->Index = ureg.idx;
dst->WriteMask = mask;
dst->CondMask = 0;
dst->CondSwizzle = 0;
}
static struct fp_instruction *
emit_op(struct texenv_fragment_program *p,
GLuint op,
struct ureg dest,
GLuint mask,
GLuint saturate,
struct ureg src0,
struct ureg src1,
struct ureg src2 )
{
GLuint nr = p->program->Base.NumInstructions++;
struct fp_instruction *inst = &p->program->Instructions[nr];
memset(inst, 0, sizeof(*inst));
inst->Opcode = op;
emit_arg( &inst->SrcReg[0], src0 );
emit_arg( &inst->SrcReg[1], src1 );
emit_arg( &inst->SrcReg[2], src2 );
inst->Saturate = saturate;
emit_dst( &inst->DstReg, dest, mask );
/* Accounting for indirection tracking:
*/
if (dest.file == PROGRAM_TEMPORARY)
p->temps_output |= 1 << dest.idx;
return inst;
}
static struct ureg emit_arith( struct texenv_fragment_program *p,
GLuint op,
struct ureg dest,
GLuint mask,
GLuint saturate,
struct ureg src0,
struct ureg src1,
struct ureg src2 )
{
emit_op(p, op, dest, mask, saturate, src0, src1, src2);
/* Accounting for indirection tracking:
*/
if (src0.file == PROGRAM_TEMPORARY)
p->alu_temps |= 1 << src0.idx;
if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
p->alu_temps |= 1 << src1.idx;
if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
p->alu_temps |= 1 << src2.idx;
if (dest.file == PROGRAM_TEMPORARY)
p->alu_temps |= 1 << dest.idx;
p->program->NumAluInstructions++;
return dest;
}
static struct ureg emit_texld( struct texenv_fragment_program *p,
GLuint op,
struct ureg dest,
GLuint destmask,
GLuint tex_unit,
GLuint tex_idx,
struct ureg coord )
{
struct fp_instruction *inst = emit_op( p, op,
dest, destmask,
0, /* don't saturate? */
coord, /* arg 0? */
undef,
undef);
inst->TexSrcIdx = tex_idx;
inst->TexSrcUnit = tex_unit;
p->program->NumTexInstructions++;
/* Is this a texture indirection?
*/
if ((coord.file == PROGRAM_TEMPORARY &&
(p->temps_output & (1<<coord.idx))) ||
(dest.file == PROGRAM_TEMPORARY &&
(p->alu_temps & (1<<dest.idx)))) {
p->program->NumTexIndirections++;
p->temps_output = 1<<coord.idx;
p->alu_temps = 0;
assert(0); /* KW: texture env crossbar */
}
return dest;
}
static struct ureg register_const4f( struct texenv_fragment_program *p,
GLfloat s0,
GLfloat s1,
GLfloat s2,
GLfloat s3)
{
GLfloat values[4];
GLuint idx;
values[0] = s0;
values[1] = s1;
values[2] = s2;
values[3] = s3;
idx = _mesa_add_unnamed_constant( p->program->Parameters, values );
return make_ureg(PROGRAM_STATE_VAR, idx);
}
#define register_scalar_const(p, s0) register_const4f(p, s0, s0, s0, s0)
#define register_const1f(p, s0) register_const4f(p, s0, 0, 0, 1)
#define register_const2f(p, s0, s1) register_const4f(p, s0, s1, 0, 1)
#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
static struct ureg get_one( struct texenv_fragment_program *p )
{
if (is_undef(p->one))
p->one = register_scalar_const(p, 1.0);
return p->one;
}
static struct ureg get_half( struct texenv_fragment_program *p )
{
if (is_undef(p->half))
p->one = register_scalar_const(p, 0.5);
return p->half;
}
static struct ureg get_zero( struct texenv_fragment_program *p )
{
if (is_undef(p->zero))
p->one = register_scalar_const(p, 0.0);
return p->zero;
}
static void program_error( struct texenv_fragment_program *p, const char *msg )
{
_mesa_problem(NULL, msg);
p->error = 1;
}
static struct ureg get_source( struct texenv_fragment_program *p,
GLuint src, GLuint unit )
{
switch (src) {
case SRC_TEXTURE:
assert(!is_undef(p->src_texture[unit]));
return p->src_texture[unit];
case SRC_TEXTURE0:
case SRC_TEXTURE1:
case SRC_TEXTURE2:
case SRC_TEXTURE3:
case SRC_TEXTURE4:
case SRC_TEXTURE5:
case SRC_TEXTURE6:
case SRC_TEXTURE7:
assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
return p->src_texture[src - SRC_TEXTURE0];
case SRC_CONSTANT:
return register_param2(p, STATE_TEXENV_COLOR, unit);
case SRC_PRIMARY_COLOR:
return register_input(p, FRAG_ATTRIB_COL0);
case SRC_PREVIOUS:
default:
if (is_undef(p->src_previous))
return register_input(p, FRAG_ATTRIB_COL0);
else
return p->src_previous;
}
}
static struct ureg emit_combine_source( struct texenv_fragment_program *p,
GLuint mask,
GLuint unit,
GLuint source,
GLuint operand )
{
struct ureg arg, src, one;
src = get_source(p, source, unit);
switch (operand) {
case OPR_ONE_MINUS_SRC_COLOR:
/* Get unused tmp,
* Emit tmp = 1.0 - arg.xyzw
*/
arg = get_temp( p );
one = get_one( p );
return emit_arith( p, FP_OPCODE_SUB, arg, mask, 0, one, src, undef);
case OPR_SRC_ALPHA:
if (mask == WRITEMASK_W)
return src;
else
return swizzle1( src, W );
case OPR_ONE_MINUS_SRC_ALPHA:
/* Get unused tmp,
* Emit tmp = 1.0 - arg.wwww
*/
arg = get_temp(p);
one = get_one(p);
return emit_arith(p, FP_OPCODE_SUB, arg, mask, 0,
one, swizzle1(src, W), undef);
case OPR_ZERO:
return get_zero(p);
case OPR_ONE:
return get_one(p);
case OPR_SRC_COLOR:
default:
return src;
}
}
static GLboolean args_match( struct state_key *key, GLuint unit )
{
int i, nr = key->unit[unit].NumArgsRGB;
for (i = 0 ; i < nr ; i++) {
if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
return GL_FALSE;
switch(key->unit[unit].OptA[i].Operand) {
case OPR_SRC_ALPHA:
switch(key->unit[unit].OptRGB[i].Operand) {
case OPR_SRC_COLOR:
case OPR_SRC_ALPHA:
break;
default:
return GL_FALSE;
}
break;
case OPR_ONE_MINUS_SRC_ALPHA:
switch(key->unit[unit].OptRGB[i].Operand) {
case OPR_ONE_MINUS_SRC_COLOR:
case OPR_ONE_MINUS_SRC_ALPHA:
break;
default:
return GL_FALSE;
}
break;
default:
return GL_FALSE; /* impossible */
}
}
return GL_TRUE;
}
static struct ureg emit_combine( struct texenv_fragment_program *p,
struct ureg dest,
GLuint mask,
GLuint saturate,
GLuint unit,
GLuint nr,
GLuint mode,
struct mode_opt *opt)
{
struct ureg src[3];
struct ureg tmp, half;
int i;
for (i = 0; i < nr; i++)
src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
switch (mode) {
case MODE_REPLACE:
if (mask == WRITEMASK_XYZW && !saturate)
return src[0];
else
return emit_arith( p, FP_OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
case MODE_MODULATE:
return emit_arith( p, FP_OPCODE_MUL, dest, mask, saturate,
src[0], src[1], undef );
case MODE_ADD:
return emit_arith( p, FP_OPCODE_ADD, dest, mask, saturate,
src[0], src[1], undef );
case MODE_ADD_SIGNED:
/* tmp = arg0 + arg1
* result = tmp - .5
*/
half = get_half(p);
emit_arith( p, FP_OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
return dest;
case MODE_INTERPOLATE:
/* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
*/
return emit_arith( p, FP_OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
case MODE_SUBTRACT:
return emit_arith( p, FP_OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
case MODE_DOT3_RGBA:
case MODE_DOT3_RGBA_EXT:
case MODE_DOT3_RGB_EXT:
case MODE_DOT3_RGB: {
struct ureg tmp0 = get_temp( p );
struct ureg tmp1 = get_temp( p );
struct ureg neg1 = register_scalar_const(p, -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -