From 0dc1dfe6444a700ebd2c9f006cba000b90c3a7b0 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 6 Oct 2012 15:35:53 +0200 Subject: [PATCH] Make Input an abstract base class, and move the current functionality into FlatInput. Also change a bit how we deal with adding them. --- Makefile | 2 +- effect_chain.cpp | 7 ++-- effect_chain.h | 4 ++- input.cpp => flat_input.cpp | 12 +++---- input.frag => flat_input.frag | 0 flat_input.h | 64 +++++++++++++++++++++++++++++++++++ input.h | 60 +++++++------------------------- main.cpp | 4 ++- 8 files changed, 92 insertions(+), 61 deletions(-) rename input.cpp => flat_input.cpp (91%) rename input.frag => flat_input.frag (100%) create mode 100644 flat_input.h diff --git a/Makefile b/Makefile index 8b8b655..51aebc5 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CXXFLAGS=-Wall -g 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 diff --git a/effect_chain.cpp b/effect_chain.cpp index 7232dcb..82e9c5d 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -24,16 +24,15 @@ EffectChain::EffectChain(unsigned width, unsigned height) 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())); return input; diff --git a/effect_chain.h b/effect_chain.h index f9e1255..0b07b85 100644 --- a/effect_chain.h +++ b/effect_chain.h @@ -15,7 +15,9 @@ public: // 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. diff --git a/input.cpp b/flat_input.cpp similarity index 91% rename from input.cpp rename to flat_input.cpp index 1df39c6..2541dc4 100644 --- a/input.cpp +++ b/flat_input.cpp @@ -5,10 +5,10 @@ #include #include -#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), @@ -22,7 +22,7 @@ Input::Input(ImageFormat image_format, unsigned width, unsigned height) register_int("needs_mipmaps", &needs_mipmaps); } -void Input::finalize() +void FlatInput::finalize() { // Translate the input format to OpenGL's enums. GLenum internal_format; @@ -81,7 +81,7 @@ void Input::finalize() 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(); @@ -119,7 +119,7 @@ void Input::set_gl_state(GLuint glsl_program_num, const std::string& prefix, uns ++*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"); } diff --git a/input.frag b/flat_input.frag similarity index 100% rename from input.frag rename to flat_input.frag diff --git a/flat_input.h b/flat_input.h new file mode 100644 index 0000000..a906a5d --- /dev/null +++ b/flat_input.h @@ -0,0 +1,64 @@ +#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) diff --git a/input.h b/input.h index d41b266..ac03e84 100644 --- a/input.h +++ b/input.h @@ -7,61 +7,25 @@ #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) diff --git a/main.cpp b/main.cpp index bc52e1d..4fbcdf3 100644 --- a/main.cpp +++ b/main.cpp @@ -26,6 +26,7 @@ #include "util.h" #include "widgets.h" +#include "flat_input.h" #include "lift_gamma_gain_effect.h" #include "saturation_effect.h" #include "diffusion_effect.h" @@ -168,7 +169,8 @@ int main(int argc, char **argv) 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()); -- 2.39.2