]> git.sesse.net Git - movit/blob - padding_effect.cpp
Prepare for better understanding of 10- and 12-bit Y'CbCr.
[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 }
33
34 string PaddingEffect::output_fragment_shader()
35 {
36         return read_file("padding_effect.frag");
37 }
38
39 void PaddingEffect::set_gl_state(GLuint glsl_program_num, const string &prefix, unsigned *sampler_num)
40 {
41         Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
42
43         float offset[2] = {
44                 left / output_width,
45                 (output_height - input_height - top) / output_height
46         };
47         set_uniform_vec2(glsl_program_num, prefix, "offset", offset);
48
49         float scale[2] = {
50                 float(output_width) / input_width,
51                 float(output_height) / input_height
52         };
53         set_uniform_vec2(glsl_program_num, prefix, "scale", scale);
54
55         float normalized_coords_to_texels[2] = {
56                 float(input_width), float(input_height)
57         };
58         set_uniform_vec2(glsl_program_num, prefix, "normalized_coords_to_texels", normalized_coords_to_texels);
59
60         // Texels -0.5..0.5 should map to light level 0..1 (and then we
61         // clamp the rest).
62         float offset_bottomleft[2] = {
63                 0.5f - border_offset_left, 0.5f + border_offset_bottom,
64         };
65
66         // Texels size-0.5..size+0.5 should map to light level 1..0 (and then clamp).
67         float offset_topright[2] = {
68                 input_width + 0.5f + border_offset_right, input_height + 0.5f - border_offset_top,
69         };
70
71         set_uniform_vec2(glsl_program_num, prefix, "offset_bottomleft", offset_bottomleft);
72         set_uniform_vec2(glsl_program_num, prefix, "offset_topright", offset_topright);
73 }
74         
75 // We don't change the pixels of the image itself, so the only thing that 
76 // can make us less flexible is if the border color can be interpreted
77 // differently in different modes.
78
79 // 0.0 and 1.0 are interpreted the same, no matter the gamma ramp.
80 // Alpha is not affected by gamma per se, but the combination of
81 // premultiplied alpha and non-linear gamma curve does not make sense,
82 // so if could possibly be converting blank alpha to non-blank
83 // (ie., premultiplied), we need our output to be in linear light.
84 bool PaddingEffect::needs_linear_light() const
85 {
86         if ((border_color.r == 0.0 || border_color.r == 1.0) &&
87             (border_color.g == 0.0 || border_color.g == 1.0) &&
88             (border_color.b == 0.0 || border_color.b == 1.0) &&
89             border_color.a == 1.0) {
90                 return false;
91         }
92         return true;
93 }
94
95 // The white point is the same (D65) in all the color spaces we currently support,
96 // so any gray would be okay, but we don't really have a guarantee for that.
97 // Stay safe and say that only pure black and pure white is okay.
98 // Alpha is not affected by color space.
99 bool PaddingEffect::needs_srgb_primaries() const
100 {
101         if (border_color.r == 0.0 && border_color.g == 0.0 && border_color.b == 0.0) {
102                 return false;
103         }
104         if (border_color.r == 1.0 && border_color.g == 1.0 && border_color.b == 1.0) {
105                 return false;
106         }
107         return true;
108 }
109
110 Effect::AlphaHandling PaddingEffect::alpha_handling() const
111 {
112         // If the border color is black, it doesn't matter if we're pre- or postmultiplied.
113         // Note that for non-solid black (i.e. alpha < 1.0), we're equally fine with
114         // pre- and postmultiplied, but later effects might change this status
115         // (consider e.g. blur), so setting DONT_CARE_ALPHA_TYPE is inappropriate,
116         // as it propagate blank alpha through this effect.
117         if (border_color.r == 0.0 && border_color.g == 0.0 && border_color.b == 0.0 && border_color.a == 1.0) {
118                 return DONT_CARE_ALPHA_TYPE;
119         }
120
121         // If the border color is solid, we preserve blank alpha, as we never output any
122         // new non-solid pixels.
123         if (border_color.a == 1.0) {
124                 return INPUT_PREMULTIPLIED_ALPHA_KEEP_BLANK;
125         }
126
127         // Otherwise, we're going to output our border color in premultiplied alpha,
128         // so the other pixels better be premultiplied as well.
129         return INPUT_AND_OUTPUT_PREMULTIPLIED_ALPHA;
130 }
131         
132 void PaddingEffect::get_output_size(unsigned *width, unsigned *height, unsigned *virtual_width, unsigned *virtual_height) const
133 {
134         *virtual_width = *width = output_width;
135         *virtual_height = *height = output_height;
136 }
137         
138 void PaddingEffect::inform_input_size(unsigned input_num, unsigned width, unsigned height)
139 {
140         assert(input_num == 0);
141         input_width = width;
142         input_height = height;
143 }
144
145 IntegralPaddingEffect::IntegralPaddingEffect() {}
146
147 bool IntegralPaddingEffect::set_int(const std::string &key, int value)
148 {
149         if (key == "top" || key == "left") {
150                 return PaddingEffect::set_float(key, value);
151         } else {
152                 return PaddingEffect::set_int(key, value);
153         }
154 }
155
156 bool IntegralPaddingEffect::set_float(const std::string &key, float value)
157 {
158         if (key == "top" || key == "left") {
159                 // These are removed as float parameters from this version.
160                 return false;
161         } else {
162                 return PaddingEffect::set_float(key, value);
163         }
164 }
165
166 }  // namespace movit