/usr/include/movit/effect.h is in libmovit-dev 1.1.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | #ifndef _MOVIT_EFFECT_H
#define _MOVIT_EFFECT_H 1
// Effect is the base class for every effect. It basically represents a single
// GLSL function, with an optional set of user-settable parameters.
//
// A note on naming: Since all effects run in the same GLSL namespace,
// you can't use any name you want for global variables (e.g. uniforms).
// The framework assigns a prefix to you which will be unique for each
// effect instance; use the macro PREFIX() around your identifiers to
// automatically prepend that prefix.
#include <epoxy/gl.h>
#include <assert.h>
#include <stddef.h>
#include <map>
#include <string>
#include "defs.h"
namespace movit {
class EffectChain;
class Node;
// Can alias on a float[2].
struct Point2D {
Point2D(float x, float y)
: x(x), y(y) {}
float x, y;
};
// Can alias on a float[3].
struct RGBTriplet {
RGBTriplet(float r, float g, float b)
: r(r), g(g), b(b) {}
float r, g, b;
};
// Can alias on a float[4].
struct RGBATuple {
RGBATuple(float r, float g, float b, float a)
: r(r), g(g), b(b), a(a) {}
float r, g, b, a;
};
class Effect {
public:
virtual ~Effect() {}
// An identifier for this type of effect, mostly used for debug output
// (but some special names, like "ColorspaceConversionEffect", holds special
// meaning). Same as the class name is fine.
virtual std::string effect_type_id() const = 0;
// Whether this effects expects its input (and output) to be in
// linear gamma, ie. without an applied gamma curve. Most effects
// will want this, although the ones that never actually look at
// the pixels, e.g. mirror, won't need to care, and can set this
// to false. If so, the input gamma will be undefined.
//
// Also see the note on needs_texture_bounce(), below.
virtual bool needs_linear_light() const { return true; }
// Whether this effect expects its input to be in the sRGB
// color space, ie. use the sRGB/Rec. 709 RGB primaries.
// (If not, it would typically come in as some slightly different
// set of RGB primaries; you would currently not get YCbCr
// or something similar).
//
// Again, most effects will want this, but you can set it to false
// if you process each channel independently, equally _and_
// in a linear fashion.
virtual bool needs_srgb_primaries() const { return true; }
// How this effect handles alpha, ie. what it outputs in its
// alpha channel. The choices are basically blank (alpha is always 1.0),
// premultiplied and postmultiplied.
//
// Premultiplied alpha is when the alpha value has been be multiplied
// into the three color components, so e.g. 100% red at 50% alpha
// would be (0.5, 0.0, 0.0, 0.5) instead of (1.0, 0.0, 0.0, 0.5)
// as it is stored in most image formats (postmultiplied alpha).
// The multiplication is taken to have happened in linear light.
// This is the most natural format for processing, and the default in
// most of Movit (just like linear light is).
//
// If you set INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA or
// INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK, all of your inputs
// (if any) are guaranteed to also be in premultiplied alpha.
// Otherwise, you can get postmultiplied or premultiplied alpha;
// you won't know. If you have multiple inputs, you will get the same
// (pre- or postmultiplied) for all inputs, although most likely,
// you will want to combine them in a premultiplied fashion anyway
// in that case.
enum AlphaHandling {
// Always outputs blank alpha (ie. alpha=1.0). Only appropriate
// for inputs that do not output an alpha channel.
// Blank alpha is special in that it can be treated as both
// pre- and postmultiplied.
OUTPUT_BLANK_ALPHA,
// Always outputs postmultiplied alpha. Only appropriate for inputs.
OUTPUT_POSTMULTIPLIED_ALPHA,
// Always outputs premultiplied alpha. As noted above,
// you will then also get all inputs in premultiplied alpha.
// If you set this, you should also set needs_linear_light().
INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA,
// Like INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA, but also guarantees
// that if you get blank alpha in, you also keep blank alpha out.
// This is a somewhat weaker guarantee than DONT_CARE_ALPHA_TYPE,
// but is still useful in many situations, and appropriate when
// e.g. you don't touch alpha at all.
//
// Does not make sense for inputs.
INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK,
// Keeps the type of alpha (premultiplied, postmultiplied, blank)
// unchanged from input to output. Usually appropriate if you
// process all color channels in a linear fashion, do not change
// alpha, and do not produce any new pixels thare have alpha != 1.0.
//
// Does not make sense for inputs.
DONT_CARE_ALPHA_TYPE,
};
virtual AlphaHandling alpha_handling() const { return INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA; }
// Whether this effect expects its input to come directly from
// a texture. If this is true, the framework will not chain the
// input from other effects, but will store the results of the
// chain to a temporary (RGBA fp16) texture and let this effect
// sample directly from that.
//
// There are two good reasons why you might want to set this:
//
// 1. You are sampling more than once from the input,
// in which case computing all the previous steps might
// be more expensive than going to a memory intermediate.
// 2. You rely on previous effects, possibly including gamma
// expansion, to happen pre-filtering instead of post-filtering.
// (This is only relevant if you actually need the filtering; if
// you sample 1:1 between pixels and texels, it makes no difference.)
//
// Note that in some cases, you might get post-filtered gamma expansion
// even when setting this option. More specifically, if you are the
// first effect in the chain, and the GPU is doing sRGB gamma
// expansion, it is undefined (from OpenGL's side) whether expansion
// happens pre- or post-filtering. For most uses, however,
// either will be fine.
virtual bool needs_texture_bounce() const { return false; }
// Whether this effect expects mipmaps or not. If you set this to
// true, you will be sampling with bilinear filtering; if not,
// you could be sampling with simple linear filtering and no mipmaps
// (although there is no guarantee; if a different effect in the chain
// needs mipmaps, you will also get them).
virtual bool needs_mipmaps() const { return false; }
// Whether this effect wants to output to a different size than
// its input(s) (see inform_input_size(), below). If you set this to
// true, the output will be bounced to a texture (similarly to if the
// next effect set needs_texture_bounce()).
virtual bool changes_output_size() const { return false; }
// Whether this effect is effectively sampling from a a single texture.
// If so, it will override needs_texture_bounce(); however, there are also
// two demands it needs to fulfill:
//
// 1. It needs to be an Input, ie. num_inputs() == 0.
// 2. It needs to allocate exactly one sampler in set_gl_state(),
// and allow dependent effects to change that sampler state.
virtual bool is_single_texture() 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)
// will _think_ your data is in. This is primarily useful if you are
// relying on getting OpenGL's bilinear resizing for free; otherwise,
// your virtual_width/virtual_height should be the same as width/height.
//
// Note that it is explicitly allowed to change width and height
// from frame to frame; EffectChain will reallocate textures as needed.
virtual void get_output_size(unsigned *width, unsigned *height,
unsigned *virtual_width, unsigned *virtual_height) const {
assert(false);
}
// Tells the effect the resolution of each of its input.
// This will be called every frame, and always before get_output_size(),
// so you can change your output size based on the input if so desired.
//
// Note that in some cases, an input might not have a single well-defined
// resolution (for instance if you fade between two inputs with
// different resolutions). In this case, you will get width=0 and height=0
// for that input. If you cannot handle that, you will need to set
// needs_texture_bounce() to true, which will force a render to a single
// given resolution before you get the input.
virtual void inform_input_size(unsigned input_num, unsigned width, unsigned height) {}
// 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; }
// Inform the effect that it has been just added to the EffectChain.
// The primary use for this is to store the ResourcePool uesd by
// the chain; for modifications to it, rewrite_graph() below
// is probably a better fit.
virtual void inform_added(EffectChain *chain) {}
// Let the effect rewrite the effect chain as it sees fit.
// Most effects won't need to do this, but this is very useful
// if you have an effect that consists of multiple sub-effects
// (for instance, two passes). The effect is given to its own
// pointer, and it can add new ones (by using add_node()
// and connect_node()) as it sees fit. This is called at
// EffectChain::finalize() time, when the entire graph is known,
// in the order that the effects were originally added.
//
// Note that if the effect wants to take itself entirely out
// of the chain, it must set “disabled” to true and then disconnect
// 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;
// Set all OpenGL state that this effect needs before rendering.
// The default implementation sets one uniform per registered parameter,
// but no other state.
//
// <sampler_num> is the first free texture sampler. If you want to use
// textures, you can bind a texture to GL_TEXTURE0 + <sampler_num>,
// and then increment the number (so that the next effect in the chain
// will use a different sampler).
virtual void set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num);
// If you set any special OpenGL state in set_gl_state(), you can clear it
// after rendering here. The default implementation does nothing.
virtual void clear_gl_state();
// Set a parameter; intended to be called from user code.
// Neither of these take ownership of the pointer.
virtual bool set_int(const std::string&, int value) MUST_CHECK_RESULT;
virtual bool set_float(const std::string &key, float value) MUST_CHECK_RESULT;
virtual bool set_vec2(const std::string &key, const float *values) MUST_CHECK_RESULT;
virtual bool set_vec3(const std::string &key, const float *values) MUST_CHECK_RESULT;
virtual bool set_vec4(const std::string &key, const float *values) MUST_CHECK_RESULT;
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).
//
// 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.
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);
private:
std::map<std::string, int *> params_int;
std::map<std::string, float *> params_float;
std::map<std::string, float *> params_vec2;
std::map<std::string, float *> params_vec3;
std::map<std::string, float *> params_vec4;
};
} // namespace movit
#endif // !defined(_MOVIT_EFFECT_H)
|