| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/timer/elapsed_timer.h" |
| 6 #include "platform/image-encoders/RGBAtoRGB.h" |
| 7 #include "testing/gtest/include/gtest/gtest.h" |
| 8 #include "wtf/build_config.h" |
| 9 |
| 10 namespace blink { |
| 11 |
| 12 class RGBAtoRGBTest : public ::testing::Test { |
| 13 public: |
| 14 RGBAtoRGBTest() {} |
| 15 }; |
| 16 |
| 17 static const size_t channelsRGBA = 4; |
| 18 static const size_t channelsRGB = 3; |
| 19 |
| 20 inline size_t calculateRGBAPixels(size_t inputBufferSize) { |
| 21 size_t pixels = inputBufferSize / channelsRGBA; |
| 22 return pixels; |
| 23 } |
| 24 |
| 25 inline size_t calculateRGBOutputSize(size_t inputBufferSize) { |
| 26 size_t pixels = calculateRGBAPixels(inputBufferSize); |
| 27 pixels *= channelsRGB; |
| 28 return pixels; |
| 29 } |
| 30 |
| 31 TEST_F(RGBAtoRGBTest, testOpaqueCaseEven8pixels) { |
| 32 unsigned char canvas[] = {255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, |
| 33 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 255, |
| 34 0, 255, 0, 255, 0, 255, 0, 255, 0, 255}; |
| 35 |
| 36 unsigned char expected[] = {255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 0, |
| 37 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0}; |
| 38 #if OS(WIN) |
| 39 // Windows release bot can't be reasoned with (compiler error C2131). |
| 40 static const constexpr size_t pixels = sizeof(canvas) / channelsRGBA; |
| 41 static const constexpr size_t rgbSize = pixels * channelsRGB; |
| 42 #else |
| 43 const size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| 44 const size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| 45 #endif |
| 46 |
| 47 unsigned char output[rgbSize]; |
| 48 memset(output, 0, rgbSize); |
| 49 |
| 50 blink::RGBAtoRGB(canvas, static_cast<unsigned>(pixels), output); |
| 51 |
| 52 EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| 53 } |
| 54 |
| 55 #ifdef __ARM_NEON__ |
| 56 TEST_F(RGBAtoRGBTest, testCaseEven16pixels) { |
| 57 unsigned char canvas[] = { |
| 58 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, |
| 59 0, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, |
| 60 0, 255, 0, 255, 0, 255, 0, 0, 255, 128, 0, 0, 255, |
| 61 128, 0, 0, 255, 128, 0, 0, 255, 128, 128, 128, 128, 128, |
| 62 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}; |
| 63 |
| 64 const size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| 65 const size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| 66 unsigned char output[rgbSize]; |
| 67 unsigned char expected[rgbSize]; |
| 68 memset(output, 0, rgbSize); |
| 69 memset(expected, 0, rgbSize); |
| 70 |
| 71 blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| 72 blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| 73 |
| 74 EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| 75 } |
| 76 |
| 77 TEST_F(RGBAtoRGBTest, testCaseOdd17pixels) { |
| 78 unsigned char canvas[] = { |
| 79 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, |
| 80 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, |
| 81 0, 255, 0, 255, 0, 0, 255, 128, 0, 0, 255, 128, 0, 0, |
| 82 255, 128, 0, 0, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 83 128, 128, 128, 128, 128, 128, 128, 128, 10, 10, 10, 100}; |
| 84 |
| 85 const size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| 86 const size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| 87 unsigned char output[rgbSize]; |
| 88 unsigned char expected[rgbSize]; |
| 89 memset(output, 0, rgbSize); |
| 90 memset(expected, 0, rgbSize); |
| 91 |
| 92 blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| 93 blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| 94 |
| 95 EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| 96 } |
| 97 |
| 98 TEST_F(RGBAtoRGBTest, testCaseEven32pixels) { |
| 99 unsigned char canvas[] = { |
| 100 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, |
| 101 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, |
| 102 0, 255, 0, 0, 255, 128, 0, 0, 255, 128, 0, 0, 255, 128, 0, |
| 103 0, 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 104 128, 128, 128, 128, 128, 128, 128, 255, 128, 128, 128, 255, 128, 128, 128, |
| 105 255, 128, 128, 128, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, |
| 106 0, 255, 255, 0, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, |
| 107 255, 0, 255, 0, 255, 0, 255, 0, 0, 255, 128, 0, 0, 255, 128, |
| 108 0, 0, 255, 128, 0, 0, 255, 128}; |
| 109 |
| 110 const size_t pixels = calculateRGBAPixels(sizeof(canvas)); |
| 111 const size_t rgbSize = calculateRGBOutputSize(sizeof(canvas)); |
| 112 unsigned char output[rgbSize]; |
| 113 unsigned char expected[rgbSize]; |
| 114 memset(output, 0, rgbSize); |
| 115 memset(expected, 0, rgbSize); |
| 116 |
| 117 blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| 118 blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| 119 |
| 120 EXPECT_EQ(memcmp(expected, output, rgbSize), 0); |
| 121 } |
| 122 |
| 123 static base::TimeDelta testNpixels(bool fastPath = true, |
| 124 const size_t width = 1024, |
| 125 const size_t height = 1024, |
| 126 bool setAlpha = true) { |
| 127 const size_t pixels = width * height; |
| 128 const size_t canvasLen = channelsRGBA * width * height; |
| 129 const size_t outputLen = channelsRGB * width * height; |
| 130 unsigned char* canvas = new unsigned char[canvasLen]; |
| 131 unsigned char* output = new unsigned char[outputLen]; |
| 132 |
| 133 auto cleanup = [&]() { |
| 134 if (canvas) |
| 135 delete[] canvas; |
| 136 if (output) |
| 137 delete[] output; |
| 138 }; |
| 139 |
| 140 if (!canvas || !output) { |
| 141 cleanup(); |
| 142 return base::TimeDelta(); |
| 143 } |
| 144 |
| 145 if (setAlpha) { |
| 146 memset(canvas, 128, canvasLen); |
| 147 } else { |
| 148 memset(canvas, 200, canvasLen); |
| 149 } |
| 150 |
| 151 base::ElapsedTimer runTime; |
| 152 if (fastPath) { |
| 153 blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| 154 } else { |
| 155 blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), output); |
| 156 } |
| 157 |
| 158 auto result = runTime.Elapsed(); |
| 159 cleanup(); |
| 160 return result; |
| 161 } |
| 162 |
| 163 TEST_F(RGBAtoRGBTest, testPerf1k) { |
| 164 auto neonElapsed = testNpixels(); |
| 165 auto scalarElapsed = testNpixels(false); |
| 166 |
| 167 EXPECT_TRUE(neonElapsed < scalarElapsed) |
| 168 << "Neon: " << neonElapsed << "\tScalar: " << scalarElapsed << std::endl; |
| 169 } |
| 170 |
| 171 TEST_F(RGBAtoRGBTest, testPerf4k) { |
| 172 auto neonElapsed = testNpixels(true, 4000, 4000); |
| 173 auto scalarElapsed = testNpixels(false, 4000, 4000); |
| 174 |
| 175 EXPECT_TRUE(neonElapsed < scalarElapsed) |
| 176 << "Neon: " << neonElapsed << "\tScalar: " << scalarElapsed << std::endl; |
| 177 } |
| 178 |
| 179 // This width will force the tail case, cause width = (16 * 64) + 15. |
| 180 static bool testRandNpixels(const size_t width = 1039, |
| 181 const size_t height = 1024, |
| 182 bool setAlpha = true) { |
| 183 const size_t pixels = width * height; |
| 184 const size_t canvasLen = channelsRGBA * pixels; |
| 185 const size_t outputLen = channelsRGB * pixels; |
| 186 unsigned char* canvas = new unsigned char[canvasLen]; |
| 187 unsigned char* expected = new unsigned char[outputLen]; |
| 188 unsigned char* output = new unsigned char[outputLen]; |
| 189 |
| 190 auto cleanup = [&]() { |
| 191 if (canvas) |
| 192 delete[] canvas; |
| 193 if (expected) |
| 194 delete[] expected; |
| 195 if (output) |
| 196 delete[] output; |
| 197 }; |
| 198 |
| 199 if (!canvas || !output || !expected) { |
| 200 cleanup(); |
| 201 return false; |
| 202 } |
| 203 |
| 204 if (setAlpha) { |
| 205 memset(canvas, 128, canvasLen); |
| 206 } else { |
| 207 memset(canvas, 200, canvasLen); |
| 208 } |
| 209 |
| 210 srand(time(0)); |
| 211 unsigned char* ptr = canvas; |
| 212 for (size_t i = 0; i < pixels; ++i) { |
| 213 *ptr++ = static_cast<unsigned char>(rand() % 255); |
| 214 *ptr++ = static_cast<unsigned char>(rand() % 255); |
| 215 *ptr++ = static_cast<unsigned char>(rand() % 255); |
| 216 *ptr++ = static_cast<unsigned char>(rand() % 255); |
| 217 } |
| 218 |
| 219 blink::RGBAtoRGBScalar(canvas, static_cast<unsigned>(pixels), expected); |
| 220 blink::RGBAtoRGBNeon(canvas, static_cast<unsigned>(pixels), output); |
| 221 |
| 222 bool result = memcmp(expected, output, outputLen) == 0; |
| 223 |
| 224 cleanup(); |
| 225 return result; |
| 226 } |
| 227 |
| 228 TEST_F(RGBAtoRGBTest, randomPixels) { |
| 229 EXPECT_TRUE(testRandNpixels()); |
| 230 } |
| 231 |
| 232 #endif |
| 233 } // namespace blink |
| OLD | NEW |