Do individual negetation in swizzling, thus we can

save one instruction in some case.
This commit is contained in:
Jerome Glisse 2006-01-21 15:16:53 +00:00
parent c6f35dd8db
commit acd1f16b35

View file

@ -360,27 +360,78 @@ static __inline pfs_reg_t absolute(pfs_reg_t r)
} }
static int swz_native(struct r300_fragment_program *rp, static int swz_native(struct r300_fragment_program *rp,
pfs_reg_t src, pfs_reg_t *r) pfs_reg_t src, pfs_reg_t *r, GLuint arbneg)
{ {
/* Native swizzle, nothing to see here */ /* Native swizzle, nothing to see here */
src.negate_s = (arbneg >> 3) & 1;
if ((arbneg & 0x7) == 0x0) {
src.negate_v = 0;
*r = src; *r = src;
} else if ((arbneg & 0x7) == 0x7) {
src.negate_v = 1;
*r = src;
} else {
if (!r->valid)
*r = get_temp_reg(rp);
src.negate_v = 1;
emit_arith(rp, PFS_OP_MAD, *r, arbneg & 0x7,
keep(src), pfs_one, pfs_zero, 0);
src.negate_v = 0;
emit_arith(rp, PFS_OP_MAD, *r,
(arbneg ^ 0x7) | WRITEMASK_W,
src, pfs_one, pfs_zero, 0);
}
return 3; return 3;
} }
static int swz_emit_partial(struct r300_fragment_program *rp, pfs_reg_t src, static int swz_emit_partial(struct r300_fragment_program *rp, pfs_reg_t src,
pfs_reg_t *r, int mask, int mc) pfs_reg_t *r, int mask, int mc, GLuint arbneg)
{ {
GLuint tmp;
GLuint wmask = 0;
if (!r->valid) if (!r->valid)
*r = get_temp_reg(rp); *r = get_temp_reg(rp);
/* A partial match, src.v_swz/mask define what parts of the /* A partial match, src.v_swz/mask define what parts of the
* desired swizzle we match */ * desired swizzle we match */
if (mc + s_mask[mask].count == 3) if (mc + s_mask[mask].count == 3) {
emit_arith(rp, PFS_OP_MAD, *r, s_mask[mask].mask|WRITEMASK_W, wmask = WRITEMASK_W;
src.negate_s = (arbneg >> 3) & 1;
}
tmp = arbneg & s_mask[mask].mask;
if (tmp) {
tmp = tmp ^ s_mask[mask].mask;
if (tmp) {
src.negate_v = 1;
emit_arith(rp, PFS_OP_MAD, *r,
arbneg & s_mask[mask].mask,
keep(src), pfs_one, pfs_zero, 0);
src.negate_v = 0;
if (!wmask) src.no_use = GL_TRUE;
else src.no_use = GL_FALSE;
emit_arith(rp, PFS_OP_MAD, *r, tmp | wmask,
src, pfs_one, pfs_zero, 0); src, pfs_one, pfs_zero, 0);
else } else {
emit_arith(rp, PFS_OP_MAD, *r, s_mask[mask].mask, keep(src), src.negate_v = 1;
pfs_one, pfs_zero, 0); if (!wmask) src.no_use = GL_TRUE;
else src.no_use = GL_FALSE;
emit_arith(rp, PFS_OP_MAD, *r,
(arbneg & s_mask[mask].mask) | wmask,
src, pfs_one, pfs_zero, 0);
src.negate_v = 0;
}
} else {
if (!wmask) src.no_use = GL_TRUE;
else src.no_use = GL_FALSE;
emit_arith(rp, PFS_OP_MAD, *r,
s_mask[mask].mask | wmask,
src, pfs_one, pfs_zero, 0);
}
return s_mask[mask].count; return s_mask[mask].count;
} }
@ -388,11 +439,11 @@ static int swz_emit_partial(struct r300_fragment_program *rp, pfs_reg_t src,
((SWIZZLE_##x<<0)| \ ((SWIZZLE_##x<<0)| \
(SWIZZLE_##y<<3)| \ (SWIZZLE_##y<<3)| \
(SWIZZLE_##z<<6)| \ (SWIZZLE_##z<<6)| \
(SWIZZLE_##w<<9))) (SWIZZLE_##w<<9)), \
0)
static pfs_reg_t do_swizzle(struct r300_fragment_program *rp, static pfs_reg_t do_swizzle(struct r300_fragment_program *rp,
pfs_reg_t src, pfs_reg_t src, GLuint arbswz, GLuint arbneg)
GLuint arbswz)
{ {
pfs_reg_t r = undef; pfs_reg_t r = undef;
@ -415,12 +466,14 @@ static pfs_reg_t do_swizzle(struct r300_fragment_program *rp,
#define CUR_HASH (v_swiz[src.v_swz].hash & s_mask[c_mask].hash) #define CUR_HASH (v_swiz[src.v_swz].hash & s_mask[c_mask].hash)
if (CUR_HASH == (arbswz & s_mask[c_mask].hash)) { if (CUR_HASH == (arbswz & s_mask[c_mask].hash)) {
if (s_mask[c_mask].count == 3) if (s_mask[c_mask].count == 3)
v_matched += swz_native(rp, src, &r); v_matched += swz_native(rp, src, &r,
arbneg);
else else
v_matched += swz_emit_partial(rp, src, v_matched += swz_emit_partial(rp, src,
&r, &r,
c_mask, c_mask,
v_matched); v_matched,
arbneg);
if (v_matched == 3) if (v_matched == 3)
return r; return r;
@ -455,14 +508,17 @@ static pfs_reg_t t_src(struct r300_fragment_program *rp,
r.valid = GL_TRUE; r.valid = GL_TRUE;
break; break;
case PROGRAM_LOCAL_PARAM: case PROGRAM_LOCAL_PARAM:
r = emit_param4fv(rp, rp->mesa_program.Base.LocalParams[fpsrc.Index]); r = emit_param4fv(rp,
rp->mesa_program.Base.LocalParams[fpsrc.Index]);
break; break;
case PROGRAM_ENV_PARAM: case PROGRAM_ENV_PARAM:
r = emit_param4fv(rp, rp->ctx->FragmentProgram.Parameters[fpsrc.Index]); r = emit_param4fv(rp,
rp->ctx->FragmentProgram.Parameters[fpsrc.Index]);
break; break;
case PROGRAM_STATE_VAR: case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM: case PROGRAM_NAMED_PARAM:
r = emit_param4fv(rp, rp->mesa_program.Base.Parameters->ParameterValues[fpsrc.Index]); r = emit_param4fv(rp,
rp->mesa_program.Base.Parameters->ParameterValues[fpsrc.Index]);
break; break;
default: default:
ERROR("unknown SrcReg->File %x\n", fpsrc.File); ERROR("unknown SrcReg->File %x\n", fpsrc.File);
@ -471,14 +527,14 @@ static pfs_reg_t t_src(struct r300_fragment_program *rp,
/* no point swizzling ONE/ZERO/HALF constants... */ /* no point swizzling ONE/ZERO/HALF constants... */
if (r.v_swz < SWIZZLE_111 && r.s_swz < SWIZZLE_ZERO) if (r.v_swz < SWIZZLE_111 && r.s_swz < SWIZZLE_ZERO)
r = do_swizzle(rp, r, fpsrc.Swizzle); r = do_swizzle(rp, r, fpsrc.Swizzle, fpsrc.NegateBase);
#if 0 #if 0
/* WRONG! Need to be able to do individual component negation, /* WRONG! Need to be able to do individual component negation,
* should probably handle this in the swizzling code unless * should probably handle this in the swizzling code unless
* all components are negated, then we can do this natively */ * all components are negated, then we can do this natively */
if ((fpsrc.NegateBase & 0xf) == 0xf) if ((fpsrc.NegateBase & 0xf) == 0xf)
r.negate = GL_TRUE; r.negate = GL_TRUE;
#endif
r.negate_s = (fpsrc.NegateBase >> 3) & 1; r.negate_s = (fpsrc.NegateBase >> 3) & 1;
if ((fpsrc.NegateBase & 0x7) == 0x0) { if ((fpsrc.NegateBase & 0x7) == 0x0) {
@ -504,6 +560,7 @@ static pfs_reg_t t_src(struct r300_fragment_program *rp,
r.negate_v = 0; r.negate_v = 0;
} }
} }
#endif
return r; return r;
} }