X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=effect.h;h=67e64238beb2bdc590f75ed83327b045d3e80c29;hp=fbe39d7274a421fd9f906ae809fdace3df7a8bc2;hb=refs%2Fheads%2F1.3.x-release;hpb=b564238fa1293c01c77bcabe7b2de267f146ab24 diff --git a/effect.h b/effect.h index fbe39d7..67e6423 100644 --- a/effect.h +++ b/effect.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "defs.h" @@ -25,6 +27,7 @@ class Node; // Can alias on a float[2]. struct Point2D { + Point2D() {} Point2D(float x, float y) : x(x), y(y) {} @@ -33,6 +36,7 @@ struct Point2D { // Can alias on a float[3]. struct RGBTriplet { + RGBTriplet() {} RGBTriplet(float r, float g, float b) : r(r), g(g), b(b) {} @@ -41,12 +45,23 @@ struct RGBTriplet { // Can alias on a float[4]. struct RGBATuple { + RGBATuple() {} RGBATuple(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {} float r, g, b, a; }; +// Represents a registered uniform. +template +struct Uniform { + std::string name; // Without prefix. + const T *value; // Owner by the effect. + size_t num_values; // Number of elements; for arrays only. _Not_ the vector length. + std::string prefix; // Filled in only after phases have been constructed. + GLint location; // Filled in only after phases have been constructed. -1 if no location. +}; + class Effect { public: virtual ~Effect() {} @@ -202,6 +217,20 @@ public: // and allow dependent effects to change that sampler state. virtual bool is_single_texture() const { return false; } + // If set, this effect should never be bounced to an output, even if a + // dependent effect demands texture bounce. + // + // Note that setting this can invoke undefined behavior, up to and including crashing, + // so you should only use it if you have deep understanding of your entire chain + // and Movit's processing of it. The most likely use case is if you have an input + // that's cheap to compute but not a single texture (e.g. YCbCrInput), and want + // to run a ResampleEffect directly from it. Normally, this would require a bounce, + // but it's faster not to. (However, also note that in this case, effective texel + // subpixel precision will be too optimistic, since chroma is already subsampled.) + // + // Has no effect if is_single_texture() is set. + virtual bool override_disable_bounce() const { return false; } + // If changes_output_size() is true, you must implement this to tell // the framework what output size you want. Also, you can set a // virtual width/height, which is the size the next effect (if any) @@ -253,11 +282,6 @@ public: // itself from all other effects. virtual void rewrite_graph(EffectChain *graph, Node *self) {} - // Outputs one GLSL uniform declaration for each registered parameter - // (see below), with the right prefix prepended to each uniform name. - // If you do not want this behavior, you can override this function. - virtual std::string output_convenience_uniforms() const; - // Returns the GLSL fragment shader string for this effect. virtual std::string output_fragment_shader() = 0; @@ -286,26 +310,73 @@ public: protected: // Register a parameter. Whenever set_*() is called with the same key, // it will update the value in the given pointer (typically a pointer - // to some private member variable in your effect). + // to some private member variable in your effect). It will also + // register a uniform of the same name (plus an arbitrary prefix + // which you can access using the PREFIX macro) that you can access. // // Neither of these take ownership of the pointer. - // int is special since GLSL pre-1.30 doesn't have integer uniforms. - // Thus, ints that you register will _not_ be converted to GLSL uniforms. + // These correspond directly to int/float/vec2/vec3/vec4 in GLSL. void register_int(const std::string &key, int *value); - - // These correspond directly to float/vec2/vec3/vec4 in GLSL. void register_float(const std::string &key, float *value); void register_vec2(const std::string &key, float *values); void register_vec3(const std::string &key, float *values); void register_vec4(const std::string &key, float *values); + // Register uniforms, such that they will automatically be set + // before the shader runs. This is more efficient than set_uniform_* + // in effect_util.h, because it doesn't need to do name lookups + // every time. Also, in the future, it will use uniform buffer objects + // (UBOs) if available to reduce the number of calls into the driver. + // + // May not be called after output_fragment_shader() has returned. + // The pointer must be valid for the entire lifetime of the Effect, + // since the value is pulled from it each execution. The value is + // guaranteed to be read after set_gl_state() for the effect has + // returned, so you can safely update its value from there. + // + // Note that this will also declare the uniform in the shader for you, + // so you should not do that yourself. (This is so it can be part of + // the right uniform block.) However, it is probably a good idea to + // have a commented-out declaration so that it is easier to see the + // type and thus understand the shader on its own. + // + // Calling register_* will automatically imply register_uniform_*, + // except for register_int as noted above. + void register_uniform_sampler2d(const std::string &key, const int *value); + void register_uniform_bool(const std::string &key, const bool *value); + void register_uniform_int(const std::string &key, const int *value); // Note: Requires GLSL 1.30 or newer. + void register_uniform_float(const std::string &key, const float *value); + void register_uniform_vec2(const std::string &key, const float *values); + void register_uniform_vec3(const std::string &key, const float *values); + void register_uniform_vec4(const std::string &key, const float *values); + void register_uniform_float_array(const std::string &key, const float *values, size_t num_values); + void register_uniform_vec2_array(const std::string &key, const float *values, size_t num_values); + void register_uniform_vec3_array(const std::string &key, const float *values, size_t num_values); + void register_uniform_vec4_array(const std::string &key, const float *values, size_t num_values); + void register_uniform_mat3(const std::string &key, const Eigen::Matrix3d *matrix); + private: std::map params_int; std::map params_float; std::map params_vec2; std::map params_vec3; std::map params_vec4; + + // Picked out by EffectChain during finalization. + std::vector > uniforms_sampler2d; + std::vector > uniforms_bool; + std::vector > uniforms_int; + std::vector > uniforms_float; + std::vector > uniforms_vec2; + std::vector > uniforms_vec3; + std::vector > uniforms_vec4; + std::vector > uniforms_float_array; + std::vector > uniforms_vec2_array; + std::vector > uniforms_vec3_array; + std::vector > uniforms_vec4_array; + std::vector > uniforms_mat3; + friend class EffectChain; }; } // namespace movit