Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp

Issue 1812273003: Eliminate copies of encoded image data (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 11 matching lines...) Expand all
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "platform/graphics/ImageFrameGenerator.h" 26 #include "platform/graphics/ImageFrameGenerator.h"
27 27
28 #include "platform/SharedBuffer.h" 28 #include "platform/SharedBuffer.h"
29 #include "platform/ThreadSafeFunctional.h" 29 #include "platform/ThreadSafeFunctional.h"
30 #include "platform/graphics/ImageDecodingStore.h" 30 #include "platform/graphics/ImageDecodingStore.h"
31 #include "platform/graphics/test/MockImageDecoder.h" 31 #include "platform/graphics/test/MockImageDecoder.h"
32 #include "platform/image-decoders/SegmentReader.h"
32 #include "public/platform/Platform.h" 33 #include "public/platform/Platform.h"
33 #include "public/platform/WebTaskRunner.h" 34 #include "public/platform/WebTaskRunner.h"
34 #include "public/platform/WebThread.h" 35 #include "public/platform/WebThread.h"
35 #include "public/platform/WebTraceLocation.h" 36 #include "public/platform/WebTraceLocation.h"
36 #include "testing/gtest/include/gtest/gtest.h" 37 #include "testing/gtest/include/gtest/gtest.h"
37 38
38 namespace blink { 39 namespace blink {
39 40
40 namespace { 41 namespace {
41 42
42 // Helper methods to generate standard sizes. 43 // Helper methods to generate standard sizes.
43 SkISize fullSize() { return SkISize::Make(100, 100); } 44 SkISize fullSize() { return SkISize::Make(100, 100); }
44 45
45 SkImageInfo imageInfo() 46 SkImageInfo imageInfo()
46 { 47 {
47 return SkImageInfo::Make(100, 100, kBGRA_8888_SkColorType, kOpaque_SkAlphaTy pe); 48 return SkImageInfo::Make(100, 100, kBGRA_8888_SkColorType, kOpaque_SkAlphaTy pe);
48 } 49 }
49 50
50 } // namespace 51 } // namespace
51 52
52 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderC lient { 53 class ImageFrameGeneratorTest : public ::testing::Test, public MockImageDecoderC lient {
53 public: 54 public:
54 void SetUp() override 55 void SetUp() override
55 { 56 {
56 ImageDecodingStore::instance().setCacheLimitInBytes(1024 * 1024); 57 ImageDecodingStore::instance().setCacheLimitInBytes(1024 * 1024);
58 m_generator = ImageFrameGenerator::create(fullSize(), false);
57 m_data = SharedBuffer::create(); 59 m_data = SharedBuffer::create();
58 m_generator = ImageFrameGenerator::create(fullSize(), m_data, false); 60 m_segmentReader = SegmentReader::createFromSharedBuffer(m_data);
59 useMockImageDecoderFactory(); 61 useMockImageDecoderFactory();
60 m_decodersDestroyed = 0; 62 m_decodersDestroyed = 0;
61 m_decodeRequestCount = 0; 63 m_decodeRequestCount = 0;
62 m_status = ImageFrame::FrameEmpty; 64 m_status = ImageFrame::FrameEmpty;
63 m_frameCount = 1; 65 m_frameCount = 1;
64 m_requestedClearExceptFrame = kNotFound; 66 m_requestedClearExceptFrame = kNotFound;
65 } 67 }
66 68
67 void TearDown() override 69 void TearDown() override
68 { 70 {
(...skipping 25 matching lines...) Expand all
94 size_t frameCount() override { return m_frameCount; } 96 size_t frameCount() override { return m_frameCount; }
95 int repetitionCount() const override { return m_frameCount == 1 ? cAnimation None:cAnimationLoopOnce; } 97 int repetitionCount() const override { return m_frameCount == 1 ? cAnimation None:cAnimationLoopOnce; }
96 float frameDuration() const override { return 0; } 98 float frameDuration() const override { return 0; }
97 99
98 protected: 100 protected:
99 void useMockImageDecoderFactory() 101 void useMockImageDecoderFactory()
100 { 102 {
101 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this , fullSize())); 103 m_generator->setImageDecoderFactory(MockImageDecoderFactory::create(this , fullSize()));
102 } 104 }
103 105
104 void addNewData(bool allDataReceived = false) 106 void addNewData()
105 { 107 {
106 m_data->append("g", 1u); 108 m_data->append("g", 1u);
107 m_generator->setData(m_data, allDataReceived);
108 } 109 }
109 110
110 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStat us = status; } 111 void setFrameStatus(ImageFrame::Status status) { m_status = m_nextFrameStat us = status; }
111 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = st atus; } 112 void setNextFrameStatus(ImageFrame::Status status) { m_nextFrameStatus = st atus; }
112 void setFrameCount(size_t count) 113 void setFrameCount(size_t count)
113 { 114 {
114 m_frameCount = count; 115 m_frameCount = count;
115 if (count > 1) { 116 if (count > 1) {
116 m_generator.clear(); 117 m_generator.clear();
117 m_generator = ImageFrameGenerator::create(fullSize(), m_data, true, true); 118 m_generator = ImageFrameGenerator::create(fullSize(), true);
118 useMockImageDecoderFactory(); 119 useMockImageDecoderFactory();
119 } 120 }
120 } 121 }
121 122
122 RefPtr<SharedBuffer> m_data; 123 RefPtr<SharedBuffer> m_data;
124 RefPtr<SegmentReader> m_segmentReader;
123 RefPtr<ImageFrameGenerator> m_generator; 125 RefPtr<ImageFrameGenerator> m_generator;
124 int m_decodersDestroyed; 126 int m_decodersDestroyed;
125 int m_decodeRequestCount; 127 int m_decodeRequestCount;
126 ImageFrame::Status m_status; 128 ImageFrame::Status m_status;
127 ImageFrame::Status m_nextFrameStatus; 129 ImageFrame::Status m_nextFrameStatus;
128 size_t m_frameCount; 130 size_t m_frameCount;
129 size_t m_requestedClearExceptFrame; 131 size_t m_requestedClearExceptFrame;
130 }; 132 };
131 133
132 TEST_F(ImageFrameGeneratorTest, incompleteDecode) 134 TEST_F(ImageFrameGeneratorTest, incompleteDecode)
133 { 135 {
134 setFrameStatus(ImageFrame::FramePartial); 136 setFrameStatus(ImageFrame::FramePartial);
135 137
136 char buffer[100 * 100 * 4]; 138 char buffer[100 * 100 * 4];
137 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 139 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
138 EXPECT_EQ(1, m_decodeRequestCount); 140 EXPECT_EQ(1, m_decodeRequestCount);
139 141
140 addNewData(); 142 addNewData();
141 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 143 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
142 EXPECT_EQ(2, m_decodeRequestCount); 144 EXPECT_EQ(2, m_decodeRequestCount);
143 EXPECT_EQ(0, m_decodersDestroyed); 145 EXPECT_EQ(0, m_decodersDestroyed);
144 } 146 }
145 147
146 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete) 148 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete)
147 { 149 {
148 setFrameStatus(ImageFrame::FramePartial); 150 setFrameStatus(ImageFrame::FramePartial);
149 151
150 char buffer[100 * 100 * 4]; 152 char buffer[100 * 100 * 4];
151 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 153 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
152 EXPECT_EQ(1, m_decodeRequestCount); 154 EXPECT_EQ(1, m_decodeRequestCount);
153 EXPECT_EQ(0, m_decodersDestroyed); 155 EXPECT_EQ(0, m_decodersDestroyed);
154 156
155 setFrameStatus(ImageFrame::FrameComplete); 157 setFrameStatus(ImageFrame::FrameComplete);
156 addNewData(); 158 addNewData();
157 159
158 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 160 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
159 EXPECT_EQ(2, m_decodeRequestCount); 161 EXPECT_EQ(2, m_decodeRequestCount);
160 EXPECT_EQ(1, m_decodersDestroyed); 162 EXPECT_EQ(1, m_decodersDestroyed);
161 163
162 // Decoder created again. 164 // Decoder created again.
163 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 165 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
164 EXPECT_EQ(3, m_decodeRequestCount); 166 EXPECT_EQ(3, m_decodeRequestCount);
165 } 167 }
166 168
167 static void decodeThreadMain(ImageFrameGenerator* generator) 169 static void decodeThreadMain(ImageFrameGenerator* generator, SegmentReader* segm entReader)
168 { 170 {
169 char buffer[100 * 100 * 4]; 171 char buffer[100 * 100 * 4];
170 generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 172 generator->decodeAndScale(segmentReader, false, 0, imageInfo(), buffer, 100 * 4);
171 }
172
173 static void decodeThreadWithRefEncodedMain(ImageFrameGenerator* generator)
174 {
175 // Image must be complete - refEncodedData otherwise returns null.
176 char buffer[100 * 100 * 4];
177 SkData* data = generator->refEncodedData();
178 generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4);
179 data->unref();
180 } 173 }
181 174
182 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded) 175 TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
183 { 176 {
184 setFrameStatus(ImageFrame::FramePartial); 177 setFrameStatus(ImageFrame::FramePartial);
185 178
186 char buffer[100 * 100 * 4]; 179 char buffer[100 * 100 * 4];
187 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 180 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
188 EXPECT_EQ(1, m_decodeRequestCount); 181 EXPECT_EQ(1, m_decodeRequestCount);
189 EXPECT_EQ(0, m_decodersDestroyed); 182 EXPECT_EQ(0, m_decodersDestroyed);
190 SkData* data = m_generator->refEncodedData();
191 EXPECT_EQ(nullptr, data);
192 183
193 // LocalFrame can now be decoded completely. 184 // LocalFrame can now be decoded completely.
194 setFrameStatus(ImageFrame::FrameComplete); 185 setFrameStatus(ImageFrame::FrameComplete);
195 addNewData(); 186 addNewData();
196 // addNewData is calling m_generator->setData with allDataReceived == false, which means that
197 // refEncodedData should return null.
198 data = m_generator->refEncodedData();
199 EXPECT_EQ(nullptr, data);
200 OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("Decod eThread")); 187 OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("Decod eThread"));
201 thread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, threadSafeBind(&decode ThreadMain, AllowCrossThreadAccess(m_generator.get()))); 188 thread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, threadSafeBind(&decode ThreadMain, AllowCrossThreadAccess(m_generator.get()), AllowCrossThreadAccess(m_ segmentReader.get())));
202 thread.clear(); 189 thread.clear();
203 EXPECT_EQ(2, m_decodeRequestCount); 190 EXPECT_EQ(2, m_decodeRequestCount);
204 EXPECT_EQ(1, m_decodersDestroyed); 191 EXPECT_EQ(1, m_decodersDestroyed);
205 192
206 // Decoder created again. 193 // Decoder created again.
207 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 194 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
208 EXPECT_EQ(3, m_decodeRequestCount); 195 EXPECT_EQ(3, m_decodeRequestCount);
209 196
210 addNewData(true); 197 addNewData();
211 data = m_generator->refEncodedData();
212 ASSERT_TRUE(data);
213 // To prevent data writting, SkData::unique() should be false.
214 ASSERT_TRUE(!data->unique());
215 198
216 // Thread will also ref and unref the data. 199 // Delete generator.
217 thread = adoptPtr(Platform::current()->createThread("RefEncodedDataThread")) ;
218 thread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, threadSafeBind(&decode ThreadWithRefEncodedMain, AllowCrossThreadAccess(m_generator.get())));
219 thread.clear();
220 EXPECT_EQ(4, m_decodeRequestCount);
221
222 data->unref();
223 // m_generator is holding the only reference to SkData now.
224 ASSERT_TRUE(data->unique());
225
226 data = m_generator->refEncodedData();
227 ASSERT_TRUE(data && !data->unique());
228
229 // Delete generator, and SkData should have the only reference.
230 m_generator = nullptr; 200 m_generator = nullptr;
231 ASSERT_TRUE(data->unique());
232 data->unref();
233 } 201 }
234 202
235 TEST_F(ImageFrameGeneratorTest, frameHasAlpha) 203 TEST_F(ImageFrameGeneratorTest, frameHasAlpha)
236 { 204 {
237 setFrameStatus(ImageFrame::FramePartial); 205 setFrameStatus(ImageFrame::FramePartial);
238 206
239 char buffer[100 * 100 * 4]; 207 char buffer[100 * 100 * 4];
240 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 208 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
241 EXPECT_TRUE(m_generator->hasAlpha(0)); 209 EXPECT_TRUE(m_generator->hasAlpha(0));
242 EXPECT_EQ(1, m_decodeRequestCount); 210 EXPECT_EQ(1, m_decodeRequestCount);
243 211
244 ImageDecoder* tempDecoder = 0; 212 ImageDecoder* tempDecoder = 0;
245 EXPECT_TRUE(ImageDecodingStore::instance().lockDecoder(m_generator.get(), fu llSize(), &tempDecoder)); 213 EXPECT_TRUE(ImageDecodingStore::instance().lockDecoder(m_generator.get(), fu llSize(), &tempDecoder));
246 ASSERT_TRUE(tempDecoder); 214 ASSERT_TRUE(tempDecoder);
247 tempDecoder->frameBufferAtIndex(0)->setHasAlpha(false); 215 tempDecoder->frameBufferAtIndex(0)->setHasAlpha(false);
248 ImageDecodingStore::instance().unlockDecoder(m_generator.get(), tempDecoder) ; 216 ImageDecodingStore::instance().unlockDecoder(m_generator.get(), tempDecoder) ;
249 EXPECT_EQ(2, m_decodeRequestCount); 217 EXPECT_EQ(2, m_decodeRequestCount);
250 218
251 setFrameStatus(ImageFrame::FrameComplete); 219 setFrameStatus(ImageFrame::FrameComplete);
252 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 220 m_generator->decodeAndScale(m_segmentReader.get(), false, 0, imageInfo(), bu ffer, 100 * 4);
253 EXPECT_EQ(3, m_decodeRequestCount); 221 EXPECT_EQ(3, m_decodeRequestCount);
254 EXPECT_FALSE(m_generator->hasAlpha(0)); 222 EXPECT_FALSE(m_generator->hasAlpha(0));
255 } 223 }
256 224
257 TEST_F(ImageFrameGeneratorTest, clearMultiFrameDecoder) 225 TEST_F(ImageFrameGeneratorTest, clearMultiFrameDecoder)
258 { 226 {
259 setFrameCount(3); 227 setFrameCount(3);
260 setFrameStatus(ImageFrame::FrameComplete); 228 setFrameStatus(ImageFrame::FrameComplete);
261 229
262 char buffer[100 * 100 * 4]; 230 char buffer[100 * 100 * 4];
263 m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4); 231 m_generator->decodeAndScale(m_segmentReader.get(), true, 0, imageInfo(), buf fer, 100 * 4);
264 EXPECT_EQ(1, m_decodeRequestCount); 232 EXPECT_EQ(1, m_decodeRequestCount);
265 EXPECT_EQ(0, m_decodersDestroyed); 233 EXPECT_EQ(0, m_decodersDestroyed);
266 EXPECT_EQ(0U, m_requestedClearExceptFrame); 234 EXPECT_EQ(0U, m_requestedClearExceptFrame);
267 235
268 setFrameStatus(ImageFrame::FrameComplete); 236 setFrameStatus(ImageFrame::FrameComplete);
269 237
270 m_generator->decodeAndScale(1, imageInfo(), buffer, 100 * 4); 238 m_generator->decodeAndScale(m_segmentReader.get(), true, 1, imageInfo(), buf fer, 100 * 4);
271 EXPECT_EQ(2, m_decodeRequestCount); 239 EXPECT_EQ(2, m_decodeRequestCount);
272 EXPECT_EQ(0, m_decodersDestroyed); 240 EXPECT_EQ(0, m_decodersDestroyed);
273 EXPECT_EQ(1U, m_requestedClearExceptFrame); 241 EXPECT_EQ(1U, m_requestedClearExceptFrame);
274 242
275 setFrameStatus(ImageFrame::FrameComplete); 243 setFrameStatus(ImageFrame::FrameComplete);
276 244
277 // Decoding the last frame of a multi-frame images should trigger clearing 245 // Decoding the last frame of a multi-frame images should trigger clearing
278 // all the frame data, but not destroying the decoder. See comments in 246 // all the frame data, but not destroying the decoder. See comments in
279 // ImageFrameGenerator::tryToResumeDecode(). 247 // ImageFrameGenerator::tryToResumeDecode().
280 m_generator->decodeAndScale(2, imageInfo(), buffer, 100 * 4); 248 m_generator->decodeAndScale(m_segmentReader.get(), true, 2, imageInfo(), buf fer, 100 * 4);
281 EXPECT_EQ(3, m_decodeRequestCount); 249 EXPECT_EQ(3, m_decodeRequestCount);
282 EXPECT_EQ(0, m_decodersDestroyed); 250 EXPECT_EQ(0, m_decodersDestroyed);
283 EXPECT_EQ(kNotFound, m_requestedClearExceptFrame); 251 EXPECT_EQ(kNotFound, m_requestedClearExceptFrame);
284 } 252 }
285 253
286 } // namespace blink 254 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698