Emulate glReadPixels of GL_ALPHA.
[movit] / mix_effect_test.cpp
1 // Unit tests for MixEffect.
2
3 #include <epoxy/gl.h>
4
5 #include "effect_chain.h"
6 #include "gtest/gtest.h"
7 #include "image_format.h"
8 #include "input.h"
9 #include "mix_effect.h"
10 #include "test_util.h"
11
12 namespace movit {
13
14 TEST(MixEffectTest, FiftyFiftyMix) {
15         float data_a[] = {
16                 0.0f, 0.25f,
17                 0.75f, 1.0f,
18         };
19         float data_b[] = {
20                 1.0f, 0.5f,
21                 0.75f, 0.6f,
22         };
23         float expected_data[] = {
24                 0.5f, 0.375f,
25                 0.75f, 0.8f,
26         };
27         float out_data[4];
28         EffectChainTester tester(data_a, 2, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
29         Effect *input1 = tester.get_chain()->last_added_effect();
30         Effect *input2 = tester.add_input(data_b, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
31
32         Effect *mix_effect = tester.get_chain()->add_effect(new MixEffect(), input1, input2);
33         ASSERT_TRUE(mix_effect->set_float("strength_first", 0.5f));
34         ASSERT_TRUE(mix_effect->set_float("strength_second", 0.5f));
35         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
36
37         expect_equal(expected_data, out_data, 2, 2);
38 }
39
40 TEST(MixEffectTest, OnlyA) {
41         float data_a[] = {
42                 0.0f, 0.25f,
43                 0.75f, 1.0f,
44         };
45         float data_b[] = {
46                 1.0f, 0.5f,
47                 0.75f, 0.6f,
48         };
49         float out_data[4];
50         EffectChainTester tester(data_a, 2, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
51         Effect *input1 = tester.get_chain()->last_added_effect();
52         Effect *input2 = tester.add_input(data_b, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
53
54         Effect *mix_effect = tester.get_chain()->add_effect(new MixEffect(), input1, input2);
55         ASSERT_TRUE(mix_effect->set_float("strength_first", 1.0f));
56         ASSERT_TRUE(mix_effect->set_float("strength_second", 0.0f));
57         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
58
59         expect_equal(data_a, out_data, 2, 2);
60 }
61
62 TEST(MixEffectTest, DoesNotSumToOne) {
63         float data_a[] = {
64                 1.0f, 0.5f, 0.75f, 0.333f,
65         };
66         float data_b[] = {
67                 1.0f, 0.25f, 0.15f, 0.333f,
68         };
69
70         // The fact that the RGB values don't sum but get averaged here might
71         // actually be a surprising result, but when you think of it,
72         // it does make physical sense.
73         float expected_data[] = {
74                 1.0f, 0.375f, 0.45f, 0.666f,
75         };
76
77         float out_data[4];
78         EffectChainTester tester(data_a, 1, 1, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
79         Effect *input1 = tester.get_chain()->last_added_effect();
80         Effect *input2 = tester.add_input(data_b, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
81
82         Effect *mix_effect = tester.get_chain()->add_effect(new MixEffect(), input1, input2);
83         ASSERT_TRUE(mix_effect->set_float("strength_first", 1.0f));
84         ASSERT_TRUE(mix_effect->set_float("strength_second", 1.0f));
85         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
86
87         expect_equal(expected_data, out_data, 4, 1);
88 }
89
90 TEST(MixEffectTest, AdditiveBlendingWorksForBothTotallyOpaqueAndPartiallyTranslucent) {
91         float data_a[] = {
92                 0.0f, 0.5f, 0.75f, 1.0f,
93                 1.0f, 1.0f, 1.0f, 0.2f,
94         };
95         float data_b[] = {
96                 1.0f, 0.25f, 0.15f, 1.0f,
97                 1.0f, 1.0f, 1.0f, 0.5f,
98         };
99
100         float expected_data[] = {
101                 1.0f, 0.75f, 0.9f, 1.0f,
102                 1.0f, 1.0f, 1.0f, 0.7f,
103         };
104
105         float out_data[4];
106         EffectChainTester tester(data_a, 1, 2, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
107         Effect *input1 = tester.get_chain()->last_added_effect();
108         Effect *input2 = tester.add_input(data_b, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, GAMMA_LINEAR);
109
110         Effect *mix_effect = tester.get_chain()->add_effect(new MixEffect(), input1, input2);
111         ASSERT_TRUE(mix_effect->set_float("strength_first", 1.0f));
112         ASSERT_TRUE(mix_effect->set_float("strength_second", 1.0f));
113         tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_LINEAR);
114
115         expect_equal(expected_data, out_data, 4, 2);
116 }
117
118 TEST(MixEffectTest, MixesLinearlyDespitesRGBInputsAndOutputs) {
119         float data_a[] = {
120                 0.0f, 0.25f,
121                 0.75f, 1.0f,
122         };
123         float data_b[] = {
124                 0.0f, 0.0f,
125                 0.0f, 0.0f,
126         };
127         float expected_data[] = {  // sRGB(0.5 * inv_sRGB(a)).
128                 0.00000f, 0.17349f,
129                 0.54807f, 0.73536f,
130         };
131         float out_data[4];
132         EffectChainTester tester(data_a, 2, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
133         Effect *input1 = tester.get_chain()->last_added_effect();
134         Effect *input2 = tester.add_input(data_b, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_sRGB);
135
136         Effect *mix_effect = tester.get_chain()->add_effect(new MixEffect(), input1, input2);
137         ASSERT_TRUE(mix_effect->set_float("strength_first", 0.5f));
138         ASSERT_TRUE(mix_effect->set_float("strength_second", 0.5f));
139         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_sRGB);
140
141         expect_equal(expected_data, out_data, 2, 2);
142 }
143
144 }  // namespace movit