Convert a loop to range-based for.
[movit] / deinterlace_effect_test.cpp
index d2045eb..a509f8c 100644 (file)
@@ -6,6 +6,7 @@
 #include <epoxy/gl.h>
 
 #include <algorithm>
+#include <memory>
 
 #include "effect_chain.h"
 #include "gtest/gtest.h"
@@ -18,7 +19,17 @@ using namespace std;
 
 namespace movit {
 
-TEST(DeinterlaceTest, ConstantColor) {
+class DeinterlaceTest : public testing::TestWithParam<string> {
+protected:
+       DeinterlaceTest() : disabler(GetParam() == "fragment") {}
+       bool should_skip() { return disabler.should_skip(); }
+
+private:
+       DisableComputeShadersTemporarily disabler;
+};
+
+TEST_P(DeinterlaceTest, ConstantColor) {
+       if (should_skip()) return;
        float data[] = {
                0.3f, 0.3f,
                0.3f, 0.3f,
@@ -33,7 +44,7 @@ TEST(DeinterlaceTest, ConstantColor) {
                0.3f, 0.3f,
        };
        float out_data[12];
-       EffectChainTester tester(NULL, 2, 6);
+       EffectChainTester tester(nullptr, 2, 6);
        Effect *input1 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
        Effect *input2 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
        Effect *input3 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, 2, 3);
@@ -51,7 +62,8 @@ TEST(DeinterlaceTest, ConstantColor) {
 }
 
 // Also tests that top/bottom change works like expected.
-TEST(DeinterlaceTest, VerticalInterpolation) {
+TEST_P(DeinterlaceTest, VerticalInterpolation) {
+       if (should_skip()) return;
        const int width = 11;
        const int height = 2;
        float data[width * height] = {
@@ -79,7 +91,7 @@ TEST(DeinterlaceTest, VerticalInterpolation) {
        fill(neg_blowout_data, neg_blowout_data + width * height, -100.0f);
        fill(pos_blowout_data, pos_blowout_data + width * height,  100.0f);
 
-       EffectChainTester tester(NULL, width, height * 2);
+       EffectChainTester tester(nullptr, width, height * 2);
        Effect *input1 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
        Effect *input2 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
        Effect *input3 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
@@ -96,7 +108,8 @@ TEST(DeinterlaceTest, VerticalInterpolation) {
        expect_equal(expected_data_bottom, out_data, width, height * 2);
 }
 
-TEST(DeinterlaceTest, DiagonalInterpolation) {
+TEST_P(DeinterlaceTest, DiagonalInterpolation) {
+       if (should_skip()) return;
        const int width = 11;
        const int height = 3;
        float data[width * height] = {
@@ -131,7 +144,7 @@ TEST(DeinterlaceTest, DiagonalInterpolation) {
        fill(neg_blowout_data, neg_blowout_data + width * height, -100.0f);
        fill(pos_blowout_data, pos_blowout_data + width * height,  100.0f);
 
-       EffectChainTester tester(NULL, width, height * 2);
+       EffectChainTester tester(nullptr, width, height * 2);
        Effect *input1 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
        Effect *input2 = tester.add_input(neg_blowout_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
        Effect *input3 = tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
@@ -144,7 +157,8 @@ TEST(DeinterlaceTest, DiagonalInterpolation) {
        expect_equal(expected_data_top, out_data, width, height * 2);
 }
 
-TEST(DeinterlaceTest, FlickerBox) {
+TEST_P(DeinterlaceTest, FlickerBox) {
+       if (should_skip()) return;
        const int width = 4;
        const int height = 4;
        float white_data[width * height] = {
@@ -172,7 +186,7 @@ TEST(DeinterlaceTest, FlickerBox) {
        float out_data[width * height * 2];
 
        {
-               EffectChainTester tester(NULL, width, height * 2);
+               EffectChainTester tester(nullptr, width, height * 2);
                Effect *white_input = tester.add_input(white_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
                Effect *black_input = tester.add_input(black_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
                Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), white_input, black_input, white_input, black_input, white_input);
@@ -184,7 +198,7 @@ TEST(DeinterlaceTest, FlickerBox) {
        }
 
        {
-               EffectChainTester tester(NULL, width, height * 2);
+               EffectChainTester tester(nullptr, width, height * 2);
                Effect *white_input = tester.add_input(white_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
                Effect *black_input = tester.add_input(black_data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, height);
                Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), white_input, black_input, white_input, black_input, white_input);
@@ -196,47 +210,66 @@ TEST(DeinterlaceTest, FlickerBox) {
        }
 }
 
+INSTANTIATE_TEST_CASE_P(DeinterlaceTest,
+                        DeinterlaceTest,
+                        testing::Values("fragment", "compute"));
+
 #ifdef HAVE_BENCHMARK
-void BM_DeinterlaceEffect_Gray(benchmark::State &state)
+namespace {
+
+struct TestFormat {
+       MovitPixelFormat input_format;
+       GLenum output_format;
+       size_t bytes_per_pixel;
+};
+TestFormat gray_format = { FORMAT_GRAYSCALE, GL_RED, 1 };
+TestFormat bgra_format = { FORMAT_BGRA_PREMULTIPLIED_ALPHA, GL_BGRA, 4 };
+
+}  // namespace
+
+void BM_DeinterlaceEffect(benchmark::State &state, TestFormat format, bool spatial_interlacing_check, const std::string &shader_type)
 {
+       DisableComputeShadersTemporarily disabler(shader_type == "fragment");
+       if (disabler.should_skip(&state)) return;
+
        unsigned width = state.range(0), height = state.range(1);
        unsigned field_height = height / 2;
 
-       float *field1 = new float[width * field_height];
-       float *field2 = new float[width * field_height];
-       float *field3 = new float[width * field_height];
-       float *field4 = new float[width * field_height];
-       float *field5 = new float[width * field_height];
-       float *out_data = new float[width * height];
-
-       for (unsigned i = 0; i < width * field_height; ++i) {
-               field1[i] = rand();
-               field2[i] = rand();
-               field3[i] = rand();
-               field4[i] = rand();
-               field5[i] = rand();
+       unique_ptr<float[]> field1(new float[width * field_height * format.bytes_per_pixel]);
+       unique_ptr<float[]> field2(new float[width * field_height * format.bytes_per_pixel]);
+       unique_ptr<float[]> field3(new float[width * field_height * format.bytes_per_pixel]);
+       unique_ptr<float[]> field4(new float[width * field_height * format.bytes_per_pixel]);
+       unique_ptr<float[]> field5(new float[width * field_height * format.bytes_per_pixel]);
+       unique_ptr<float[]> out_data(new float[width * height * format.bytes_per_pixel]);
+
+       for (unsigned i = 0; i < width * field_height * format.bytes_per_pixel; ++i) {
+               field1[i] = rand() / (RAND_MAX + 1.0);
+               field2[i] = rand() / (RAND_MAX + 1.0);
+               field3[i] = rand() / (RAND_MAX + 1.0);
+               field4[i] = rand() / (RAND_MAX + 1.0);
+               field5[i] = rand() / (RAND_MAX + 1.0);
        }
 
-       EffectChainTester tester(NULL, width, height);
-       Effect *input1 = tester.add_input(field1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
-       Effect *input2 = tester.add_input(field2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
-       Effect *input3 = tester.add_input(field3, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
-       Effect *input4 = tester.add_input(field4, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
-       Effect *input5 = tester.add_input(field5, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+       EffectChainTester tester(nullptr, width, height);
+       Effect *input1 = tester.add_input(field1.get(), format.input_format, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+       Effect *input2 = tester.add_input(field2.get(), format.input_format, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+       Effect *input3 = tester.add_input(field3.get(), format.input_format, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+       Effect *input4 = tester.add_input(field4.get(), format.input_format, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
+       Effect *input5 = tester.add_input(field5.get(), format.input_format, COLORSPACE_sRGB, GAMMA_LINEAR, width, field_height);
        Effect *deinterlace_effect = tester.get_chain()->add_effect(new DeinterlaceEffect(), input1, input2, input3, input4, input5);
 
        ASSERT_TRUE(deinterlace_effect->set_int("current_field_position", 0));
+       ASSERT_TRUE(deinterlace_effect->set_int("enable_spatial_interlacing_check", spatial_interlacing_check));
 
-       tester.benchmark(state, out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
-
-       delete[] field1;
-       delete[] field2;
-       delete[] field3;
-       delete[] field4;
-       delete[] field5;
-       delete[] out_data;
+       tester.benchmark(state, out_data.get(), format.output_format, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
 }
-BENCHMARK(BM_DeinterlaceEffect_Gray)->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+BENCHMARK_CAPTURE(BM_DeinterlaceEffect, Gray, gray_format, true, "fragment")->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+BENCHMARK_CAPTURE(BM_DeinterlaceEffect, BGRA, bgra_format, true, "fragment")->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+BENCHMARK_CAPTURE(BM_DeinterlaceEffect, BGRANoSpatialCheck, bgra_format, false, "fragment")->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+BENCHMARK_CAPTURE(BM_DeinterlaceEffect, GrayCompute, gray_format, true, "compute")->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+BENCHMARK_CAPTURE(BM_DeinterlaceEffect, BGRACompute, bgra_format, true, "compute")->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+BENCHMARK_CAPTURE(BM_DeinterlaceEffect, BGRANoSpatialCheckCompute, bgra_format, false, "compute")->Args({720, 576})->Args({1280, 720})->Args({1920, 1080})->UseRealTime()->Unit(benchmark::kMicrosecond);
+
 #endif
 
 }  // namespace movit