vpass->set_int("direction", SingleBlurPassEffect::VERTICAL);
}
-void BlurEffect::add_self_to_effect_chain(EffectChain *chain, Effect *input) {
- hpass->add_self_to_effect_chain(chain, input);
- vpass->add_self_to_effect_chain(chain, hpass);
+void BlurEffect::add_self_to_effect_chain(EffectChain *chain, const std::vector<Effect *> &inputs) {
+ assert(inputs.size() == 1);
+ hpass->add_self_to_effect_chain(chain, inputs);
+
+ std::vector<Effect *> vpass_inputs;
+ vpass_inputs.push_back(hpass);
+ vpass->add_self_to_effect_chain(chain, vpass_inputs);
}
bool BlurEffect::set_float(const std::string &key, float value) {
virtual bool needs_texture_bounce() const { return true; }
virtual bool needs_mipmaps() const { return true; }
- virtual void add_self_to_effect_chain(EffectChain *chain, Effect *input);
+ virtual void add_self_to_effect_chain(EffectChain *chain, const std::vector<Effect *> &input);
virtual bool set_float(const std::string &key, float value);
private:
params_tex_1d[key].needs_update = true;
}
-void Effect::add_self_to_effect_chain(EffectChain *chain, Effect *input)
+void Effect::add_self_to_effect_chain(EffectChain *chain, const std::vector<Effect *> &inputs)
{
- chain->add_effect_raw(this, input);
+ chain->add_effect_raw(this, inputs);
}
// Output convenience uniforms for each parameter.
// needs mipmaps, you will also get them).
virtual bool needs_mipmaps() const { return false; }
+ // How many inputs this effect will take (a fixed number).
+ // If you have only one input, it will be called INPUT() in GLSL;
+ // if you have several, they will be INPUT1(), INPUT2(), and so on.
+ virtual unsigned num_inputs() const { return 1; }
+
// Requests that this effect adds itself to the given effect chain.
// For most effects, the default will be fine, but for effects that
// consist of multiple passes, it is often useful to replace this
// with something that adds completely different things to the chain.
- virtual void add_self_to_effect_chain(EffectChain *graph, Effect *input);
+ virtual void add_self_to_effect_chain(EffectChain *graph, const std::vector<Effect *> &inputs);
// Outputs one GLSL uniform declaration for each registered parameter
// (see below), with the right prefix prepended to each uniform name.
void EffectChain::add_input(const ImageFormat &format)
{
input_format = format;
- current_color_space = format.color_space;
- current_gamma_curve = format.gamma_curve;
+ output_color_space.insert(std::make_pair(static_cast<Effect *>(NULL), format.color_space));
+ output_gamma_curve.insert(std::make_pair(static_cast<Effect *>(NULL), format.gamma_curve));
}
void EffectChain::add_output(const ImageFormat &format)
output_format = format;
}
-void EffectChain::add_effect_raw(Effect *effect, Effect *input)
+void EffectChain::add_effect_raw(Effect *effect, const std::vector<Effect *> &inputs)
{
effects.push_back(effect);
- outgoing_links.insert(std::make_pair(input, effect));
- incoming_links.insert(std::make_pair(effect, input));
+ assert(inputs.size() == effect->num_inputs());
+ for (unsigned i = 0; i < inputs.size(); ++i) {
+ outgoing_links.insert(std::make_pair(inputs[i], effect));
+ incoming_links.insert(std::make_pair(effect, inputs[i]));
+ }
last_added_effect = effect;
}
Effect *EffectChain::normalize_to_linear_gamma(Effect *input)
{
+ GammaCurve current_gamma_curve = output_gamma_curve[input];
if (current_gamma_curve == GAMMA_sRGB) {
// TODO: check if the extension exists
use_srgb_texture_format = true;
} else {
GammaExpansionEffect *gamma_conversion = new GammaExpansionEffect();
gamma_conversion->set_int("source_curve", current_gamma_curve);
- gamma_conversion->add_self_to_effect_chain(this, input);
+ std::vector<Effect *> inputs;
+ inputs.push_back(input);
+ gamma_conversion->add_self_to_effect_chain(this, inputs);
current_gamma_curve = GAMMA_LINEAR;
return gamma_conversion;
}
Effect *EffectChain::normalize_to_srgb(Effect *input)
{
+ GammaCurve current_gamma_curve = output_gamma_curve[input];
+ ColorSpace current_color_space = output_color_space[input];
assert(current_gamma_curve == GAMMA_LINEAR);
ColorSpaceConversionEffect *colorspace_conversion = new ColorSpaceConversionEffect();
colorspace_conversion->set_int("source_space", current_color_space);
colorspace_conversion->set_int("destination_space", COLORSPACE_sRGB);
- colorspace_conversion->add_self_to_effect_chain(this, input);
+ std::vector<Effect *> inputs;
+ inputs.push_back(input);
+ colorspace_conversion->add_self_to_effect_chain(this, inputs);
current_color_space = COLORSPACE_sRGB;
return colorspace_conversion;
}
-Effect *EffectChain::add_effect(EffectId effect_id, Effect *input)
+Effect *EffectChain::add_effect(EffectId effect_id, const std::vector<Effect *> &inputs)
{
Effect *effect = instantiate_effect(effect_id);
- if (effect->needs_linear_light() && current_gamma_curve != GAMMA_LINEAR) {
- input = normalize_to_linear_gamma(input);
- }
+ assert(inputs.size() == effect->num_inputs());
- if (effect->needs_srgb_primaries() && current_color_space != COLORSPACE_sRGB) {
- input = normalize_to_srgb(input);
+ std::vector<Effect *> normalized_inputs = inputs;
+ for (unsigned i = 0; i < normalized_inputs.size(); ++i) {
+ if (effect->needs_linear_light() && output_gamma_curve[normalized_inputs[i]] != GAMMA_LINEAR) {
+ normalized_inputs[i] = normalize_to_linear_gamma(normalized_inputs[i]);
+ }
+ if (effect->needs_srgb_primaries() && output_color_space[normalized_inputs[i]] != COLORSPACE_sRGB) {
+ normalized_inputs[i] = normalize_to_srgb(normalized_inputs[i]);
+ }
}
- effect->add_self_to_effect_chain(this, input);
+ effect->add_self_to_effect_chain(this, normalized_inputs);
return effect;
}
void EffectChain::finalize()
{
// Add normalizers to get the output format right.
+ GammaCurve current_gamma_curve = output_gamma_curve[last_added_effect]; // FIXME
+ ColorSpace current_color_space = output_color_space[last_added_effect]; // FIXME
if (current_color_space != output_format.color_space) {
ColorSpaceConversionEffect *colorspace_conversion = new ColorSpaceConversionEffect();
colorspace_conversion->set_int("source_space", current_color_space);
Effect *add_effect(EffectId effect) {
return add_effect(effect, get_last_added_effect());
}
- Effect *add_effect(EffectId effect, Effect *input);
+ Effect *add_effect(EffectId effect, Effect *input) {
+ std::vector<Effect *> inputs;
+ inputs.push_back(input);
+ return add_effect(effect, inputs);
+ }
+ Effect *add_effect(EffectId effect, Effect *input1, Effect *input2) {
+ std::vector<Effect *> inputs;
+ inputs.push_back(input1);
+ inputs.push_back(input2);
+ return add_effect(effect, inputs);
+ }
+ Effect *add_effect(EffectId effect, const std::vector<Effect *> &inputs);
// Similar to add_effect, but:
//
//
// We should really separate out these two “sides” of Effect in the
// type system soon.
- void add_effect_raw(Effect *effect, Effect *input);
+ void add_effect_raw(Effect *effect, const std::vector<Effect *> &inputs);
void add_output(const ImageFormat &format);
void finalize();
bool finalized;
// Used during the building of the effect chain.
- ColorSpace current_color_space;
- GammaCurve current_gamma_curve;
+ std::map<Effect *, ColorSpace> output_color_space;
+ std::map<Effect *, GammaCurve> output_gamma_curve;
};