]> git.sesse.net Git - movit/blob - resample_effect_test.cpp
When a shader fails compilation, add some line numbers.
[movit] / resample_effect_test.cpp
1 // Unit tests for ResampleEffect.
2
3 #include <epoxy/gl.h>
4 #include <gtest/gtest.h>
5 #include <math.h>
6
7 #include <memory>
8
9 #include "effect_chain.h"
10 #include "flat_input.h"
11 #include "image_format.h"
12 #include "init.h"
13 #include "resample_effect.h"
14 #include "test_util.h"
15
16 using namespace std;
17
18 namespace movit {
19
20 namespace {
21
22 float sinc(float x)
23 {
24         return sin(M_PI * x) / (M_PI * x);
25 }
26
27 float lanczos(float x, float a)
28 {
29         if (fabs(x) >= a) {
30                 return 0.0f;
31         } else {
32                 return sinc(x) * sinc(x / a);
33         }
34 }
35
36 }  // namespace
37
38 TEST(ResampleEffectTest, IdentityTransformDoesNothing) {
39         const int size = 4;
40
41         float data[size * size] = {
42                 0.0, 1.0, 0.0, 1.0,
43                 0.0, 1.0, 1.0, 0.0,
44                 0.0, 0.5, 1.0, 0.5,
45                 0.0, 0.0, 0.0, 0.0,
46         };
47         float out_data[size * size];
48
49         EffectChainTester tester(data, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
50         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
51         ASSERT_TRUE(resample_effect->set_int("width", 4));
52         ASSERT_TRUE(resample_effect->set_int("height", 4));
53         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
54
55         expect_equal(data, out_data, size, size);
56 }
57
58 TEST(ResampleEffectTest, UpscaleByTwoGetsCorrectPixelCenters) {
59         const int size = 5;
60
61         float data[size * size] = {
62                 0.0, 0.0, 0.0, 0.0, 0.0,
63                 0.0, 0.0, 0.0, 0.0, 0.0,
64                 0.0, 0.0, 1.0, 0.0, 0.0,
65                 0.0, 0.0, 0.0, 0.0, 0.0,
66                 0.0, 0.0, 0.0, 0.0, 0.0,
67         };
68         float expected_data[size * size * 4], out_data[size * size * 4];
69
70         for (int y = 0; y < size * 2; ++y) {
71                 for (int x = 0; x < size * 2; ++x) {
72                         float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
73                         weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
74                         expected_data[y * (size * 2) + x] = weight;
75                 }
76         }
77
78         EffectChainTester tester(nullptr, size * 2, size * 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
79
80         ImageFormat format;
81         format.color_space = COLORSPACE_sRGB;
82         format.gamma_curve = GAMMA_LINEAR;
83
84         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
85         input->set_pixel_data(data);
86         tester.get_chain()->add_input(input);
87
88         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
89         ASSERT_TRUE(resample_effect->set_int("width", size * 2));
90         ASSERT_TRUE(resample_effect->set_int("height", size * 2));
91         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
92
93         expect_equal(expected_data, out_data, size * 2, size * 2);
94 }
95
96 TEST(ResampleEffectTest, DownscaleByTwoGetsCorrectPixelCenters) {
97         const int size = 5;
98
99         // This isn't a perfect dot, since the Lanczos filter has a slight
100         // sharpening effect; the most important thing is that we have kept
101         // the texel center right (everything is nicely symmetric).
102         // The approximate magnitudes have been checked against ImageMagick.
103         float expected_data[size * size] = {
104                  0.0045, -0.0067, -0.0599, -0.0067,  0.0045,
105                 -0.0067,  0.0100,  0.0892,  0.0100, -0.0067,
106                 -0.0599,  0.0890,  0.7925,  0.0892, -0.0599,
107                 -0.0067,  0.0100,  0.0890,  0.0100, -0.0067,
108                  0.0045, -0.0067, -0.0599, -0.0067,  0.0045,
109         };
110         float data[size * size * 4], out_data[size * size];
111
112         for (int y = 0; y < size * 2; ++y) {
113                 for (int x = 0; x < size * 2; ++x) {
114                         float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
115                         weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
116                         data[y * (size * 2) + x] = weight;
117                 }
118         }
119
120         EffectChainTester tester(nullptr, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
121
122         ImageFormat format;
123         format.color_space = COLORSPACE_sRGB;
124         format.gamma_curve = GAMMA_LINEAR;
125
126         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size * 2, size * 2);
127         input->set_pixel_data(data);
128         tester.get_chain()->add_input(input);
129
130         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
131         ASSERT_TRUE(resample_effect->set_int("width", size));
132         ASSERT_TRUE(resample_effect->set_int("height", size));
133         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
134
135         expect_equal(expected_data, out_data, size, size);
136 }
137
138 TEST(ResampleEffectTest, UpscaleByThreeGetsCorrectPixelCenters) {
139         const int size = 5;
140
141         float data[size * size] = {
142                 0.0, 0.0, 0.0, 0.0, 0.0,
143                 0.0, 0.0, 0.0, 0.0, 0.0,
144                 0.0, 0.0, 1.0, 0.0, 0.0,
145                 0.0, 0.0, 0.0, 0.0, 0.0,
146                 0.0, 0.0, 0.0, 0.0, 0.0,
147         };
148         float out_data[size * size * 9];
149
150         EffectChainTester tester(nullptr, size * 3, size * 3, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
151
152         ImageFormat format;
153         format.color_space = COLORSPACE_sRGB;
154         format.gamma_curve = GAMMA_LINEAR;
155
156         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
157         input->set_pixel_data(data);
158         tester.get_chain()->add_input(input);
159
160         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
161         ASSERT_TRUE(resample_effect->set_int("width", size * 3));
162         ASSERT_TRUE(resample_effect->set_int("height", size * 3));
163         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
164
165         // We only bother checking that the middle pixel is still correct,
166         // and that symmetry holds.
167         EXPECT_FLOAT_EQ(1.0, out_data[7 * (size * 3) + 7]);
168         for (unsigned y = 0; y < size * 3; ++y) {
169                 for (unsigned x = 0; x < size * 3; ++x) {
170                         EXPECT_NEAR(out_data[y * (size * 3) + x], out_data[(size * 3 - y - 1) * (size * 3) + x], 1e-6);
171                         EXPECT_NEAR(out_data[y * (size * 3) + x], out_data[y * (size * 3) + (size * 3 - x - 1)], 1e-6);
172                 }
173         }
174 }
175
176 TEST(ResampleEffectTest, HeavyResampleGetsSumRight) {
177         // Do only one resample pass, more specifically the last one, which goes to
178         // our fp32 output. This allows us to analyze the precision without intermediate
179         // fp16 rounding.
180         const int swidth = 1, sheight = 1280;
181         const int dwidth = 1, dheight = 64;
182
183         float data[swidth * sheight], out_data[dwidth * dheight], expected_data[dwidth * dheight];
184         for (int y = 0; y < sheight; ++y) {
185                 for (int x = 0; x < swidth; ++x) {
186                         data[y * swidth + x] = 1.0f;
187                 }
188         }
189         for (int y = 0; y < dheight; ++y) {
190                 for (int x = 0; x < dwidth; ++x) {
191                         expected_data[y * dwidth + x] = 1.0f;
192                 }
193         }
194
195         EffectChainTester tester(nullptr, dwidth, dheight, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, GL_RGBA32F);
196
197         ImageFormat format;
198         format.color_space = COLORSPACE_sRGB;
199         format.gamma_curve = GAMMA_LINEAR;
200
201         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, swidth, sheight);
202         input->set_pixel_data(data);
203
204         tester.get_chain()->add_input(input);
205         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
206         ASSERT_TRUE(resample_effect->set_int("width", dwidth));
207         ASSERT_TRUE(resample_effect->set_int("height", dheight));
208         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
209
210         // Require that we are within 10-bit accuracy. Note that this limit is for
211         // one pass only, but the limit is tight enough that it should be good enough
212         // for 10-bit accuracy even after two passes.
213         expect_equal(expected_data, out_data, dwidth, dheight, 0.12 / 1023.0);
214 }
215
216 TEST(ResampleEffectTest, ReadWholePixelFromLeft) {
217         const int size = 5;
218
219         float data[size * size] = {
220                 0.0, 0.0, 0.0, 0.0, 0.0,
221                 0.0, 0.0, 0.0, 0.0, 0.0,
222                 0.0, 0.0, 1.0, 0.0, 0.0,
223                 0.0, 0.0, 0.0, 0.0, 0.0,
224                 0.0, 0.0, 0.0, 0.0, 0.0,
225         };
226         float expected_data[size * size] = {
227                 0.0, 0.0, 0.0, 0.0, 0.0,
228                 0.0, 0.0, 0.0, 0.0, 0.0,
229                 0.0, 1.0, 0.0, 0.0, 0.0,
230                 0.0, 0.0, 0.0, 0.0, 0.0,
231                 0.0, 0.0, 0.0, 0.0, 0.0,
232         };
233         float out_data[size * size];
234
235         EffectChainTester tester(data, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
236         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
237         ASSERT_TRUE(resample_effect->set_int("width", size));
238         ASSERT_TRUE(resample_effect->set_int("height", size));
239         ASSERT_TRUE(resample_effect->set_float("left", 1.0f));
240         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
241
242         expect_equal(expected_data, out_data, size, size);
243 }
244
245 TEST(ResampleEffectTest, ReadQuarterPixelFromLeft) {
246         const int size = 5;
247
248         float data[size * size] = {
249                 0.0, 0.0, 0.0, 0.0, 0.0,
250                 0.0, 0.0, 0.0, 0.0, 0.0,
251                 0.0, 0.0, 1.0, 0.0, 0.0,
252                 0.0, 0.0, 0.0, 0.0, 0.0,
253                 0.0, 0.0, 0.0, 0.0, 0.0,
254         };
255
256         float expected_data[size * size] = {
257                 0.0, 0.0, 0.0, 0.0, 0.0,
258                 0.0, 0.0, 0.0, 0.0, 0.0,
259
260                 // sin(x*pi)/(x*pi) * sin(x*pi/3)/(x*pi/3) for
261                 // x = -1.75, -0.75, 0.25, 1.25, 2.25.
262                 // Note that the weight is mostly on the left side.
263                 -0.06779, 0.27019, 0.89007, -0.13287, 0.03002,
264
265                 0.0, 0.0, 0.0, 0.0, 0.0,
266                 0.0, 0.0, 0.0, 0.0, 0.0,
267         };
268         float out_data[size * size];
269
270         EffectChainTester tester(data, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
271         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
272         ASSERT_TRUE(resample_effect->set_int("width", size));
273         ASSERT_TRUE(resample_effect->set_int("height", size));
274         ASSERT_TRUE(resample_effect->set_float("left", 0.25f));
275         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
276
277         expect_equal(expected_data, out_data, size, size);
278 }
279
280 TEST(ResampleEffectTest, ReadQuarterPixelFromTop) {
281         const int width = 3;
282         const int height = 5;
283
284         float data[width * height] = {
285                 0.0, 0.0, 0.0,
286                 0.0, 0.0, 0.0,
287                 1.0, 0.0, 0.0,
288                 0.0, 0.0, 0.0,
289                 0.0, 0.0, 0.0,
290         };
291
292         // See ReadQuarterPixelFromLeft for explanation of the data.
293         float expected_data[width * height] = {
294                 -0.06779, 0.0, 0.0,
295                  0.27019, 0.0, 0.0,
296                  0.89007, 0.0, 0.0,
297                 -0.13287, 0.0, 0.0,
298                  0.03002, 0.0, 0.0,
299         };
300         float out_data[width * height];
301
302         EffectChainTester tester(data, width, height, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
303         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
304         ASSERT_TRUE(resample_effect->set_int("width", width));
305         ASSERT_TRUE(resample_effect->set_int("height", height));
306         ASSERT_TRUE(resample_effect->set_float("top", 0.25f));
307         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
308
309         expect_equal(expected_data, out_data, width, height);
310 }
311
312 TEST(ResampleEffectTest, ReadHalfPixelFromLeftAndScale) {
313         const int src_width = 4;
314         const int dst_width = 8;
315
316         float data[src_width * 1] = {
317                 1.0, 2.0, 3.0, 4.0,
318         };
319         float expected_data[dst_width * 1] = {
320                 // Empirical; the real test is that we are the same for 0.499 and 0.501.
321                 1.1553, 1.7158, 2.2500, 2.7461, 3.2812, 3.8418, 4.0703, 4.0508
322         };
323         float out_data[dst_width * 1];
324
325         EffectChainTester tester(nullptr, dst_width, 1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
326
327         ImageFormat format;
328         format.color_space = COLORSPACE_sRGB;
329         format.gamma_curve = GAMMA_LINEAR;
330
331         FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, src_width, 1);
332         input->set_pixel_data(data);
333         tester.get_chain()->add_input(input);
334
335         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
336         ASSERT_TRUE(resample_effect->set_int("width", dst_width));
337         ASSERT_TRUE(resample_effect->set_int("height", 1));
338
339         // Check that we are (almost) the same no matter the rounding.
340         ASSERT_TRUE(resample_effect->set_float("left", 0.499f));
341         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
342         expect_equal(expected_data, out_data, dst_width, 1, 1.5f / 255.0f, 0.4f / 255.0f);
343
344         ASSERT_TRUE(resample_effect->set_float("left", 0.501f));
345         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
346         expect_equal(expected_data, out_data, dst_width, 1, 1.5f / 255.0f, 0.4f / 255.0f);
347 }
348
349 TEST(ResampleEffectTest, Zoom) {
350         const int width = 5;
351         const int height = 3;
352
353         float data[width * height] = {
354                 0.0, 0.0, 0.0, 0.0, 0.0,
355                 0.2, 0.4, 0.6, 0.4, 0.2,
356                 0.0, 0.0, 0.0, 0.0, 0.0,
357         };
358         float expected_data[width * height] = {
359                 0.0, 0.0,    0.0, 0.0,    0.0,
360                 0.4, 0.5396, 0.6, 0.5396, 0.4,
361                 0.0, 0.0,    0.0, 0.0,    0.0,
362         };
363         float out_data[width * height];
364
365         EffectChainTester tester(data, width, height, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
366         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
367         ASSERT_TRUE(resample_effect->set_int("width", width));
368         ASSERT_TRUE(resample_effect->set_int("height", height));
369         ASSERT_TRUE(resample_effect->set_float("zoom_x", 2.0f));
370         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
371
372         expect_equal(expected_data, out_data, width, height);
373 }
374
375 TEST(ResampleEffectTest, VerticalZoomFromTop) {
376         const int width = 5;
377         const int height = 5;
378
379         float data[width * height] = {
380                 0.2, 0.4, 0.6, 0.4, 0.2,
381                 0.0, 0.0, 0.0, 0.0, 0.0,
382                 0.0, 0.0, 0.0, 0.0, 0.0,
383                 0.0, 0.0, 0.0, 0.0, 0.0,
384                 0.0, 0.0, 0.0, 0.0, 0.0,
385         };
386
387         // Largely empirical data; the main point is that the top line
388         // is unchanged, since that's our zooming point.
389         float expected_data[width * height] = {
390                  0.2000,  0.4000,  0.6000,  0.4000,  0.2000,
391                  0.1389,  0.2778,  0.4167,  0.2778,  0.1389,
392                  0.0600,  0.1199,  0.1798,  0.1199,  0.0600,
393                  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,
394                 -0.0229, -0.0459, -0.0688, -0.0459, -0.0229,
395         };
396         float out_data[width * height];
397
398         EffectChainTester tester(data, width, height, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
399         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
400         ASSERT_TRUE(resample_effect->set_int("width", width));
401         ASSERT_TRUE(resample_effect->set_int("height", height));
402         ASSERT_TRUE(resample_effect->set_float("zoom_y", 3.0f));
403         ASSERT_TRUE(resample_effect->set_float("zoom_center_y", 0.5f / height));
404         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
405
406         expect_equal(expected_data, out_data, width, height);
407 }
408
409 TEST(ResampleEffectTest, Precision) {
410         const int size = 1920;  // Difficult non-power-of-two size.
411         const int offset = 5;
412
413         // Deliberately put the data of interest very close to the right,
414         // where texture coordinates are farther from 0 and thus less precise.
415         float data[size * 2] = {0};
416         data[size - offset] = 1.0f;
417         float expected_data[size * 2] = {0};
418         for (int x = 0; x < size * 2; ++x) {
419                 expected_data[x] = lanczos((x - (size - 2 * offset + 1) + 0.5f) * 0.5f, 3.0f);
420         }
421         float out_data[size * 2];
422
423         EffectChainTester tester(data, size * 2, 1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
424         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
425         ASSERT_TRUE(resample_effect->set_int("width", size * 2));
426         ASSERT_TRUE(resample_effect->set_int("height", 1));
427         ASSERT_TRUE(resample_effect->set_float("zoom_x", 2.0f));
428         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
429
430         expect_equal(expected_data, out_data, size, 1);
431 }
432
433 #ifdef HAVE_BENCHMARK
434 template<class T>
435 void BM_ResampleEffect(benchmark::State &state, GammaCurve gamma_curve, GLenum output_format, const std::string &shader_type)
436 {
437         DisableComputeShadersTemporarily disabler(shader_type == "fragment");
438         if (disabler.should_skip(&state)) return;
439
440         unsigned in_width = state.range(0), in_height = state.range(1);
441         unsigned out_width = state.range(2), out_height = state.range(3);
442
443         unique_ptr<T[]> data(new T[in_width * in_height * 4]);
444         unique_ptr<T[]> out_data(new T[out_width * out_height * 4]);
445
446         for (unsigned i = 0; i < in_width * in_height * 4; ++i) {
447                 data[i] = rand();
448         }
449
450         EffectChainTester tester(nullptr, out_width, out_height, FORMAT_BGRA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, gamma_curve, output_format);
451         tester.add_input(data.get(), FORMAT_BGRA_POSTMULTIPLIED_ALPHA, COLORSPACE_sRGB, gamma_curve, in_width, in_height);
452         Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
453
454         ASSERT_TRUE(resample_effect->set_int("width", out_width));
455         ASSERT_TRUE(resample_effect->set_int("height", out_height));
456
457         tester.benchmark(state, out_data.get(), GL_BGRA, COLORSPACE_sRGB, gamma_curve, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
458 }
459
460 void BM_ResampleEffectFloat(benchmark::State &state, GammaCurve gamma_curve, const std::string &shader_type)
461 {
462         BM_ResampleEffect<float>(state, gamma_curve, GL_RGBA16F, shader_type);
463 }
464
465 void BM_ResampleEffectInt8(benchmark::State &state, GammaCurve gamma_curve, const std::string &shader_type)
466 {
467         BM_ResampleEffect<uint8_t>(state, gamma_curve, GL_RGBA8, shader_type);
468 }
469
470 BENCHMARK_CAPTURE(BM_ResampleEffectInt8, Int8Upscale, GAMMA_REC_709, "fragment")->Args({640, 360, 1280, 720})->Args({320, 180, 1280, 720})->Args({321, 181, 1280, 720})->UseRealTime()->Unit(benchmark::kMicrosecond);
471 BENCHMARK_CAPTURE(BM_ResampleEffectFloat, Float32Upscale, GAMMA_LINEAR, "fragment")->Args({640, 360, 1280, 720})->Args({320, 180, 1280, 720})->Args({321, 181, 1280, 720})->UseRealTime()->Unit(benchmark::kMicrosecond);
472 BENCHMARK_CAPTURE(BM_ResampleEffectInt8, Int8Downscale, GAMMA_REC_709, "fragment")->Args({1280, 720, 640, 360})->Args({1280, 720, 320, 180})->Args({1280, 720, 321, 181})->UseRealTime()->Unit(benchmark::kMicrosecond);
473 BENCHMARK_CAPTURE(BM_ResampleEffectFloat, Float32Downscale, GAMMA_LINEAR, "fragment")->Args({1280, 720, 640, 360})->Args({1280, 720, 320, 180})->Args({1280, 720, 321, 181})->UseRealTime()->Unit(benchmark::kMicrosecond);
474
475 void BM_ComputeScalingWeights(benchmark::State &state)
476 {
477         constexpr unsigned src_size = 1280;
478         constexpr unsigned dst_size = 35;
479         int old_precision = movit_texel_subpixel_precision;
480         movit_texel_subpixel_precision = 64;  // To get consistent results across GPUs; this is a CPU test.
481
482         // One iteration warmup to make sure the Lanczos table is computed.
483         calculate_scaling_weights(src_size, dst_size, 0.999f, 0.0f);
484
485         for (auto _ : state) {
486                 ScalingWeights weights = calculate_scaling_weights(src_size, dst_size, 0.999f, 0.0f);
487         }
488
489         movit_texel_subpixel_precision = old_precision;
490 }
491 BENCHMARK(BM_ComputeScalingWeights)->Unit(benchmark::kMicrosecond);
492
493 #endif
494
495 }  // namespace movit