vpass->set_int("direction", SingleBlurPassEffect::VERTICAL);
}
-void BlurEffect::add_self_to_effect_chain(std::vector<Effect *> *chain) {
- hpass->add_self_to_effect_chain(chain);
- vpass->add_self_to_effect_chain(chain);
+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);
}
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(std::vector<Effect *> *chain);
+ virtual void add_self_to_effect_chain(EffectChain *chain, Effect *input);
virtual bool set_float(const std::string &key, float value);
private:
#include <string.h>
#include <assert.h>
#include "effect.h"
+#include "effect_chain.h"
#include "util.h"
#include <GL/gl.h>
params_tex_1d[key].needs_update = true;
}
+void Effect::add_self_to_effect_chain(EffectChain *chain, Effect *input)
+{
+ chain->add_effect_raw(this, input);
+}
+
// Output convenience uniforms for each parameter.
// These will be filled in per-frame.
std::string Effect::output_convenience_uniforms() const
#include <GL/gl.h>
+class EffectChain;
+
// Can alias on a float[2].
struct Point2D {
Point2D(float x, float y)
// 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(std::vector<Effect *> *chain) {
- chain->push_back(this);
- }
+ virtual void add_self_to_effect_chain(EffectChain *graph, Effect *input);
// Outputs one GLSL uniform declaration for each registered parameter
// (see below), with the right prefix prepended to each uniform name.
#include "blur_effect.h"
EffectChain::EffectChain(unsigned width, unsigned height)
- : width(width), height(height), use_srgb_texture_format(false), finalized(false) {}
+ : width(width),
+ height(height),
+ last_added_effect(NULL),
+ use_srgb_texture_format(false),
+ finalized(false) {}
void EffectChain::add_input(const ImageFormat &format)
{
{
output_format = format;
}
-
+
+void EffectChain::add_effect_raw(Effect *effect, Effect *input)
+{
+ effects.push_back(effect);
+ outgoing_links.insert(std::make_pair(input, effect));
+ incoming_links.insert(std::make_pair(effect, input));
+ last_added_effect = effect;
+}
+
Effect *instantiate_effect(EffectId effect)
{
switch (effect) {
assert(false);
}
-void EffectChain::normalize_to_linear_gamma()
+Effect *EffectChain::normalize_to_linear_gamma(Effect *input)
{
if (current_gamma_curve == GAMMA_sRGB) {
// TODO: check if the extension exists
use_srgb_texture_format = true;
+ current_gamma_curve = GAMMA_LINEAR;
+ return input;
} else {
GammaExpansionEffect *gamma_conversion = new GammaExpansionEffect();
gamma_conversion->set_int("source_curve", current_gamma_curve);
- gamma_conversion->add_self_to_effect_chain(&effects);
+ gamma_conversion->add_self_to_effect_chain(this, input);
+ current_gamma_curve = GAMMA_LINEAR;
+ return gamma_conversion;
}
- current_gamma_curve = GAMMA_LINEAR;
}
-void EffectChain::normalize_to_srgb()
+Effect *EffectChain::normalize_to_srgb(Effect *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(&effects);
+ colorspace_conversion->add_self_to_effect_chain(this, input);
current_color_space = COLORSPACE_sRGB;
+ return colorspace_conversion;
}
-Effect *EffectChain::add_effect(EffectId effect_id)
+Effect *EffectChain::add_effect(EffectId effect_id, Effect *input)
{
Effect *effect = instantiate_effect(effect_id);
if (effect->needs_linear_light() && current_gamma_curve != GAMMA_LINEAR) {
- normalize_to_linear_gamma();
+ input = normalize_to_linear_gamma(input);
}
if (effect->needs_srgb_primaries() && current_color_space != COLORSPACE_sRGB) {
- normalize_to_srgb();
+ input = normalize_to_srgb(input);
}
- effect->add_self_to_effect_chain(&effects);
+ effect->add_self_to_effect_chain(this, input);
return effect;
}
}
if (current_gamma_curve != output_format.gamma_curve) {
if (current_gamma_curve != GAMMA_LINEAR) {
- normalize_to_linear_gamma();
+ normalize_to_linear_gamma(last_added_effect); // FIXME
}
assert(current_gamma_curve == GAMMA_LINEAR);
GammaCompressionEffect *gamma_conversion = new GammaCompressionEffect();
public:
EffectChain(unsigned width, unsigned height);
+ // User API:
// input, effects, output, finalize need to come in that specific order.
void add_input(const ImageFormat &format);
// The returned pointer is owned by EffectChain.
- Effect *add_effect(EffectId effect);
+ Effect *add_effect(EffectId effect) {
+ return add_effect(effect, get_last_added_effect());
+ }
+ Effect *add_effect(EffectId effect, Effect *input);
+
+ // Similar to add_effect, but:
+ //
+ // * Does not insert any normalizing effects.
+ // * Does not ask the effect to insert itself, so it won't work
+ // with meta-effects.
+ //
+ // 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_output(const ImageFormat &format);
void finalize();
//void render(unsigned char *src, unsigned char *dst);
void render_to_screen(unsigned char *src);
+ Effect *get_last_added_effect() {
+ return last_added_effect;
+ }
+
private:
struct Phase {
GLint glsl_program_num;
unsigned start, end;
};
- void normalize_to_linear_gamma();
- void normalize_to_srgb();
+ Effect *normalize_to_linear_gamma(Effect *input);
+ Effect *normalize_to_srgb(Effect *input);
// Create a GLSL program computing effects [start, end>.
Phase compile_glsl_program(unsigned start_index, unsigned end_index);
unsigned width, height;
ImageFormat input_format, output_format;
std::vector<Effect *> effects;
+ std::multimap<Effect *, Effect *> outgoing_links;
+ std::multimap<Effect *, Effect *> incoming_links;
+ Effect *last_added_effect;
GLuint source_image_num;
bool use_srgb_texture_format;