diff --git a/src/compiler/nir/nir_lower_blend.c b/src/compiler/nir/nir_lower_blend.c index 8cb17546841..70df8a918c7 100644 --- a/src/compiler/nir/nir_lower_blend.c +++ b/src/compiler/nir/nir_lower_blend.c @@ -34,6 +34,7 @@ #include "compiler/nir/nir.h" #include "compiler/nir/nir_builder.h" #include "compiler/nir/nir_format_convert.h" +#include "util/blend.h" #include "nir_lower_blend.h" struct ctx { @@ -46,19 +47,19 @@ struct ctx { static nir_ssa_def * nir_blend_func( nir_builder *b, - enum blend_func func, + enum pipe_blend_func func, nir_ssa_def *src, nir_ssa_def *dst) { switch (func) { - case BLEND_FUNC_ADD: + case PIPE_BLEND_ADD: return nir_fadd(b, src, dst); - case BLEND_FUNC_SUBTRACT: + case PIPE_BLEND_SUBTRACT: return nir_fsub(b, src, dst); - case BLEND_FUNC_REVERSE_SUBTRACT: + case PIPE_BLEND_REVERSE_SUBTRACT: return nir_fsub(b, dst, src); - case BLEND_FUNC_MIN: + case PIPE_BLEND_MIN: return nir_fmin(b, src, dst); - case BLEND_FUNC_MAX: + case PIPE_BLEND_MAX: return nir_fmax(b, src, dst); } @@ -68,12 +69,12 @@ nir_blend_func( /* Does this blend function multiply by a blend factor? */ static bool -nir_blend_factored(enum blend_func func) +nir_blend_factored(enum pipe_blend_func func) { switch (func) { - case BLEND_FUNC_ADD: - case BLEND_FUNC_SUBTRACT: - case BLEND_FUNC_REVERSE_SUBTRACT: + case PIPE_BLEND_ADD: + case PIPE_BLEND_SUBTRACT: + case PIPE_BLEND_REVERSE_SUBTRACT: return true; default: return false; @@ -102,32 +103,33 @@ nir_blend_factor_value( nir_builder *b, nir_ssa_def *src, nir_ssa_def *src1, nir_ssa_def *dst, nir_ssa_def *bconst, unsigned chan, - enum blend_factor factor) + enum pipe_blendfactor factor_without_invert) { - switch (factor) { - case BLEND_FACTOR_ZERO: - return nir_imm_floatN_t(b, 0.0, src->bit_size); - case BLEND_FACTOR_SRC_COLOR: + switch (factor_without_invert) { + case PIPE_BLENDFACTOR_ONE: + return nir_imm_floatN_t(b, 1.0, src->bit_size); + case PIPE_BLENDFACTOR_SRC_COLOR: return nir_channel(b, src, chan); - case BLEND_FACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_COLOR: return nir_channel(b, src1, chan); - case BLEND_FACTOR_DST_COLOR: + case PIPE_BLENDFACTOR_DST_COLOR: return nir_channel(b, dst, chan); - case BLEND_FACTOR_SRC_ALPHA: + case PIPE_BLENDFACTOR_SRC_ALPHA: return nir_channel(b, src, 3); - case BLEND_FACTOR_SRC1_ALPHA: + case PIPE_BLENDFACTOR_SRC1_ALPHA: return nir_channel(b, src1, 3); - case BLEND_FACTOR_DST_ALPHA: + case PIPE_BLENDFACTOR_DST_ALPHA: return nir_channel(b, dst, 3); - case BLEND_FACTOR_CONSTANT_COLOR: + case PIPE_BLENDFACTOR_CONST_COLOR: return nir_channel(b, bconst, chan); - case BLEND_FACTOR_CONSTANT_ALPHA: + case PIPE_BLENDFACTOR_CONST_ALPHA: return nir_channel(b, bconst, 3); - case BLEND_FACTOR_SRC_ALPHA_SATURATE: + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return nir_alpha_saturate(b, src, dst, chan); + default: + assert(util_blendfactor_is_inverted(factor_without_invert)); + unreachable("Unexpected inverted factor"); } - - unreachable("Invalid blend factor"); } static nir_ssa_def * @@ -154,49 +156,62 @@ nir_fsat_to_format(nir_builder *b, nir_ssa_def *x, enum pipe_format format) * clamping a blend factor is needed. */ static bool -should_clamp_factor(enum blend_factor factor, bool inverted, bool snorm) +should_clamp_factor(enum pipe_blendfactor factor, bool snorm) { - switch (factor) { - case BLEND_FACTOR_ZERO: + switch (util_blendfactor_without_invert(factor)) { + case PIPE_BLENDFACTOR_ONE: /* 0, 1 are in [0, 1] and [-1, 1] */ return false; - case BLEND_FACTOR_SRC_COLOR: - case BLEND_FACTOR_SRC1_COLOR: - case BLEND_FACTOR_DST_COLOR: - case BLEND_FACTOR_SRC_ALPHA: - case BLEND_FACTOR_SRC1_ALPHA: - case BLEND_FACTOR_DST_ALPHA: + case PIPE_BLENDFACTOR_SRC_COLOR: + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_DST_COLOR: + case PIPE_BLENDFACTOR_SRC_ALPHA: + case PIPE_BLENDFACTOR_SRC1_ALPHA: + case PIPE_BLENDFACTOR_DST_ALPHA: /* Colours are already clamped. For unorm, the complement of something * clamped is still clamped. But for snorm, this is not true. Clamp for * snorm only. */ - return inverted && snorm; + return util_blendfactor_is_inverted(factor) && snorm; - case BLEND_FACTOR_CONSTANT_COLOR: - case BLEND_FACTOR_CONSTANT_ALPHA: + case PIPE_BLENDFACTOR_CONST_COLOR: + case PIPE_BLENDFACTOR_CONST_ALPHA: /* Constant colours are not yet clamped */ return true; - case BLEND_FACTOR_SRC_ALPHA_SATURATE: + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* For unorm, this is in bounds (and hence so is its complement). For * snorm, it may not be. */ return snorm; + + default: + unreachable("invalid blend factor"); } - unreachable("invalid blend factor"); } static bool channel_uses_dest(nir_lower_blend_channel chan) { - return chan.src_factor == BLEND_FACTOR_DST_COLOR || - chan.src_factor == BLEND_FACTOR_DST_ALPHA || - chan.src_factor == BLEND_FACTOR_SRC_ALPHA_SATURATE || - !(chan.dst_factor == BLEND_FACTOR_ZERO && !chan.invert_dst_factor) || - chan.func == BLEND_FUNC_MIN || - chan.func == BLEND_FUNC_MAX; + /* If blend factors are ignored, dest is used (min/max) */ + if (!nir_blend_factored(chan.func)) + return true; + + /* If dest has a nonzero factor, it is used */ + if (chan.dst_factor != PIPE_BLENDFACTOR_ZERO) + return true; + + /* Else, check the source factor */ + switch (util_blendfactor_without_invert(chan.src_factor)) { + case PIPE_BLENDFACTOR_DST_COLOR: + case PIPE_BLENDFACTOR_DST_ALPHA: + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: + return true; + default: + return false; + } } static nir_ssa_def * @@ -205,17 +220,17 @@ nir_blend_factor( nir_ssa_def *raw_scalar, nir_ssa_def *src, nir_ssa_def *src1, nir_ssa_def *dst, nir_ssa_def *bconst, unsigned chan, - enum blend_factor factor, - bool inverted, + enum pipe_blendfactor factor, enum pipe_format format) { nir_ssa_def *f = - nir_blend_factor_value(b, src, src1, dst, bconst, chan, factor); + nir_blend_factor_value(b, src, src1, dst, bconst, chan, + util_blendfactor_without_invert(factor)); - if (inverted) + if (util_blendfactor_is_inverted(factor)) f = nir_fadd_imm(b, nir_fneg(b, f), 1.0); - if (should_clamp_factor(factor, inverted, util_format_is_snorm(format))) + if (should_clamp_factor(factor, util_format_is_snorm(format))) f = nir_fsat_to_format(b, f, format); return nir_fmul(b, raw_scalar, f); @@ -240,7 +255,7 @@ nir_color_mask( static nir_ssa_def * nir_logicop_func( nir_builder *b, - unsigned func, + enum pipe_logicop func, nir_ssa_def *src, nir_ssa_def *dst, nir_ssa_def *bitmask) { switch (func) { @@ -440,12 +455,12 @@ nir_blend( psrc = nir_blend_factor( b, psrc, src, src1, dst, bconst, c, - chan.src_factor, chan.invert_src_factor, format); + chan.src_factor, format); pdst = nir_blend_factor( b, pdst, src, src1, dst, bconst, c, - chan.dst_factor, chan.invert_dst_factor, format); + chan.dst_factor, format); } channels[c] = nir_blend_func(b, chan.func, psrc, pdst); @@ -473,9 +488,9 @@ color_index_for_location(unsigned location) static bool nir_blend_replace_channel(const nir_lower_blend_channel *c) { - return (c->func == BLEND_FUNC_ADD) && - (c->src_factor == BLEND_FACTOR_ZERO && c->invert_src_factor) && - (c->dst_factor == BLEND_FACTOR_ZERO && !c->invert_dst_factor); + return (c->func == PIPE_BLEND_ADD) && + (c->src_factor == PIPE_BLENDFACTOR_ONE) && + (c->dst_factor == PIPE_BLENDFACTOR_ZERO); } static bool diff --git a/src/compiler/nir/nir_lower_blend.h b/src/compiler/nir/nir_lower_blend.h index aaf45664125..a04e3afc24f 100644 --- a/src/compiler/nir/nir_lower_blend.h +++ b/src/compiler/nir/nir_lower_blend.h @@ -27,19 +27,16 @@ #include "compiler/nir/nir.h" #include "util/format/u_formats.h" +#include "util/blend.h" /* These structs encapsulates the blend state such that it can be lowered * cleanly */ typedef struct { - enum blend_func func; - - enum blend_factor src_factor; - bool invert_src_factor; - - enum blend_factor dst_factor; - bool invert_dst_factor; + enum pipe_blend_func func; + enum pipe_blendfactor src_factor; + enum pipe_blendfactor dst_factor; } nir_lower_blend_channel; typedef struct { @@ -55,7 +52,7 @@ typedef struct { enum pipe_format format[8]; bool logicop_enable; - unsigned logicop_func; + enum pipe_logicop logicop_func; /* If set, will use load_blend_const_color_{r,g,b,a}_float instead of * load_blend_const_color_rgba */ diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 98d063f836d..c68a6783df4 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -181,35 +181,21 @@ agx_create_blend_state(struct pipe_context *ctx, /* No blending, but we get the colour mask below */ } else if (!rt.blend_enable) { static const nir_lower_blend_channel replace = { - .func = BLEND_FUNC_ADD, - .src_factor = BLEND_FACTOR_ZERO, - .invert_src_factor = true, - .dst_factor = BLEND_FACTOR_ZERO, - .invert_dst_factor = false, + .func = PIPE_BLEND_ADD, + .src_factor = PIPE_BLENDFACTOR_ONE, + .dst_factor = PIPE_BLENDFACTOR_ZERO, }; so->rt[i].rgb = replace; so->rt[i].alpha = replace; } else { - so->rt[i].rgb.func = util_blend_func_to_shader(rt.rgb_func); - so->rt[i].rgb.src_factor = - util_blend_factor_to_shader(rt.rgb_src_factor); - so->rt[i].rgb.invert_src_factor = - util_blend_factor_is_inverted(rt.rgb_src_factor); - so->rt[i].rgb.dst_factor = - util_blend_factor_to_shader(rt.rgb_dst_factor); - so->rt[i].rgb.invert_dst_factor = - util_blend_factor_is_inverted(rt.rgb_dst_factor); + so->rt[i].rgb.func = rt.rgb_func; + so->rt[i].rgb.src_factor = rt.rgb_src_factor; + so->rt[i].rgb.dst_factor = rt.rgb_dst_factor; - so->rt[i].alpha.func = util_blend_func_to_shader(rt.alpha_func); - so->rt[i].alpha.src_factor = - util_blend_factor_to_shader(rt.alpha_src_factor); - so->rt[i].alpha.invert_src_factor = - util_blend_factor_is_inverted(rt.alpha_src_factor); - so->rt[i].alpha.dst_factor = - util_blend_factor_to_shader(rt.alpha_dst_factor); - so->rt[i].alpha.invert_dst_factor = - util_blend_factor_is_inverted(rt.alpha_dst_factor); + so->rt[i].alpha.func = rt.alpha_func; + so->rt[i].alpha.src_factor = rt.alpha_src_factor; + so->rt[i].alpha.dst_factor = rt.alpha_dst_factor; so->blend_enable = true; } @@ -1631,11 +1617,9 @@ agx_create_shader_state(struct pipe_context *pctx, key.fs.blend.rt[i].colormask = 0xF; const nir_lower_blend_channel replace = { - .func = BLEND_FUNC_ADD, - .src_factor = BLEND_FACTOR_ZERO, - .invert_src_factor = true, - .dst_factor = BLEND_FACTOR_ZERO, - .invert_dst_factor = false, + .func = PIPE_BLEND_ADD, + .src_factor = PIPE_BLENDFACTOR_ONE, + .dst_factor = PIPE_BLENDFACTOR_ZERO, }; key.fs.blend.rt[i].rgb = replace; diff --git a/src/panfrost/lib/pan_blend.c b/src/panfrost/lib/pan_blend.c index aacf926694d..782c7e11e1d 100644 --- a/src/panfrost/lib/pan_blend.c +++ b/src/panfrost/lib/pan_blend.c @@ -23,6 +23,7 @@ */ #include "pan_blend.h" +#include "util/blend.h" #ifdef PAN_ARCH #include "pan_shader.h" @@ -36,6 +37,67 @@ #include "util/format/u_format.h" #include "pan_texture.h" +static inline enum pipe_blend_func +to_pipe_blend_func(enum blend_func func) +{ + switch (func) { + case BLEND_FUNC_ADD: + return PIPE_BLEND_ADD; + case BLEND_FUNC_SUBTRACT: + return PIPE_BLEND_SUBTRACT; + case BLEND_FUNC_REVERSE_SUBTRACT: + return PIPE_BLEND_REVERSE_SUBTRACT; + case BLEND_FUNC_MIN: + return PIPE_BLEND_MIN; + case BLEND_FUNC_MAX: + return PIPE_BLEND_MAX; + } + + unreachable("invalid"); +} + +static inline enum pipe_blendfactor +to_pipe_blendfactor_uninverted(enum blend_factor factor) +{ + switch (factor) { + case BLEND_FACTOR_SRC_COLOR: + return PIPE_BLENDFACTOR_SRC_COLOR; + case BLEND_FACTOR_SRC1_COLOR: + return PIPE_BLENDFACTOR_SRC1_COLOR; + case BLEND_FACTOR_DST_COLOR: + return PIPE_BLENDFACTOR_DST_COLOR; + case BLEND_FACTOR_SRC_ALPHA: + return PIPE_BLENDFACTOR_SRC_ALPHA; + case BLEND_FACTOR_SRC1_ALPHA: + return PIPE_BLENDFACTOR_SRC1_ALPHA; + case BLEND_FACTOR_DST_ALPHA: + return PIPE_BLENDFACTOR_DST_ALPHA; + case BLEND_FACTOR_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_CONST_COLOR; + case BLEND_FACTOR_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_CONST_ALPHA; + case BLEND_FACTOR_SRC_ALPHA_SATURATE: + return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + default: + unreachable("Invalid"); + } +} + +static inline enum pipe_blendfactor +to_pipe_blendfactor(enum blend_factor factor, bool inverted) +{ + /* Flipped so handle special */ + if (factor == BLEND_FACTOR_ZERO) + return inverted ? PIPE_BLENDFACTOR_ONE : PIPE_BLENDFACTOR_ZERO; + + enum pipe_blendfactor pipe = to_pipe_blendfactor_uninverted(factor); + + if (inverted) + pipe |= PIPE_BLENDFACTOR_INVERT_BIT; + + return pipe; +} + #ifndef PAN_ARCH /* Fixed function blending */ @@ -637,30 +699,29 @@ GENX(pan_blend_create_shader)(const struct panfrost_device *dev, if (!rt_state->equation.blend_enable) { static const nir_lower_blend_channel replace = { - .func = BLEND_FUNC_ADD, - .src_factor = BLEND_FACTOR_ZERO, - .invert_src_factor = true, - .dst_factor = BLEND_FACTOR_ZERO, - .invert_dst_factor = false, + .func = PIPE_BLEND_ADD, + .src_factor = PIPE_BLENDFACTOR_ONE, + .dst_factor = PIPE_BLENDFACTOR_ZERO, }; options.rt[rt].rgb = replace; options.rt[rt].alpha = replace; } else { - options.rt[rt].rgb.func = rt_state->equation.rgb_func; - options.rt[rt].rgb.src_factor = rt_state->equation.rgb_src_factor; - options.rt[rt].rgb.invert_src_factor = - rt_state->equation.rgb_invert_src_factor; - options.rt[rt].rgb.dst_factor = rt_state->equation.rgb_dst_factor; - options.rt[rt].rgb.invert_dst_factor = - rt_state->equation.rgb_invert_dst_factor; - options.rt[rt].alpha.func = rt_state->equation.alpha_func; - options.rt[rt].alpha.src_factor = rt_state->equation.alpha_src_factor; - options.rt[rt].alpha.invert_src_factor = - rt_state->equation.alpha_invert_src_factor; - options.rt[rt].alpha.dst_factor = rt_state->equation.alpha_dst_factor; - options.rt[rt].alpha.invert_dst_factor = - rt_state->equation.alpha_invert_dst_factor; + options.rt[rt].rgb.func = to_pipe_blend_func(rt_state->equation.rgb_func); + options.rt[rt].rgb.src_factor = + to_pipe_blendfactor(rt_state->equation.rgb_src_factor, + rt_state->equation.rgb_invert_src_factor); + options.rt[rt].rgb.dst_factor = + to_pipe_blendfactor(rt_state->equation.rgb_dst_factor, + rt_state->equation.rgb_invert_dst_factor); + options.rt[rt].alpha.func = + to_pipe_blend_func(rt_state->equation.alpha_func); + options.rt[rt].alpha.src_factor = + to_pipe_blendfactor(rt_state->equation.alpha_src_factor, + rt_state->equation.alpha_invert_src_factor); + options.rt[rt].alpha.dst_factor = + to_pipe_blendfactor(rt_state->equation.alpha_dst_factor, + rt_state->equation.alpha_invert_dst_factor); } nir_ssa_def *pixel = nir_load_barycentric_pixel(&b, 32, .interp_mode = 1); diff --git a/src/panfrost/vulkan/panvk_vX_shader.c b/src/panfrost/vulkan/panvk_vX_shader.c index 483a44e5a43..e889799249b 100644 --- a/src/panfrost/vulkan/panvk_vX_shader.c +++ b/src/panfrost/vulkan/panvk_vX_shader.c @@ -120,6 +120,67 @@ panvk_lower_sysvals(nir_builder *b, nir_instr *instr, void *data) return true; } +static inline enum pipe_blend_func +to_pipe_blend_func(enum blend_func func) +{ + switch (func) { + case BLEND_FUNC_ADD: + return PIPE_BLEND_ADD; + case BLEND_FUNC_SUBTRACT: + return PIPE_BLEND_SUBTRACT; + case BLEND_FUNC_REVERSE_SUBTRACT: + return PIPE_BLEND_REVERSE_SUBTRACT; + case BLEND_FUNC_MIN: + return PIPE_BLEND_MIN; + case BLEND_FUNC_MAX: + return PIPE_BLEND_MAX; + } + + unreachable("invalid"); +} + +static inline enum pipe_blendfactor +to_pipe_blendfactor_uninverted(enum blend_factor factor) +{ + switch (factor) { + case BLEND_FACTOR_SRC_COLOR: + return PIPE_BLENDFACTOR_SRC_COLOR; + case BLEND_FACTOR_SRC1_COLOR: + return PIPE_BLENDFACTOR_SRC1_COLOR; + case BLEND_FACTOR_DST_COLOR: + return PIPE_BLENDFACTOR_DST_COLOR; + case BLEND_FACTOR_SRC_ALPHA: + return PIPE_BLENDFACTOR_SRC_ALPHA; + case BLEND_FACTOR_SRC1_ALPHA: + return PIPE_BLENDFACTOR_SRC1_ALPHA; + case BLEND_FACTOR_DST_ALPHA: + return PIPE_BLENDFACTOR_DST_ALPHA; + case BLEND_FACTOR_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_CONST_COLOR; + case BLEND_FACTOR_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_CONST_ALPHA; + case BLEND_FACTOR_SRC_ALPHA_SATURATE: + return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + default: + unreachable("Invalid"); + } +} + +static inline enum pipe_blendfactor +to_pipe_blendfactor(enum blend_factor factor, bool inverted) +{ + /* Flipped so handle special */ + if (factor == BLEND_FACTOR_ZERO) + return inverted ? PIPE_BLENDFACTOR_ONE : PIPE_BLENDFACTOR_ZERO; + + enum pipe_blendfactor pipe = to_pipe_blendfactor_uninverted(factor); + + if (inverted) + pipe |= PIPE_BLENDFACTOR_INVERT_BIT; + + return pipe; +} + static void panvk_lower_blend(struct panfrost_device *pdev, nir_shader *nir, struct panfrost_compile_inputs *inputs, @@ -145,30 +206,30 @@ panvk_lower_blend(struct panfrost_device *pdev, nir_shader *nir, if (!rt_state->equation.blend_enable) { static const nir_lower_blend_channel replace = { - .func = BLEND_FUNC_ADD, - .src_factor = BLEND_FACTOR_ZERO, - .invert_src_factor = true, - .dst_factor = BLEND_FACTOR_ZERO, - .invert_dst_factor = false, + .func = PIPE_BLEND_ADD, + .src_factor = PIPE_BLENDFACTOR_ONE, + .dst_factor = PIPE_BLENDFACTOR_ZERO, }; options.rt[rt].rgb = replace; options.rt[rt].alpha = replace; } else { - options.rt[rt].rgb.func = rt_state->equation.rgb_func; - options.rt[rt].rgb.src_factor = rt_state->equation.rgb_src_factor; - options.rt[rt].rgb.invert_src_factor = - rt_state->equation.rgb_invert_src_factor; - options.rt[rt].rgb.dst_factor = rt_state->equation.rgb_dst_factor; - options.rt[rt].rgb.invert_dst_factor = - rt_state->equation.rgb_invert_dst_factor; - options.rt[rt].alpha.func = rt_state->equation.alpha_func; - options.rt[rt].alpha.src_factor = rt_state->equation.alpha_src_factor; - options.rt[rt].alpha.invert_src_factor = - rt_state->equation.alpha_invert_src_factor; - options.rt[rt].alpha.dst_factor = rt_state->equation.alpha_dst_factor; - options.rt[rt].alpha.invert_dst_factor = - rt_state->equation.alpha_invert_dst_factor; + options.rt[rt].rgb.func = + to_pipe_blend_func(rt_state->equation.rgb_func); + options.rt[rt].rgb.src_factor = + to_pipe_blendfactor(rt_state->equation.rgb_src_factor, + rt_state->equation.rgb_invert_src_factor); + options.rt[rt].rgb.dst_factor = + to_pipe_blendfactor(rt_state->equation.rgb_dst_factor, + rt_state->equation.rgb_invert_dst_factor); + options.rt[rt].alpha.func = + to_pipe_blend_func(rt_state->equation.alpha_func); + options.rt[rt].alpha.src_factor = + to_pipe_blendfactor(rt_state->equation.alpha_src_factor, + rt_state->equation.alpha_invert_src_factor); + options.rt[rt].alpha.dst_factor = + to_pipe_blendfactor(rt_state->equation.alpha_dst_factor, + rt_state->equation.alpha_invert_dst_factor); } /* Update the equation to force a color replacement */