| 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/testing/TestingPlatformSupport.h" | 12 #include "platform/testing/TestingPlatformSupport.h" |
| 13 #include "public/platform/Platform.h" | 13 #include "public/platform/Platform.h" |
| 14 #include "public/platform/WebThread.h" | 14 #include "public/platform/WebThread.h" |
| 15 #include "public/platform/WebTraceLocation.h" | 15 #include "public/platform/WebTraceLocation.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #include "third_party/skia/include/core/SkCanvas.h" | 18 #include "third_party/skia/include/core/SkCanvas.h" |
| 19 #include "third_party/skia/include/core/SkPictureRecorder.h" | 19 #include "third_party/skia/include/core/SkPictureRecorder.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(SkCanvas*) 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 testEmptyPicture() { | 69 RecordingImageBufferSurface* testSurface() { return m_testSurface; } |
| 117 m_testSurface->initializeCurrentFrame(); | 70 int createSurfaceCount() { return m_surfaceFactory->createSurfaceCount(); } |
| 118 sk_sp<SkPicture> picture = m_testSurface->getPicture(); | 71 SkCanvas* canvas() { return m_imageBuffer->canvas(); } |
| 119 EXPECT_TRUE((bool)picture.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->getPicture(); | |
| 128 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
| 129 expectDisplayListEnabled(true); | |
| 130 } | |
| 131 | |
| 132 void testNonAnimatedCanvasUpdate() { | |
| 133 m_testSurface->initializeCurrentFrame(); | |
| 134 // Acquire picture twice to simulate a static canvas: nothing drawn between | |
| 135 // updates. | |
| 136 m_fakeImageBufferClient->fakeDraw(); | |
| 137 m_testSurface->getPicture(); | |
| 138 m_testSurface->getPicture(); | |
| 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->getPicture(); | |
| 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->getPicture(); | |
| 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->getPicture(); | |
| 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->getPicture(); | |
| 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->getPicture(); | |
| 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->getPicture(); | |
| 187 m_testSurface->willOverwriteCanvas(); | |
| 188 m_fakeImageBufferClient->fakeDraw(); | |
| 189 EXPECT_EQ(1, m_fakeImageBufferClient->frameCount()); | |
| 190 m_testSurface->getPicture(); | |
| 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->getPicture(); | |
| 198 EXPECT_EQ(3, m_fakeImageBufferClient->frameCount()); | |
| 199 expectDisplayListEnabled(true); | |
| 200 } | |
| 201 | |
| 202 void testClearRect() { | |
| 203 m_testSurface->initializeCurrentFrame(); | |
| 204 m_testSurface->getPicture(); | |
| 205 SkPaint 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->getPicture(); | |
| 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) \ | |
| 235 { \ | |
| 236 ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> \ | |
| 237 platform; \ | |
| 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, testEmptyPicture) { | 88 TEST_F(RecordingImageBufferSurfaceTest, testEmptyPicture) { |
| 246 testEmptyPicture(); | 89 sk_sp<SkPicture> picture = testSurface()->getPicture(); |
| 90 EXPECT_TRUE((bool)picture.get()); |
| 91 expectDisplayListEnabled(true); |
| 247 } | 92 } |
| 248 | 93 |
| 249 TEST_F(RecordingImageBufferSurfaceTest, testNoFallbackWithClear) { | 94 TEST_F(RecordingImageBufferSurfaceTest, testNoFallbackWithClear) { |
| 250 testNoFallbackWithClear(); | 95 testSurface()->willOverwriteCanvas(); |
| 96 testSurface()->getPicture(); |
| 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()->getPicture(); |
| 105 testSurface()->getPicture(); |
| 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()->getPicture(); |
| 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()->getPicture(); |
| 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()->getPicture(); |
| 121 testSurface()->willOverwriteCanvas(); |
| 122 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
| 123 testSurface()->getPicture(); |
| 124 expectDisplayListEnabled(true); |
| 125 // clear after use |
| 126 testSurface()->didDraw(FloatRect(0, 0, 1, 1)); |
| 127 testSurface()->willOverwriteCanvas(); |
| 128 testSurface()->getPicture(); |
| 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()->getPicture(); |
| 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()->getPicture(); |
| 277 expectDisplayListEnabled(true); | 141 expectDisplayListEnabled(true); |
| 278 } | 142 } |
| 279 | 143 |
| 280 } // namespace blink | 144 } // namespace blink |
| OLD | NEW |