Remove some unneeded conversions from ResampleEffect. Speeds up texture generation...
[movit] / padding_effect.cpp
1 #include <epoxy/gl.h>
2 #include <assert.h>
3
4 #include "effect_util.h"
5 #include "padding_effect.h"
6 #include "util.h"
7
8 using namespace std;
9
10 namespace movit {
11
12 PaddingEffect::PaddingEffect()
13         : border_color(0.0f, 0.0f, 0.0f, 0.0f),
14           output_width(1280),
15           output_height(720),
16           top(0),
17           left(0),
18           border_offset_top(0.0f),
19           border_offset_left(0.0f),
20           border_offset_bottom(0.0f),
21           border_offset_right(0.0f)
22 {
23         register_vec4("border_color", (float *)&border_color);
24         register_int("width", &output_width);
25         register_int("height", &output_height);
26         register_float("top", &top);
27         register_float("left", &left);
28         register_float("border_offset_top", &border_offset_top);
29         register_float("border_offset_left", &border_offset_left);
30         register_float("border_offset_bottom", &border_offset_bottom);
31         register_float("border_offset_right", &border_offset_right);
32         register_uniform_vec2("offset", uniform_offset);
33         register_uniform_vec2("scale", uniform_scale);
34         register_uniform_vec2("normalized_coords_to_texels", uniform_normalized_coords_to_texels);
35         register_uniform_vec2("offset_bottomleft", uniform_offset_bottomleft);
36         register_uniform_vec2("offset_topright", uniform_offset_topright);
37 }
38
39 string PaddingEffect::output_fragment_shader()
40 {
41         return read_file("padding_effect.frag");
42 }
43
44 void PaddingEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, unsigned *sampler_num)
45 {
46         Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
47
48         uniform_offset[0] = left / output_width;
49         uniform_offset[1] = (output_height - input_height - top) / output_height;
50
51         uniform_scale[0] = float(output_width) / input_width;
52         uniform_scale[1] = float(output_height) / input_height;
53
54         uniform_normalized_coords_to_texels[0] = float(input_width);
55         uniform_normalized_coords_to_texels[1] = float(input_height);
56
57         // Texels -0.5..0.5 should map to light level 0..1 (and then we
58         // clamp the rest).
59         uniform_offset_bottomleft[0] = 0.5f - border_offset_left;
60         uniform_offset_bottomleft[1] = 0.5f + border_offset_bottom;
61
62         // Texels size-0.5..size+0.5 should map to light level 1..0 (and then clamp).
63         uniform_offset_topright[0] = input_width + 0.5f + border_offset_right;
64         uniform_offset_topright[1] = input_height + 0.5f - border_offset_top;
65 }
66         
67 // We don't change the pixels of the image itself, so the only thing that 
68 // can make us less flexible is if the border color can be interpreted
69 // differently in different modes.
70
71 // 0.0 and 1.0 are interpreted the same, no matter the gamma ramp.
72 // Alpha is not affected by gamma per se, but the combination of
73 // premultiplied alpha and non-linear gamma curve does not make sense,
74 // so if could possibly be converting blank alpha to non-blank
75 // (ie., premultiplied), we need our output to be in linear light.
76 bool PaddingEffect::needs_linear_light() const
77 {
78         if ((border_color.r == 0.0 || border_color.r == 1.0) &&
79             (border_color.g == 0.0 || border_color.g == 1.0) &&
80             (border_color.b == 0.0 || border_color.b == 1.0) &&
81             border_color.a == 1.0) {
82                 return false;
83         }
84         return true;
85 }
86
87 // The white point is the same (D65) in all the color spaces we currently support,
88 // so any gray would be okay, but we don't really have a guarantee for that.
89 // Stay safe and say that only pure black and pure white is okay.
90 // Alpha is not affected by color space.
91 bool PaddingEffect::needs_srgb_primaries() const
92 {
93         if (border_color.r == 0.0 && border_color.g == 0.0 && border_color.b == 0.0) {
94                 return false;
95         }
96         if (border_color.r == 1.0 && border_color.g == 1.0 && border_color.b == 1.0) {
97                 return false;
98         }
99         return true;
100 }
101
102 Effect::AlphaHandling PaddingEffect::alpha_handling() const
103 {
104         // If the border color is solid, it doesn't matter if we're pre- or postmultiplied.
105         if (border_color.a == 1.0) {
106                 return DONT_CARE_ALPHA_TYPE;
107         }
108
109         // Otherwise, we're going to output our border color in premultiplied alpha,
110         // so the other pixels better be premultiplied as well.
111         // Note that for non-solid black (i.e. alpha < 1.0), we're equally fine with
112         // pre- and postmultiplied, but we are _not_ fine with blank being passed through,
113         // and we don't have a way to specify that.
114         return INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA;
115 }
116         
117 void PaddingEffect::get_output_size(unsigned *width, unsigned *height, unsigned *virtual_width, unsigned *virtual_height) const
118 {
119         *virtual_width = *width = output_width;
120         *virtual_height = *height = output_height;
121 }
122         
123 void PaddingEffect::inform_input_size(unsigned input_num, unsigned width, unsigned height)
124 {
125         assert(input_num == 0);
126         input_width = width;
127         input_height = height;
128 }
129
130 IntegralPaddingEffect::IntegralPaddingEffect() {}
131
132 bool IntegralPaddingEffect::set_int(const std::string &key, int value)
133 {
134         if (key == "top" || key == "left") {
135                 return PaddingEffect::set_float(key, value);
136         } else {
137                 return PaddingEffect::set_int(key, value);
138         }
139 }
140
141 bool IntegralPaddingEffect::set_float(const std::string &key, float value)
142 {
143         if (key == "top" || key == "left") {
144                 // These are removed as float parameters from this version.
145                 return false;
146         } else {
147                 return PaddingEffect::set_float(key, value);
148         }
149 }
150
151 }  // namespace movit