LDFLAGS=-lSDL -lSDL_image -lGL
# Core.
-OBJS=main.o util.o widgets.o effect.o effect_chain.o input.o
+OBJS=main.o util.o widgets.o effect.o effect_chain.o flat_input.o
# Effects.
OBJS += lift_gamma_gain_effect.o
height(height),
finalized(false) {}
-Input *EffectChain::add_input(const ImageFormat &format)
+Input *EffectChain::add_input(Input *input)
{
char eff_id[256];
sprintf(eff_id, "src_image%u", (unsigned)inputs.size());
- Input *input = new Input(format, width, height);
effects.push_back(input);
inputs.push_back(input);
- output_color_space.insert(std::make_pair(input, format.color_space));
- output_gamma_curve.insert(std::make_pair(input, format.gamma_curve));
+ output_color_space.insert(std::make_pair(input, input->get_color_space()));
+ output_gamma_curve.insert(std::make_pair(input, input->get_gamma_curve()));
effect_ids.insert(std::make_pair(input, eff_id));
incoming_links.insert(std::make_pair(input, std::vector<Effect *>()));
return input;
// User API:
// input, effects, output, finalize need to come in that specific order.
- Input *add_input(const ImageFormat &format);
+ // EffectChain takes ownership of the given input.
+ // input is returned back for convenience.
+ Input *add_input(Input *input);
// EffectChain takes ownership of the given effect.
// effect is returned back for convenience.
#include <GL/glext.h>
#include <assert.h>
-#include "input.h"
+#include "flat_input.h"
#include "util.h"
-Input::Input(ImageFormat image_format, unsigned width, unsigned height)
+FlatInput::FlatInput(ImageFormat image_format, unsigned width, unsigned height)
: image_format(image_format),
needs_update(false),
finalized(false),
register_int("needs_mipmaps", &needs_mipmaps);
}
-void Input::finalize()
+void FlatInput::finalize()
{
// Translate the input format to OpenGL's enums.
GLenum internal_format;
finalized = true;
}
-void Input::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
+void FlatInput::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
{
glActiveTexture(GL_TEXTURE0 + *sampler_num);
check_error();
++*sampler_num;
}
-std::string Input::output_fragment_shader()
+std::string FlatInput::output_fragment_shader()
{
- return read_file("input.frag");
+ return read_file("flat_input.frag");
}
--- /dev/null
+#ifndef _FLAT_INPUT_H
+#define _FLAT_INPUT_H 1
+
+#include "input.h"
+
+// A FlatInput is the normal, “classic” case of an input, where everything
+// comes from a single 2D array with chunky pixels.
+class FlatInput : public Input {
+public:
+ FlatInput(ImageFormat format, unsigned width, unsigned height);
+
+ // Create the texture itself. We cannot do this in the constructor,
+ // because we don't necessarily know all the settings (sRGB texture,
+ // mipmap generation) at that point.
+ void finalize();
+
+ std::string output_fragment_shader();
+
+ // Uploads the texture if it has changed since last time.
+ void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num);
+
+ ColorSpace get_color_space() { return image_format.color_space; }
+ GammaCurve get_gamma_curve() { return image_format.gamma_curve; }
+
+ // Tells the input where to fetch the actual pixel data. Note that if you change
+ // this data, you must either call set_pixel_data() again (using the same pointer
+ // is fine), or invalidate_pixel_data(). Otherwise, the texture won't be re-uploaded
+ // on subsequent frames.
+ void set_pixel_data(const unsigned char *pixel_data)
+ {
+ this->pixel_data = pixel_data;
+ invalidate_pixel_data();
+ }
+
+ void invalidate_pixel_data()
+ {
+ needs_update = true;
+ }
+
+ const unsigned char *get_pixel_data() const
+ {
+ return pixel_data;
+ }
+
+ void set_pitch(unsigned pitch) {
+ assert(!finalized);
+ this->pitch = pitch;
+ }
+
+ unsigned get_pitch() {
+ return pitch;
+ }
+
+private:
+ ImageFormat image_format;
+ GLenum format;
+ GLuint pbo, texture_num;
+ bool needs_update, finalized;
+ int use_srgb_texture_format, needs_mipmaps;
+ unsigned width, height, pitch, bytes_per_pixel;
+ const unsigned char *pixel_data;
+};
+
+#endif // !defined(_FLAT_INPUT_H)
#include "image_format.h"
// An input is a degenerate case of an effect; it represents the picture data
-// that comes from the user. As such, it has zero “inputs” itself, and some of
-// the normal operations don't really make sense for it.
+// that comes from the user. As such, it has zero “inputs” itself. Also, it
+// has an extra operation called finalize(), which runs when the effect chain
+// is finalized.
+//
+// An input is, like any other effect, required to be able to output a GLSL
+// fragment giving a RGBA value (although that GLSL fragment will have zero
+// inputs itself), and set the required OpenGL state on set_gl_state(),
+// including possibly uploading the texture if so required.
class Input : public Effect {
public:
- Input(ImageFormat format, unsigned width, unsigned height);
-
- unsigned num_inputs() const { return 0; }
+ virtual unsigned num_inputs() const { return 0; }
// Create the texture itself. We cannot do this in the constructor,
// because we don't necessarily know all the settings (sRGB texture,
// mipmap generation) at that point.
- void finalize();
-
- std::string output_fragment_shader();
-
- // Uploads the texture if it has changed since last time.
- void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num);
-
- // Tells the input where to fetch the actual pixel data. Note that if you change
- // this data, you must either call set_pixel_data() again (using the same pointer
- // is fine), or invalidate_pixel_data(). Otherwise, the texture won't be re-uploaded
- // on subsequent frames.
- void set_pixel_data(const unsigned char *pixel_data)
- {
- this->pixel_data = pixel_data;
- invalidate_pixel_data();
- }
-
- void invalidate_pixel_data()
- {
- needs_update = true;
- }
-
- const unsigned char *get_pixel_data() const
- {
- return pixel_data;
- }
-
- void set_pitch(unsigned pitch) {
- assert(!finalized);
- this->pitch = pitch;
- }
-
- unsigned get_pitch() {
- return pitch;
- }
+ virtual void finalize() = 0;
-private:
- ImageFormat image_format;
- GLenum format;
- GLuint pbo, texture_num;
- bool needs_update, finalized;
- int use_srgb_texture_format, needs_mipmaps;
- unsigned width, height, pitch, bytes_per_pixel;
- const unsigned char *pixel_data;
+ virtual ColorSpace get_color_space() = 0;
+ virtual GammaCurve get_gamma_curve() = 0;
};
#endif // !defined(_INPUT_H)
#include "util.h"
#include "widgets.h"
+#include "flat_input.h"
#include "lift_gamma_gain_effect.h"
#include "saturation_effect.h"
#include "diffusion_effect.h"
inout_format.color_space = COLORSPACE_sRGB;
inout_format.gamma_curve = GAMMA_sRGB;
- Input *input = chain.add_input(inout_format);
+ FlatInput *input = new FlatInput(inout_format, WIDTH, HEIGHT);
+ chain.add_input(input);
Effect *lift_gamma_gain_effect = chain.add_effect(new LiftGammaGainEffect());
Effect *saturation_effect = chain.add_effect(new SaturationEffect());
Effect *diffusion_effect = chain.add_effect(new DiffusionEffect());