Release Movit 1.3.2. (From a branch, since I do not want to break ABI compatibility...
[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 black, it doesn't matter if we're pre- or postmultiplied.
105         // Note that for non-solid black (i.e. alpha < 1.0), we're equally fine with
106         // pre- and postmultiplied, but later effects might change this status
107         // (consider e.g. blur), so setting DONT_CARE_ALPHA_TYPE is inappropriate,
108         // as it propagate blank alpha through this effect.
109         if (border_color.r == 0.0 && border_color.g == 0.0 && border_color.b == 0.0 && border_color.a == 1.0) {
110                 return DONT_CARE_ALPHA_TYPE;
111         }
112
113         // If the border color is solid, we preserve blank alpha, as we never output any
114         // new non-solid pixels.
115         if (border_color.a == 1.0) {
116                 return INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK;
117         }
118
119         // Otherwise, we're going to output our border color in premultiplied alpha,
120         // so the other pixels better be premultiplied as well.
121         return INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA;
122 }
123         
124 void PaddingEffect::get_output_size(unsigned *width, unsigned *height, unsigned *virtual_width, unsigned *virtual_height) const
125 {
126         *virtual_width = *width = output_width;
127         *virtual_height = *height = output_height;
128 }
129         
130 void PaddingEffect::inform_input_size(unsigned input_num, unsigned width, unsigned height)
131 {
132         assert(input_num == 0);
133         input_width = width;
134         input_height = height;
135 }
136
137 IntegralPaddingEffect::IntegralPaddingEffect() {}
138
139 bool IntegralPaddingEffect::set_int(const std::string &key, int value)
140 {
141         if (key == "top" || key == "left") {
142                 return PaddingEffect::set_float(key, value);
143         } else {
144                 return PaddingEffect::set_int(key, value);
145         }
146 }
147
148 bool IntegralPaddingEffect::set_float(const std::string &key, float value)
149 {
150         if (key == "top" || key == "left") {
151                 // These are removed as float parameters from this version.
152                 return false;
153         } else {
154                 return PaddingEffect::set_float(key, value);
155         }
156 }
157
158 }  // namespace movit