TestDecodersPerf.cpp (6389B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "gtest/gtest.h" 6 #include "gtest/MozGTestBench.h" 7 8 #include "Common.h" 9 #include "Decoder.h" 10 #include "DecoderFactory.h" 11 #include "IDecodingTask.h" 12 #include "mozilla/RefPtr.h" 13 #include "ProgressTracker.h" 14 #include "SourceBuffer.h" 15 16 using namespace mozilla; 17 using namespace mozilla::gfx; 18 using namespace mozilla::image; 19 20 namespace { 21 22 static void CheckDecoderState(const ImageTestCase& aTestCase, 23 image::Decoder* aDecoder, 24 const IntSize& aOutputSize) { 25 // image::Decoder should match what we asked for in the MIME type. 26 EXPECT_NE(aDecoder->GetType(), DecoderType::UNKNOWN); 27 EXPECT_EQ(aDecoder->GetType(), 28 DecoderFactory::GetDecoderType(aTestCase.mMimeType)); 29 30 EXPECT_TRUE(aDecoder->GetDecodeDone()); 31 EXPECT_FALSE(aDecoder->HasError()); 32 33 // Verify that the decoder made the expected progress. 34 Progress progress = aDecoder->TakeProgress(); 35 EXPECT_FALSE(bool(progress & FLAG_HAS_ERROR)); 36 EXPECT_FALSE(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR)); 37 38 EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE)); 39 EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE)); 40 EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE)); 41 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT), 42 bool(progress & FLAG_HAS_TRANSPARENCY)); 43 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED), 44 bool(progress & FLAG_IS_ANIMATED)); 45 46 // The decoder should get the correct size. 47 OrientedIntSize size = aDecoder->Size(); 48 EXPECT_EQ(aTestCase.mSize.width, size.width); 49 EXPECT_EQ(aTestCase.mSize.height, size.height); 50 51 // Get the current frame, which is always the first frame of the image 52 // because CreateAnonymousDecoder() forces a first-frame-only decode. 53 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 54 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 55 56 // Verify that the resulting surfaces matches our expectations. 57 EXPECT_TRUE(surface->IsDataSourceSurface()); 58 EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX || 59 surface->GetFormat() == SurfaceFormat::OS_RGBA); 60 EXPECT_EQ(aOutputSize, surface->GetSize()); 61 } 62 63 template <typename Func> 64 static void WithSingleChunkDecode(const ImageTestCase& aTestCase, 65 SourceBuffer* aSourceBuffer, 66 const Maybe<IntSize>& aOutputSize, 67 Func aResultChecker) { 68 auto sourceBuffer = WrapNotNull(RefPtr<SourceBuffer>(aSourceBuffer)); 69 70 // Create a decoder. 71 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); 72 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder( 73 decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY, 74 aTestCase.mSurfaceFlags); 75 ASSERT_TRUE(decoder != nullptr); 76 RefPtr<IDecodingTask> task = 77 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false); 78 79 // Run the full decoder synchronously. 80 task->Run(); 81 82 // Call the lambda to verify the expected results. 83 aResultChecker(decoder); 84 } 85 86 static void CheckDecode(const ImageTestCase& aTestCase, 87 SourceBuffer* aSourceBuffer) { 88 WithSingleChunkDecode( 89 aTestCase, aSourceBuffer, Nothing(), [&](image::Decoder* aDecoder) { 90 CheckDecoderState(aTestCase, aDecoder, aTestCase.mSize); 91 }); 92 } 93 94 static void CheckDownscaleDuringDecode(const ImageTestCase& aTestCase, 95 SourceBuffer* aSourceBuffer) { 96 IntSize outputSize(20, 20); 97 WithSingleChunkDecode(aTestCase, aSourceBuffer, Some(outputSize), 98 [&](image::Decoder* aDecoder) { 99 CheckDecoderState(aTestCase, aDecoder, outputSize); 100 }); 101 } 102 103 #define IMAGE_GTEST_BENCH_FIXTURE(test_fixture, test_case) \ 104 class test_fixture : public ImageBenchmarkBase { \ 105 protected: \ 106 test_fixture() : ImageBenchmarkBase(test_case()) {} \ 107 }; 108 109 #define IMAGE_GTEST_NATIVE_BENCH_F(test_fixture) \ 110 MOZ_GTEST_BENCH_F(test_fixture, Native, \ 111 [this] { CheckDecode(mTestCase, mSourceBuffer); }); 112 113 #define IMAGE_GTEST_DOWNSCALE_BENCH_F(test_fixture) \ 114 MOZ_GTEST_BENCH_F(test_fixture, Downscale, [this] { \ 115 CheckDownscaleDuringDecode(mTestCase, mSourceBuffer); \ 116 }); 117 118 #define IMAGE_GTEST_NO_COLOR_MANAGEMENT_BENCH_F(test_fixture) \ 119 MOZ_GTEST_BENCH_F(test_fixture, NoColorManagement, [this] { \ 120 ImageTestCase testCase = mTestCase; \ 121 testCase.mSurfaceFlags |= SurfaceFlags::NO_COLORSPACE_CONVERSION; \ 122 CheckDecode(testCase, mSourceBuffer); \ 123 }); 124 125 #define IMAGE_GTEST_NO_PREMULTIPLY_BENCH_F(test_fixture) \ 126 MOZ_GTEST_BENCH_F(test_fixture, NoPremultiplyAlpha, [this] { \ 127 ImageTestCase testCase = mTestCase; \ 128 testCase.mSurfaceFlags |= SurfaceFlags::NO_PREMULTIPLY_ALPHA; \ 129 CheckDecode(testCase, mSourceBuffer); \ 130 }); 131 132 #define IMAGE_GTEST_BENCH_F(type, test) \ 133 IMAGE_GTEST_BENCH_FIXTURE(ImageDecodersPerf_##type##_##test, \ 134 Perf##test##type##TestCase) \ 135 IMAGE_GTEST_NATIVE_BENCH_F(ImageDecodersPerf_##type##_##test) \ 136 IMAGE_GTEST_DOWNSCALE_BENCH_F(ImageDecodersPerf_##type##_##test) \ 137 IMAGE_GTEST_NO_COLOR_MANAGEMENT_BENCH_F(ImageDecodersPerf_##type##_##test) 138 139 #define IMAGE_GTEST_BENCH_ALPHA_F(type, test) \ 140 IMAGE_GTEST_BENCH_F(type, test) \ 141 IMAGE_GTEST_NO_PREMULTIPLY_BENCH_F(ImageDecodersPerf_##type##_##test) 142 143 IMAGE_GTEST_BENCH_F(JPG, YCbCr) 144 IMAGE_GTEST_BENCH_F(JPG, Cmyk) 145 IMAGE_GTEST_BENCH_F(JPG, Gray) 146 147 IMAGE_GTEST_BENCH_F(PNG, Rgb) 148 IMAGE_GTEST_BENCH_F(PNG, Gray) 149 IMAGE_GTEST_BENCH_ALPHA_F(PNG, RgbAlpha) 150 IMAGE_GTEST_BENCH_ALPHA_F(PNG, GrayAlpha) 151 152 IMAGE_GTEST_BENCH_F(WebP, RgbLossless) 153 IMAGE_GTEST_BENCH_F(WebP, RgbLossy) 154 IMAGE_GTEST_BENCH_ALPHA_F(WebP, RgbAlphaLossless) 155 IMAGE_GTEST_BENCH_ALPHA_F(WebP, RgbAlphaLossy) 156 157 IMAGE_GTEST_BENCH_F(GIF, Rgb) 158 159 } // namespace