OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "platform/graphics/RecordingImageBufferSurface.h" | 5 #include "platform/graphics/RecordingImageBufferSurface.h" |
6 | 6 |
7 #include "platform/WebTaskRunner.h" | 7 #include "platform/WebTaskRunner.h" |
8 #include "platform/graphics/GraphicsContext.h" | 8 #include "platform/graphics/GraphicsContext.h" |
9 #include "platform/graphics/ImageBuffer.h" | 9 #include "platform/graphics/ImageBuffer.h" |
10 #include "platform/graphics/ImageBufferClient.h" | 10 #include "platform/graphics/ImageBufferClient.h" |
11 #include "platform/graphics/UnacceleratedImageBufferSurface.h" | 11 #include "platform/graphics/UnacceleratedImageBufferSurface.h" |
12 #include "platform/graphics/paint/PaintCanvas.h" | 12 #include "platform/graphics/paint/PaintCanvas.h" |
13 #include "platform/graphics/paint/PaintRecord.h" | 13 #include "platform/graphics/paint/PaintRecord.h" |
14 #include "platform/testing/TestingPlatformSupport.h" | 14 #include "platform/testing/TestingPlatformSupport.h" |
15 #include "public/platform/Platform.h" | 15 #include "public/platform/Platform.h" |
16 #include "public/platform/WebThread.h" | 16 #include "public/platform/WebThread.h" |
17 #include "public/platform/WebTraceLocation.h" | 17 #include "public/platform/WebTraceLocation.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 18 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "wtf/PtrUtil.h" | 20 #include "wtf/PtrUtil.h" |
21 #include "wtf/RefPtr.h" | 21 #include "wtf/RefPtr.h" |
22 #include <memory> | 22 #include <memory> |
23 | 23 |
24 using testing::Test; | 24 using testing::Test; |
25 | 25 |
26 namespace blink { | 26 namespace blink { |
27 | 27 |
28 class FakeImageBufferClient : public ImageBufferClient, | |
29 public WebThread::TaskObserver { | |
30 public: | |
31 FakeImageBufferClient(ImageBuffer* imageBuffer) | |
32 : m_isDirty(false), m_imageBuffer(imageBuffer), m_frameCount(0) {} | |
33 | |
34 ~FakeImageBufferClient() override {} | |
35 | |
36 // ImageBufferClient implementation | |
37 void notifySurfaceInvalid() override {} | |
38 bool isDirty() override { return m_isDirty; } | |
39 void didDisableAcceleration() override {} | |
40 void didFinalizeFrame() override { | |
41 if (m_isDirty) { | |
42 Platform::current()->currentThread()->removeTaskObserver(this); | |
43 m_isDirty = false; | |
44 } | |
45 ++m_frameCount; | |
46 } | |
47 | |
48 // TaskObserver implementation | |
49 void willProcessTask() override { NOTREACHED(); } | |
50 void didProcessTask() override { | |
51 ASSERT_TRUE(m_isDirty); | |
52 FloatRect dirtyRect(0, 0, 1, 1); | |
53 m_imageBuffer->finalizeFrame(dirtyRect); | |
54 ASSERT_FALSE(m_isDirty); | |
55 } | |
56 void restoreCanvasMatrixClipStack(PaintCanvas*) const override {} | |
57 | |
58 void fakeDraw() { | |
59 if (m_isDirty) | |
60 return; | |
61 m_isDirty = true; | |
62 Platform::current()->currentThread()->addTaskObserver(this); | |
63 } | |
64 | |
65 int frameCount() { return m_frameCount; } | |
66 | |
67 private: | |
68 bool m_isDirty; | |
69 ImageBuffer* m_imageBuffer; | |
70 int m_frameCount; | |
71 }; | |
72 | |
73 class MockSurfaceFactory : public RecordingImageBufferFallbackSurfaceFactory { | 28 class MockSurfaceFactory : public RecordingImageBufferFallbackSurfaceFactory { |
74 public: | 29 public: |
75 MockSurfaceFactory() : m_createSurfaceCount(0) {} | 30 MockSurfaceFactory() : m_createSurfaceCount(0) {} |
76 | 31 |
77 virtual std::unique_ptr<ImageBufferSurface> createSurface( | 32 virtual std::unique_ptr<ImageBufferSurface> createSurface( |
78 const IntSize& size, | 33 const IntSize& size, |
79 OpacityMode opacityMode, | 34 OpacityMode opacityMode, |
80 sk_sp<SkColorSpace> colorSpace, | 35 sk_sp<SkColorSpace> colorSpace, |
81 SkColorType colorType) { | 36 SkColorType colorType) { |
82 m_createSurfaceCount++; | 37 m_createSurfaceCount++; |
(...skipping 17 matching lines...) Expand all Loading... |
100 WTF::makeUnique<MockSurfaceFactory>(); | 55 WTF::makeUnique<MockSurfaceFactory>(); |
101 m_surfaceFactory = surfaceFactory.get(); | 56 m_surfaceFactory = surfaceFactory.get(); |
102 std::unique_ptr<RecordingImageBufferSurface> testSurface = | 57 std::unique_ptr<RecordingImageBufferSurface> testSurface = |
103 WTF::wrapUnique(new RecordingImageBufferSurface( | 58 WTF::wrapUnique(new RecordingImageBufferSurface( |
104 IntSize(10, 10), std::move(surfaceFactory), NonOpaque, nullptr)); | 59 IntSize(10, 10), std::move(surfaceFactory), NonOpaque, nullptr)); |
105 m_testSurface = testSurface.get(); | 60 m_testSurface = testSurface.get(); |
106 // We create an ImageBuffer in order for the testSurface to be | 61 // We create an ImageBuffer in order for the testSurface to be |
107 // properly initialized with a GraphicsContext | 62 // properly initialized with a GraphicsContext |
108 m_imageBuffer = ImageBuffer::create(std::move(testSurface)); | 63 m_imageBuffer = ImageBuffer::create(std::move(testSurface)); |
109 EXPECT_FALSE(!m_imageBuffer); | 64 EXPECT_FALSE(!m_imageBuffer); |
110 m_fakeImageBufferClient = | 65 m_testSurface->initializeCurrentFrame(); |
111 WTF::wrapUnique(new FakeImageBufferClient(m_imageBuffer.get())); | |
112 m_imageBuffer->setClient(m_fakeImageBufferClient.get()); | |
113 } | 66 } |
114 | 67 |
115 public: | 68 public: |
116 void testEmptyRecord() { | 69 RecordingImageBufferSurface* testSurface() { return m_testSurface; } |
117 m_testSurface->initializeCurrentFrame(); | 70 int createSurfaceCount() { return m_surfaceFactory->createSurfaceCount(); } |
118 sk_sp<PaintRecord> record = m_testSurface->getRecord(); | 71 SkCanvas* canvas() { return m_imageBuffer->canvas(); } |
119 EXPECT_TRUE((bool)record.get()); | |
120 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
121 expectDisplayListEnabled(true); | |
122 } | |
123 | |
124 void testNoFallbackWithClear() { | |
125 m_testSurface->initializeCurrentFrame(); | |
126 m_testSurface->willOverwriteCanvas(); | |
127 m_testSurface->getRecord(); | |
128 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
129 expectDisplayListEnabled(true); | |
130 } | |
131 | |
132 void testNonAnimatedCanvasUpdate() { | |
133 m_testSurface->initializeCurrentFrame(); | |
134 // Acquire record twice to simulate a static canvas: nothing drawn between | |
135 // updates. | |
136 m_fakeImageBufferClient->fakeDraw(); | |
137 m_testSurface->getRecord(); | |
138 m_testSurface->getRecord(); | |
139 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
140 expectDisplayListEnabled(true); | |
141 } | |
142 | |
143 void testAnimatedWithoutClear() { | |
144 m_testSurface->initializeCurrentFrame(); | |
145 m_fakeImageBufferClient->fakeDraw(); | |
146 m_testSurface->getRecord(); | |
147 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
148 EXPECT_EQ(0, m_surfaceFactory->createSurfaceCount()); | |
149 expectDisplayListEnabled(true); // first frame has an implicit clear | |
150 m_fakeImageBufferClient->fakeDraw(); | |
151 m_testSurface->getRecord(); | |
152 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
153 expectDisplayListEnabled(false); | |
154 } | |
155 | |
156 void testFrameFinalizedByTaskObserver1() { | |
157 m_testSurface->initializeCurrentFrame(); | |
158 expectDisplayListEnabled(true); | |
159 m_testSurface->getRecord(); | |
160 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
161 expectDisplayListEnabled(true); | |
162 m_fakeImageBufferClient->fakeDraw(); | |
163 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
164 expectDisplayListEnabled(true); | |
165 m_testSurface->getRecord(); | |
166 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
167 expectDisplayListEnabled(true); | |
168 m_fakeImageBufferClient->fakeDraw(); | |
169 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
170 expectDisplayListEnabled(true); | |
171 // Display list will be disabled only after exiting the runLoop | |
172 } | |
173 void testFrameFinalizedByTaskObserver2() { | |
174 EXPECT_EQ(3, m_fakeImageBufferClient->frameCount()); | |
175 expectDisplayListEnabled(false); | |
176 m_testSurface->getRecord(); | |
177 EXPECT_EQ(3, m_fakeImageBufferClient->frameCount()); | |
178 expectDisplayListEnabled(false); | |
179 m_fakeImageBufferClient->fakeDraw(); | |
180 EXPECT_EQ(3, m_fakeImageBufferClient->frameCount()); | |
181 expectDisplayListEnabled(false); | |
182 } | |
183 | |
184 void testAnimatedWithClear() { | |
185 m_testSurface->initializeCurrentFrame(); | |
186 m_testSurface->getRecord(); | |
187 m_testSurface->willOverwriteCanvas(); | |
188 m_fakeImageBufferClient->fakeDraw(); | |
189 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
190 m_testSurface->getRecord(); | |
191 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
192 expectDisplayListEnabled(true); | |
193 // clear after use | |
194 m_fakeImageBufferClient->fakeDraw(); | |
195 m_testSurface->willOverwriteCanvas(); | |
196 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
197 m_testSurface->getRecord(); | |
198 EXPECT_EQ(3, m_fakeImageBufferClient->frameCount()); | |
199 expectDisplayListEnabled(true); | |
200 } | |
201 | |
202 void testClearRect() { | |
203 m_testSurface->initializeCurrentFrame(); | |
204 m_testSurface->getRecord(); | |
205 PaintFlags clearPaint; | |
206 clearPaint.setBlendMode(SkBlendMode::kClear); | |
207 m_imageBuffer->canvas()->drawRect( | |
208 SkRect::MakeWH(m_testSurface->size().width(), | |
209 m_testSurface->size().height()), | |
210 clearPaint); | |
211 m_fakeImageBufferClient->fakeDraw(); | |
212 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
213 m_testSurface->getRecord(); | |
214 EXPECT_EQ(2, m_fakeImageBufferClient->frameCount()); | |
215 expectDisplayListEnabled(true); | |
216 } | |
217 | 72 |
218 void expectDisplayListEnabled(bool displayListEnabled) { | 73 void expectDisplayListEnabled(bool displayListEnabled) { |
219 EXPECT_EQ(displayListEnabled, (bool)m_testSurface->m_currentFrame.get()); | 74 EXPECT_EQ(displayListEnabled, (bool)m_testSurface->m_currentFrame.get()); |
220 EXPECT_EQ(!displayListEnabled, | 75 EXPECT_EQ(!displayListEnabled, |
221 (bool)m_testSurface->m_fallbackSurface.get()); | 76 (bool)m_testSurface->m_fallbackSurface.get()); |
222 int expectedSurfaceCreationCount = displayListEnabled ? 0 : 1; | 77 int expectedSurfaceCreationCount = displayListEnabled ? 0 : 1; |
223 EXPECT_EQ(expectedSurfaceCreationCount, | 78 EXPECT_EQ(expectedSurfaceCreationCount, |
224 m_surfaceFactory->createSurfaceCount()); | 79 m_surfaceFactory->createSurfaceCount()); |
225 } | 80 } |
226 | 81 |
227 private: | 82 private: |
228 MockSurfaceFactory* m_surfaceFactory; | 83 MockSurfaceFactory* m_surfaceFactory; |
229 RecordingImageBufferSurface* m_testSurface; | 84 RecordingImageBufferSurface* m_testSurface; |
230 std::unique_ptr<FakeImageBufferClient> m_fakeImageBufferClient; | |
231 std::unique_ptr<ImageBuffer> m_imageBuffer; | 85 std::unique_ptr<ImageBuffer> m_imageBuffer; |
232 }; | 86 }; |
233 | 87 |
234 #define CALL_TEST_TASK_WRAPPER(TEST_METHOD) \ | 88 TEST_F(RecordingImageBufferSurfaceTest, testEmptyPicture) { |
235 { \ | 89 sk_sp<SkPicture> picture = testSurface()->getRecord(); |
236 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> \ | 90 EXPECT_TRUE((bool)picture.get()); |
237 platform; \ | 91 expectDisplayListEnabled(true); |
238 Platform::current()->currentThread()->getWebTaskRunner()->postTask( \ | |
239 BLINK_FROM_HERE, \ | |
240 WTF::bind(&RecordingImageBufferSurfaceTest::TEST_METHOD, \ | |
241 WTF::unretained(this))); \ | |
242 platform->runUntilIdle(); \ | |
243 } | |
244 | |
245 TEST_F(RecordingImageBufferSurfaceTest, testEmptyRecord) { | |
246 testEmptyRecord(); | |
247 } | 92 } |
248 | 93 |
249 TEST_F(RecordingImageBufferSurfaceTest, testNoFallbackWithClear) { | 94 TEST_F(RecordingImageBufferSurfaceTest, testNoFallbackWithClear) { |
250 testNoFallbackWithClear(); | 95 testSurface()->willOverwriteCanvas(); |
| 96 testSurface()->getRecord(); |
| 97 expectDisplayListEnabled(true); |
251 } | 98 } |
252 | 99 |
253 TEST_F(RecordingImageBufferSurfaceTest, testNonAnimatedCanvasUpdate) { | 100 TEST_F(RecordingImageBufferSurfaceTest, testNonAnimatedCanvasUpdate) { |
254 CALL_TEST_TASK_WRAPPER(testNonAnimatedCanvasUpdate) | 101 // Acquire picture twice to simulate a static canvas: nothing drawn between |
| 102 // updates. |
| 103 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
| 104 testSurface()->getRecord(); |
| 105 testSurface()->getRecord(); |
255 expectDisplayListEnabled(true); | 106 expectDisplayListEnabled(true); |
256 } | 107 } |
257 | 108 |
258 TEST_F(RecordingImageBufferSurfaceTest, testAnimatedWithoutClear) { | 109 TEST_F(RecordingImageBufferSurfaceTest, testAnimatedWithoutClear) { |
259 CALL_TEST_TASK_WRAPPER(testAnimatedWithoutClear) | 110 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
260 expectDisplayListEnabled(false); | 111 testSurface()->getRecord(); |
261 } | 112 EXPECT_EQ(0, createSurfaceCount()); |
262 | 113 expectDisplayListEnabled(true); // first frame has an implicit clear |
263 TEST_F(RecordingImageBufferSurfaceTest, testFrameFinalizedByTaskObserver) { | 114 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
264 CALL_TEST_TASK_WRAPPER(testFrameFinalizedByTaskObserver1) | 115 testSurface()->getRecord(); |
265 expectDisplayListEnabled(false); | |
266 CALL_TEST_TASK_WRAPPER(testFrameFinalizedByTaskObserver2) | |
267 expectDisplayListEnabled(false); | 116 expectDisplayListEnabled(false); |
268 } | 117 } |
269 | 118 |
270 TEST_F(RecordingImageBufferSurfaceTest, testAnimatedWithClear) { | 119 TEST_F(RecordingImageBufferSurfaceTest, testAnimatedWithClear) { |
271 CALL_TEST_TASK_WRAPPER(testAnimatedWithClear) | 120 testSurface()->getRecord(); |
| 121 testSurface()->willOverwriteCanvas(); |
| 122 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
| 123 testSurface()->getRecord(); |
| 124 expectDisplayListEnabled(true); |
| 125 // clear after use |
| 126 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
| 127 testSurface()->willOverwriteCanvas(); |
| 128 testSurface()->getRecord(); |
272 expectDisplayListEnabled(true); | 129 expectDisplayListEnabled(true); |
273 } | 130 } |
274 | 131 |
275 TEST_F(RecordingImageBufferSurfaceTest, testClearRect) { | 132 TEST_F(RecordingImageBufferSurfaceTest, testClearRect) { |
276 CALL_TEST_TASK_WRAPPER(testClearRect); | 133 testSurface()->getRecord(); |
| 134 SkPaint clearPaint; |
| 135 clearPaint.setBlendMode(SkBlendMode::kClear); |
| 136 canvas()->drawRect(SkRect::MakeWH(testSurface()->size().width(), |
| 137 testSurface()->size().height()), |
| 138 clearPaint); |
| 139 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
| 140 testSurface()->getRecord(); |
277 expectDisplayListEnabled(true); | 141 expectDisplayListEnabled(true); |
278 } | 142 } |
279 | 143 |
280 } // namespace blink | 144 } // namespace blink |
OLD | NEW |