Chromium Code Reviews| Index: third_party/WebKit/Source/platform/image-encoders/JPEGImageEncoderTest.cpp |
| diff --git a/third_party/WebKit/Source/platform/image-encoders/JPEGImageEncoderTest.cpp b/third_party/WebKit/Source/platform/image-encoders/JPEGImageEncoderTest.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..056e38d2f5acb960c561def9089ae55f7c7521c5 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/platform/image-encoders/JPEGImageEncoderTest.cpp |
| @@ -0,0 +1,234 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/timer/elapsed_timer.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +// TODO(cavalcantii): use regular macro, see https://crbug.com/673067. |
| +#ifdef __ARM_NEON__ |
| +#include "platform/image-encoders/RGBAtoRGB.h" |
| +#endif |
| + |
| +namespace blink { |
| + |
| +static const size_t channelsRGBA = 4; |
| +static const size_t channelsRGB = 3; |
| + |
| +class RGBAtoRGBTest : public ::testing::Test { |
| + public: |
| + RGBAtoRGBTest() {} |
| +}; |
| + |
| +TEST_F(RGBAtoRGBTest, testEmpty) { |
| + EXPECT_TRUE(true); |
| +} |
| + |
| +inline size_t calculateRGBAPixels(size_t inputBufferSize) { |
| + size_t pixels = inputBufferSize / channelsRGBA; |
| + return pixels; |
| +} |
| + |
| +inline size_t calculateRGBOutputSize(size_t inputBufferSize) { |
| + size_t pixels = calculateRGBAPixels(inputBufferSize); |
| + pixels *= channelsRGB; |
| + return pixels; |
| +} |
| + |
| +#ifdef __ARM_NEON__ |
|
msarett
2016/12/18 18:48:37
Is there a reason to only test on Arm NEON? This
|
| +TEST_F(RGBAtoRGBTest, testOpaqueCaseEven8pixels) { |
| + unsigned char canvas[] = {255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, |
| + 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 255, |
| + 0, 255, 0, 255, 0, 255, 0, 255, 0, 255}; |
| + |
| + unsigned char expected[] = {255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 0, |
| + 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0}; |
| + |
| + size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| + size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| + unsigned char output[rgbSize]; |
| + memset(output, 0, rgbSize); |
| + |
| + blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| + |
| + EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| +} |
| + |
| +TEST_F(RGBAtoRGBTest, testCaseEven16pixels) { |
| + unsigned char canvas[] = { |
| + 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, |
| + 0, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, |
| + 0, 255, 0, 255, 0, 255, 0, 0, 255, 128, 0, 0, 255, |
| + 128, 0, 0, 255, 128, 0, 0, 255, 128, 128, 128, 128, 128, |
| + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; |
| + |
| + size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| + size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| + unsigned char output[rgbSize]; |
| + unsigned char expected[rgbSize]; |
| + memset(output, 0, rgbSize); |
| + memset(expected, 0, rgbSize); |
| + |
| + blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| + blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| + |
| + EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| +} |
| + |
| +TEST_F(RGBAtoRGBTest, testCaseOdd17pixels) { |
| + unsigned char canvas[] = { |
| + 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, |
| + 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, |
| + 0, 255, 0, 255, 0, 0, 255, 128, 0, 0, 255, 128, 0, 0, |
| + 255, 128, 0, 0, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| + 128, 128, 128, 128, 128, 128, 128, 128, 10, 10, 10, 100}; |
| + |
| + size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| + size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| + unsigned char output[rgbSize]; |
| + unsigned char expected[rgbSize]; |
| + memset(output, 0, rgbSize); |
| + memset(expected, 0, rgbSize); |
| + |
| + blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| + blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| + |
| + EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| +} |
| + |
| +TEST_F(RGBAtoRGBTest, testCaseEven32pixels) { |
| + unsigned char canvas[] = { |
| + 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, |
| + 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, |
| + 0, 255, 0, 0, 255, 128, 0, 0, 255, 128, 0, 0, 255, 128, 0, |
| + 0, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| + 128, 128, 128, 128, 128, 128, 128, 255, 128, 128, 128, 255, 128, 128, 128, |
| + 255, 128, 128, 128, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, |
| + 0, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, |
| + 255, 0, 255, 0, 255, 0, 255, 0, 0, 255, 128, 0, 0, 255, 128, |
| + 0, 0, 255, 128, 0, 0, 255, 128}; |
| + |
| + size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| + size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| + unsigned char output[rgbSize]; |
| + unsigned char expected[rgbSize]; |
| + memset(output, 0, rgbSize); |
| + memset(expected, 0, rgbSize); |
| + |
| + blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| + blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| + |
| + EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| +} |
| + |
| +static base::TimeDelta testNpixels(bool fastPath = true, |
| + const size_t width = 1024, |
| + const size_t height = 1024, |
| + bool setAlpha = true) { |
| + size_t pixels = width * height; |
| + size_t canvasLen = channelsRGBA * width * height; |
| + size_t outputLen = channelsRGB * width * height; |
| + unsigned char* canvas = new unsigned char[canvasLen]; |
| + unsigned char* output = new unsigned char[outputLen]; |
| + |
| + auto cleanup = [&]() { |
| + if (canvas) |
| + delete[] canvas; |
| + if (output) |
| + delete[] output; |
| + }; |
| + |
| + if (!canvas || !output) { |
| + cleanup(); |
| + return base::TimeDelta(); |
| + } |
| + |
| + if (setAlpha) { |
| + memset(canvas, 128, canvasLen); |
| + } else { |
| + memset(canvas, 200, canvasLen); |
| + } |
| + |
| + base::ElapsedTimer runTime; |
| + if (fastPath) { |
| + blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| + } else { |
| + blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), output); |
| + } |
| + |
| + auto result = runTime.Elapsed(); |
| + cleanup(); |
| + return result; |
| +} |
| + |
| +TEST_F(RGBAtoRGBTest, testPerf1k) { |
| + auto neonElapsed = testNpixels(); |
| + auto scalarElapsed = testNpixels(false); |
| + |
| + EXPECT_TRUE(neonElapsed < scalarElapsed) |
| + << "Neon: " << neonElapsed << "\tScalar: " << scalarElapsed << std::endl; |
| +} |
| + |
| +TEST_F(RGBAtoRGBTest, testPerf4k) { |
| + auto neonElapsed = testNpixels(true, 4000, 4000); |
| + auto scalarElapsed = testNpixels(false, 4000, 4000); |
| + |
| + EXPECT_TRUE(neonElapsed < scalarElapsed) |
| + << "Neon: " << neonElapsed << "\tScalar: " << scalarElapsed << std::endl; |
| +} |
| + |
| +// This width will force the tail case, cause width = (16 * 64) + 15. |
| +static bool testRandNpixels(const size_t width = 1039, |
| + const size_t height = 1024, |
| + bool setAlpha = true) { |
| + size_t pixels = width * height; |
| + size_t canvasLen = channelsRGBA * pixels; |
| + size_t outputLen = channelsRGB * pixels; |
| + unsigned char* canvas = new unsigned char[canvasLen]; |
| + unsigned char* expected = new unsigned char[outputLen]; |
| + unsigned char* output = new unsigned char[outputLen]; |
| + |
| + auto cleanup = [&]() { |
| + if (canvas) |
| + delete[] canvas; |
| + if (expected) |
| + delete[] expected; |
| + if (output) |
| + delete[] output; |
| + }; |
| + |
| + if (!canvas || !output || !expected) { |
| + cleanup(); |
| + return false; |
| + } |
| + |
| + if (setAlpha) { |
| + memset(canvas, 128, canvasLen); |
| + } else { |
| + memset(canvas, 200, canvasLen); |
| + } |
| + |
| + srand(time(0)); |
| + unsigned char* ptr = canvas; |
| + for (size_t i = 0; i < pixels; ++i) { |
| + *ptr++ = static_cast<unsigned char>(rand() % 255); |
| + *ptr++ = static_cast<unsigned char>(rand() % 255); |
| + *ptr++ = static_cast<unsigned char>(rand() % 255); |
| + *ptr++ = static_cast<unsigned char>(rand() % 255); |
| + } |
| + |
| + blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| + blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| + |
| + bool result = memcmp(expected, output, outputLen) == 0; |
| + |
| + cleanup(); |
| + return result; |
| +} |
| + |
| +TEST_F(RGBAtoRGBTest, randomPixels) { |
| + EXPECT_TRUE(testRandNpixels()); |
| +} |
| + |
| +#endif |
| +} // namespace blink |