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
CheckDecoderState(const ImageTestCase & aTestCase,image::Decoder * aDecoder,const IntSize & aOutputSize)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>
WithSingleChunkDecode(const ImageTestCase & aTestCase,SourceBuffer * aSourceBuffer,const Maybe<IntSize> & aOutputSize,Func aResultChecker)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
CheckDecode(const ImageTestCase & aTestCase,SourceBuffer * aSourceBuffer)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
CheckDownscaleDuringDecode(const ImageTestCase & aTestCase,SourceBuffer * aSourceBuffer)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
160