| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2011 Google Inc. All rights reserved. | 2  * Copyright (C) 2011 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  * 1.  Redistributions of source code must retain the above copyright | 7  * 1.  Redistributions of source code must retain the above copyright | 
| 8  *     notice, this list of conditions and the following disclaimer. | 8  *     notice, this list of conditions and the following disclaimer. | 
| 9  * 2.  Redistributions in binary form must reproduce the above copyright | 9  * 2.  Redistributions in binary form must reproduce the above copyright | 
| 10  *     notice, this list of conditions and the following disclaimer in the | 10  *     notice, this list of conditions and the following disclaimer in the | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 24 | 24 | 
| 25 #include "config.h" | 25 #include "config.h" | 
| 26 #include "platform/graphics/Canvas2DLayerBridge.h" | 26 #include "platform/graphics/Canvas2DLayerBridge.h" | 
| 27 | 27 | 
| 28 #include "SkSurface.h" | 28 #include "SkSurface.h" | 
| 29 #include "platform/graphics/ImageBuffer.h" | 29 #include "platform/graphics/ImageBuffer.h" | 
| 30 #include "platform/graphics/test/MockWebGraphicsContext3D.h" | 30 #include "platform/graphics/test/MockWebGraphicsContext3D.h" | 
| 31 #include "public/platform/Platform.h" | 31 #include "public/platform/Platform.h" | 
| 32 #include "public/platform/WebExternalBitmap.h" | 32 #include "public/platform/WebExternalBitmap.h" | 
| 33 #include "public/platform/WebGraphicsContext3DProvider.h" | 33 #include "public/platform/WebGraphicsContext3DProvider.h" | 
|  | 34 #include "public/platform/WebScheduler.h" | 
|  | 35 #include "public/platform/WebTaskRunner.h" | 
| 34 #include "public/platform/WebThread.h" | 36 #include "public/platform/WebThread.h" | 
|  | 37 #include "public/platform/WebTraceLocation.h" | 
| 35 #include "testing/gmock/include/gmock/gmock.h" | 38 #include "testing/gmock/include/gmock/gmock.h" | 
| 36 #include "testing/gtest/include/gtest/gtest.h" | 39 #include "testing/gtest/include/gtest/gtest.h" | 
| 37 #include "third_party/skia/include/core/SkCanvas.h" | 40 #include "third_party/skia/include/core/SkCanvas.h" | 
| 38 #include "third_party/skia/include/gpu/GrContext.h" | 41 #include "third_party/skia/include/gpu/GrContext.h" | 
| 39 #include "third_party/skia/include/gpu/gl/SkNullGLContext.h" | 42 #include "third_party/skia/include/gpu/gl/SkNullGLContext.h" | 
| 40 #include "wtf/RefPtr.h" | 43 #include "wtf/RefPtr.h" | 
| 41 | 44 | 
| 42 using testing::InSequence; | 45 using testing::InSequence; | 
| 43 using testing::Return; | 46 using testing::Return; | 
| 44 using testing::Test; | 47 using testing::Test; | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 74         return m_grContext.get(); | 77         return m_grContext.get(); | 
| 75     } | 78     } | 
| 76 | 79 | 
| 77 private: | 80 private: | 
| 78     WebGraphicsContext3D* m_context3d; | 81     WebGraphicsContext3D* m_context3d; | 
| 79     RefPtr<GrContext> m_grContext; | 82     RefPtr<GrContext> m_grContext; | 
| 80 }; | 83 }; | 
| 81 | 84 | 
| 82 class Canvas2DLayerBridgePtr { | 85 class Canvas2DLayerBridgePtr { | 
| 83 public: | 86 public: | 
|  | 87     Canvas2DLayerBridgePtr() { } | 
| 84     Canvas2DLayerBridgePtr(PassRefPtr<Canvas2DLayerBridge> layerBridge) | 88     Canvas2DLayerBridgePtr(PassRefPtr<Canvas2DLayerBridge> layerBridge) | 
| 85         : m_layerBridge(layerBridge) { } | 89         : m_layerBridge(layerBridge) { } | 
| 86 | 90 | 
| 87     ~Canvas2DLayerBridgePtr() | 91     ~Canvas2DLayerBridgePtr() | 
| 88     { | 92     { | 
| 89         m_layerBridge->beginDestruction(); | 93         clear(); | 
|  | 94     } | 
|  | 95 | 
|  | 96     void clear() | 
|  | 97     { | 
|  | 98         if (m_layerBridge) { | 
|  | 99             m_layerBridge->beginDestruction(); | 
|  | 100             m_layerBridge.clear(); | 
|  | 101         } | 
|  | 102     } | 
|  | 103 | 
|  | 104     void operator=(PassRefPtr<Canvas2DLayerBridge> layerBridge) | 
|  | 105     { | 
|  | 106         ASSERT(!m_layerBridge); | 
|  | 107         m_layerBridge = layerBridge; | 
| 90     } | 108     } | 
| 91 | 109 | 
| 92     Canvas2DLayerBridge* operator->() { return m_layerBridge.get(); } | 110     Canvas2DLayerBridge* operator->() { return m_layerBridge.get(); } | 
| 93     Canvas2DLayerBridge* get() { return m_layerBridge.get(); } | 111     Canvas2DLayerBridge* get() { return m_layerBridge.get(); } | 
| 94 | 112 | 
| 95 private: | 113 private: | 
| 96     RefPtr<Canvas2DLayerBridge> m_layerBridge; | 114     RefPtr<Canvas2DLayerBridge> m_layerBridge; | 
| 97 }; | 115 }; | 
| 98 | 116 | 
| 99 class NullWebExternalBitmap : public WebExternalBitmap { | 117 class NullWebExternalBitmap : public WebExternalBitmap { | 
| 100 public: | 118 public: | 
| 101     WebSize size() override | 119     WebSize size() override | 
| 102     { | 120     { | 
| 103         return WebSize(); | 121         return WebSize(); | 
| 104     } | 122     } | 
| 105 | 123 | 
| 106     void setSize(WebSize) override | 124     void setSize(WebSize) override | 
| 107     { | 125     { | 
| 108     } | 126     } | 
| 109 | 127 | 
| 110     uint8* pixels() override | 128     uint8* pixels() override | 
| 111     { | 129     { | 
| 112         return nullptr; | 130         return nullptr; | 
| 113     } | 131     } | 
| 114 }; | 132 }; | 
| 115 | 133 | 
| 116 } // anonymous namespace | 134 } // anonymous namespace | 
| 117 | 135 | 
| 118 class Canvas2DLayerBridgeTest : public Test { | 136 class Canvas2DLayerBridgeTest : public Test { | 
|  | 137 public: | 
|  | 138     PassRefPtr<Canvas2DLayerBridge> makeBridge(PassOwnPtr<MockWebGraphicsContext
     3DProvider> provider, const IntSize& size, Canvas2DLayerBridge::AccelerationMode
      accelerationMode) | 
|  | 139     { | 
|  | 140         return adoptRef(new Canvas2DLayerBridge(provider, size, 0, NonOpaque, ac
     celerationMode)); | 
|  | 141     } | 
|  | 142 | 
| 119 protected: | 143 protected: | 
| 120     void fullLifecycleTest() | 144     void fullLifecycleTest() | 
| 121     { | 145     { | 
| 122         MockCanvasContext mainMock; | 146         MockCanvasContext mainMock; | 
| 123         OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new
      MockWebGraphicsContext3DProvider(&mainMock)); | 147         OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new
      MockWebGraphicsContext3DProvider(&mainMock)); | 
| 124 | 148 | 
| 125         ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 149         ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
| 126 | 150 | 
| 127         { | 151         { | 
| 128             Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainM
     ockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::Dis
     ableAcceleration))); | 152             Canvas2DLayerBridgePtr bridge(adoptRef(new Canvas2DLayerBridge(mainM
     ockProvider.release(), IntSize(300, 150), 0, NonOpaque, Canvas2DLayerBridge::Dis
     ableAcceleration))); | 
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 329 TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareIfContextLost) | 353 TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareIfContextLost) | 
| 330 { | 354 { | 
| 331     fallbackToSoftwareIfContextLost(); | 355     fallbackToSoftwareIfContextLost(); | 
| 332 } | 356 } | 
| 333 | 357 | 
| 334 TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareOnFailedTextureAlloc) | 358 TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareOnFailedTextureAlloc) | 
| 335 { | 359 { | 
| 336     fallbackToSoftwareOnFailedTextureAlloc(); | 360     fallbackToSoftwareOnFailedTextureAlloc(); | 
| 337 } | 361 } | 
| 338 | 362 | 
|  | 363 class MockLogger : public Canvas2DLayerBridge::Logger { | 
|  | 364 public: | 
|  | 365     MOCK_METHOD1(reportHibernationEvent, void(Canvas2DLayerBridge::HibernationEv
     ent)); | 
|  | 366     MOCK_METHOD0(didStartHibernating, void()); | 
|  | 367     virtual ~MockLogger() { } | 
|  | 368 }; | 
|  | 369 | 
|  | 370 | 
|  | 371 class CreateBridgeTask : public WebTaskRunner::Task { | 
|  | 372 public: | 
|  | 373     CreateBridgeTask(Canvas2DLayerBridgePtr* bridgePtr, MockCanvasContext* mockC
     anvasContext, Canvas2DLayerBridgeTest* testHost, WebWaitableEvent* doneEvent) | 
|  | 374         : m_bridgePtr(bridgePtr) | 
|  | 375         , m_mockCanvasContext(mockCanvasContext) | 
|  | 376         , m_testHost(testHost) | 
|  | 377         , m_doneEvent(doneEvent) | 
|  | 378     { } | 
|  | 379 | 
|  | 380     virtual ~CreateBridgeTask() { } | 
|  | 381 | 
|  | 382     void run() override | 
|  | 383     { | 
|  | 384         OwnPtr<MockWebGraphicsContext3DProvider> mainMockProvider = adoptPtr(new
      MockWebGraphicsContext3DProvider(m_mockCanvasContext)); | 
|  | 385         *m_bridgePtr = m_testHost->makeBridge(mainMockProvider.release(), IntSiz
     e(300, 300), Canvas2DLayerBridge::EnableAcceleration); | 
|  | 386         // draw+flush to trigger the creation of a GPU surface | 
|  | 387         (*m_bridgePtr)->didDraw(FloatRect(0, 0, 1, 1)); | 
|  | 388         (*m_bridgePtr)->finalizeFrame(FloatRect(0, 0, 1, 1)); | 
|  | 389         (*m_bridgePtr)->flush(); | 
|  | 390         m_doneEvent->signal(); | 
|  | 391     } | 
|  | 392 | 
|  | 393 private: | 
|  | 394     Canvas2DLayerBridgePtr* m_bridgePtr; | 
|  | 395     MockCanvasContext* m_mockCanvasContext; | 
|  | 396     Canvas2DLayerBridgeTest* m_testHost; | 
|  | 397     WebWaitableEvent* m_doneEvent; | 
|  | 398 }; | 
|  | 399 | 
|  | 400 class DestroyBridgeTask : public WebTaskRunner::Task { | 
|  | 401 public: | 
|  | 402     DestroyBridgeTask(Canvas2DLayerBridgePtr* bridgePtr, WebWaitableEvent* doneE
     vent = nullptr) | 
|  | 403         : m_bridgePtr(bridgePtr) | 
|  | 404         , m_doneEvent(doneEvent) | 
|  | 405     { } | 
|  | 406 | 
|  | 407     virtual ~DestroyBridgeTask() { } | 
|  | 408 | 
|  | 409     void run() override | 
|  | 410     { | 
|  | 411         m_bridgePtr->clear(); | 
|  | 412         if (m_doneEvent) | 
|  | 413             m_doneEvent->signal(); | 
|  | 414     } | 
|  | 415 | 
|  | 416 private: | 
|  | 417     Canvas2DLayerBridgePtr* m_bridgePtr; | 
|  | 418     WebWaitableEvent* m_doneEvent; | 
|  | 419 }; | 
|  | 420 | 
|  | 421 class SetIsHiddenTask : public WebTaskRunner::Task { | 
|  | 422 public: | 
|  | 423     SetIsHiddenTask(Canvas2DLayerBridge* bridge, bool value, WebWaitableEvent* d
     oneEvent = nullptr) | 
|  | 424         : m_bridge(bridge) | 
|  | 425         , m_value(value) | 
|  | 426         , m_doneEvent(doneEvent) | 
|  | 427     { } | 
|  | 428 | 
|  | 429     virtual ~SetIsHiddenTask() { } | 
|  | 430 | 
|  | 431     void run() override | 
|  | 432     { | 
|  | 433         m_bridge->setIsHidden(m_value); | 
|  | 434         if (m_doneEvent) | 
|  | 435             m_doneEvent->signal(); | 
|  | 436     } | 
|  | 437 | 
|  | 438 private: | 
|  | 439     Canvas2DLayerBridge* m_bridge; | 
|  | 440     bool m_value; | 
|  | 441     WebWaitableEvent* m_doneEvent; | 
|  | 442 }; | 
|  | 443 | 
|  | 444 TEST_F(Canvas2DLayerBridgeTest, HibernationLifeCycle) | 
|  | 445 { | 
|  | 446     MockCanvasContext mainMock; | 
|  | 447     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 448 | 
|  | 449     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 450     // to avoid WeakPtr thread check issues. | 
|  | 451     Canvas2DLayerBridgePtr bridge; | 
|  | 452     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 453     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 454     bridgeCreatedEvent->wait(); | 
|  | 455 | 
|  | 456     // Register an alternate Logger for tracking hibernation events | 
|  | 457     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 458     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 459     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 460 | 
|  | 461     // Test entering hibernation | 
|  | 462     OwnPtr<WebWaitableEvent> hibernationStartedEvent = adoptPtr(Platform::curren
     t()->createWaitableEvent()); | 
|  | 463     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 464     EXPECT_CALL(*mockLoggerPtr, didStartHibernating()) | 
|  | 465         .WillOnce(testing::Invoke(hibernationStartedEvent.get(), &WebWaitableEve
     nt::signal)); | 
|  | 466     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true)); | 
|  | 467     hibernationStartedEvent->wait(); | 
|  | 468     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 469     EXPECT_FALSE(bridge->isAccelerated()); | 
|  | 470     EXPECT_TRUE(bridge->isHibernating()); | 
|  | 471 | 
|  | 472     // Test exiting hibernation | 
|  | 473     OwnPtr<WebWaitableEvent> hibernationEndedEvent = adoptPtr(Platform::current(
     )->createWaitableEvent()); | 
|  | 474     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationEndedNormally)); | 
|  | 475     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), false, hibernationEndedEvent.get())); | 
|  | 476     hibernationEndedEvent->wait(); | 
|  | 477     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 478     EXPECT_TRUE(bridge->isAccelerated()); | 
|  | 479     EXPECT_FALSE(bridge->isHibernating()); | 
|  | 480 | 
|  | 481     // Tear down the bridge on the thread so that 'bridge' can go out of scope | 
|  | 482     // without crashing due to thread checks | 
|  | 483     OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()
     ->createWaitableEvent()); | 
|  | 484     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge, bridgeDestroyedEvent.get())); | 
|  | 485     bridgeDestroyedEvent->wait(); | 
|  | 486 | 
|  | 487     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 488 } | 
|  | 489 | 
|  | 490 class RenderingTask : public WebTaskRunner::Task { | 
|  | 491 public: | 
|  | 492     RenderingTask(Canvas2DLayerBridge* bridge, WebWaitableEvent* doneEvent) | 
|  | 493         : m_bridge(bridge) | 
|  | 494         , m_doneEvent(doneEvent) | 
|  | 495     { } | 
|  | 496 | 
|  | 497     virtual ~RenderingTask() { } | 
|  | 498 | 
|  | 499     void run() override | 
|  | 500     { | 
|  | 501         m_bridge->didDraw(FloatRect(0, 0, 1, 1)); | 
|  | 502         m_bridge->finalizeFrame(FloatRect(0, 0, 1, 1)); | 
|  | 503         m_bridge->flush(); | 
|  | 504         m_doneEvent->signal(); | 
|  | 505     } | 
|  | 506 | 
|  | 507 private: | 
|  | 508     Canvas2DLayerBridge* m_bridge; | 
|  | 509     WebWaitableEvent* m_doneEvent; | 
|  | 510 }; | 
|  | 511 | 
|  | 512 TEST_F(Canvas2DLayerBridgeTest, BackgroundRenderingWhileHibernating) | 
|  | 513 { | 
|  | 514     MockCanvasContext mainMock; | 
|  | 515     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 516 | 
|  | 517     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 518     // to avoid WeakPtr thread check issues. | 
|  | 519     Canvas2DLayerBridgePtr bridge; | 
|  | 520     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 521     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 522     bridgeCreatedEvent->wait(); | 
|  | 523 | 
|  | 524     // Register an alternate Logger for tracking hibernation events | 
|  | 525     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 526     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 527     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 528 | 
|  | 529     // Test entering hibernation | 
|  | 530     OwnPtr<WebWaitableEvent> hibernationStartedEvent = adoptPtr(Platform::curren
     t()->createWaitableEvent()); | 
|  | 531     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 532     EXPECT_CALL(*mockLoggerPtr, didStartHibernating()) | 
|  | 533         .WillOnce(testing::Invoke(hibernationStartedEvent.get(), &WebWaitableEve
     nt::signal)); | 
|  | 534     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true)); | 
|  | 535     hibernationStartedEvent->wait(); | 
|  | 536     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 537     EXPECT_FALSE(bridge->isAccelerated()); | 
|  | 538     EXPECT_TRUE(bridge->isHibernating()); | 
|  | 539 | 
|  | 540     // Rendering in the background -> temp switch to SW | 
|  | 541     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationEndedWithSwitchToBackgroundRendering)); | 
|  | 542     OwnPtr<WebWaitableEvent> switchEvent = adoptPtr(Platform::current()->createW
     aitableEvent()); | 
|  | 543     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new RenderingTask(bridge
     .get(), switchEvent.get())); | 
|  | 544     switchEvent->wait(); | 
|  | 545     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 546     EXPECT_FALSE(bridge->isAccelerated()); | 
|  | 547     EXPECT_FALSE(bridge->isHibernating()); | 
|  | 548 | 
|  | 549     // Unhide | 
|  | 550     OwnPtr<WebWaitableEvent> unhideEvent = adoptPtr(Platform::current()->createW
     aitableEvent()); | 
|  | 551     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), false, unhideEvent.get())); | 
|  | 552     unhideEvent->wait(); | 
|  | 553     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 554     EXPECT_TRUE(bridge->isAccelerated()); // Becoming visible causes switch back
      to GPU | 
|  | 555     EXPECT_FALSE(bridge->isHibernating()); | 
|  | 556 | 
|  | 557     // Tear down the bridge on the thread so that 'bridge' can go out of scope | 
|  | 558     // without crashing due to thread checks | 
|  | 559     OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()
     ->createWaitableEvent()); | 
|  | 560     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge, bridgeDestroyedEvent.get())); | 
|  | 561     bridgeDestroyedEvent->wait(); | 
|  | 562 | 
|  | 563     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 564 } | 
|  | 565 | 
|  | 566 TEST_F(Canvas2DLayerBridgeTest, TeardownWhileHibernating) | 
|  | 567 { | 
|  | 568     MockCanvasContext mainMock; | 
|  | 569     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 570 | 
|  | 571     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 572     // to avoid WeakPtr thread check issues. | 
|  | 573     Canvas2DLayerBridgePtr bridge; | 
|  | 574     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 575     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 576     bridgeCreatedEvent->wait(); | 
|  | 577 | 
|  | 578     // Register an alternate Logger for tracking hibernation events | 
|  | 579     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 580     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 581     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 582 | 
|  | 583     // Test entering hibernation | 
|  | 584     OwnPtr<WebWaitableEvent> hibernationStartedEvent = adoptPtr(Platform::curren
     t()->createWaitableEvent()); | 
|  | 585     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 586     EXPECT_CALL(*mockLoggerPtr, didStartHibernating()) | 
|  | 587         .WillOnce(testing::Invoke(hibernationStartedEvent.get(), &WebWaitableEve
     nt::signal)); | 
|  | 588     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true)); | 
|  | 589     hibernationStartedEvent->wait(); | 
|  | 590     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 591     EXPECT_FALSE(bridge->isAccelerated()); | 
|  | 592     EXPECT_TRUE(bridge->isHibernating()); | 
|  | 593 | 
|  | 594     // Tear down the bridge while hibernating | 
|  | 595     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationEndedWithTeardown)); | 
|  | 596     OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()
     ->createWaitableEvent()); | 
|  | 597     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge, bridgeDestroyedEvent.get())); | 
|  | 598     bridgeDestroyedEvent->wait(); | 
|  | 599 | 
|  | 600     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 601 } | 
|  | 602 | 
|  | 603 class IdleFenceTask : public WebThread::IdleTask { | 
|  | 604 public: | 
|  | 605     IdleFenceTask(WebWaitableEvent* doneEvent) | 
|  | 606         : m_doneEvent(doneEvent) | 
|  | 607     { } | 
|  | 608 | 
|  | 609     virtual ~IdleFenceTask() { } | 
|  | 610 | 
|  | 611     void run(double /*deadline*/) override | 
|  | 612     { | 
|  | 613         m_doneEvent->signal(); | 
|  | 614     } | 
|  | 615 | 
|  | 616 private: | 
|  | 617     WebWaitableEvent* m_doneEvent; | 
|  | 618 }; | 
|  | 619 | 
|  | 620 TEST_F(Canvas2DLayerBridgeTest, TeardownWhileHibernationIsPending) | 
|  | 621 { | 
|  | 622     MockCanvasContext mainMock; | 
|  | 623     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 624 | 
|  | 625     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 626     // to avoid WeakPtr thread check issues. | 
|  | 627     Canvas2DLayerBridgePtr bridge; | 
|  | 628     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 629     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 630     bridgeCreatedEvent->wait(); | 
|  | 631 | 
|  | 632     // Register an alternate Logger for tracking hibernation events | 
|  | 633     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 634     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 635     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 636 | 
|  | 637     // Test entering hibernation | 
|  | 638     OwnPtr<WebWaitableEvent> hibernationScheduledEvent = adoptPtr(Platform::curr
     ent()->createWaitableEvent()); | 
|  | 639     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 640     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true, hibernationScheduledEvent.get())); | 
|  | 641     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge)); | 
|  | 642     // In production, we would expect a | 
|  | 643     // HibernationAbortedDueToDestructionWhileHibernatePending event to be | 
|  | 644     // fired, but that signal is lost in the unit test due to no longer having | 
|  | 645     // a bridge to hold the mockLogger. | 
|  | 646     hibernationScheduledEvent->wait(); | 
|  | 647     // Once we know the hibernation task is scheduled, we can schedule a fence. | 
|  | 648     // Assuming Idle tasks are guaranteed to run in the order they were | 
|  | 649     // submitted, this fence will guarantee the attempt to hibernate runs to | 
|  | 650     // completion before the thread is destroyed. | 
|  | 651     // This test passes by not crashing, which proves that the WeakPtr logic | 
|  | 652     // is sound. | 
|  | 653     OwnPtr<WebWaitableEvent> fenceEvent = adoptPtr(Platform::current()->createWa
     itableEvent()); | 
|  | 654     testThread->scheduler()->postIdleTask(BLINK_FROM_HERE, new IdleFenceTask(fen
     ceEvent.get())); | 
|  | 655     fenceEvent->wait(); | 
|  | 656 | 
|  | 657     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 658 } | 
|  | 659 | 
|  | 660 class BeginDestroyBridgeTask : public WebTaskRunner::Task { | 
|  | 661 public: | 
|  | 662     BeginDestroyBridgeTask(Canvas2DLayerBridge* bridge) | 
|  | 663         : m_bridge(bridge) | 
|  | 664     { } | 
|  | 665 | 
|  | 666     virtual ~BeginDestroyBridgeTask() { } | 
|  | 667 | 
|  | 668     void run() override | 
|  | 669     { | 
|  | 670         m_bridge->beginDestruction(); | 
|  | 671     } | 
|  | 672 | 
|  | 673 private: | 
|  | 674     Canvas2DLayerBridge* m_bridge; | 
|  | 675 }; | 
|  | 676 | 
|  | 677 TEST_F(Canvas2DLayerBridgeTest, HibernationAbortedDueToPendingTeardown) | 
|  | 678 { | 
|  | 679     MockCanvasContext mainMock; | 
|  | 680     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 681 | 
|  | 682     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 683     // to avoid WeakPtr thread check issues. | 
|  | 684     Canvas2DLayerBridgePtr bridge; | 
|  | 685     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 686     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 687     bridgeCreatedEvent->wait(); | 
|  | 688 | 
|  | 689     // Register an alternate Logger for tracking hibernation events | 
|  | 690     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 691     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 692     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 693 | 
|  | 694     // Test entering hibernation | 
|  | 695     OwnPtr<WebWaitableEvent> hibernationAbortedEvent = adoptPtr(Platform::curren
     t()->createWaitableEvent()); | 
|  | 696     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 697     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationAbortedDueToPendingDestruction)) | 
|  | 698         .WillOnce(testing::InvokeWithoutArgs(hibernationAbortedEvent.get(), &Web
     WaitableEvent::signal)); | 
|  | 699     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true)); | 
|  | 700     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new BeginDestroyBridgeTa
     sk(bridge.get())); | 
|  | 701     hibernationAbortedEvent->wait(); | 
|  | 702 | 
|  | 703     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 704 | 
|  | 705     // Tear down bridge on thread | 
|  | 706     OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()
     ->createWaitableEvent()); | 
|  | 707     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge, bridgeDestroyedEvent.get())); | 
|  | 708     bridgeDestroyedEvent->wait(); | 
|  | 709 | 
|  | 710     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 711 } | 
|  | 712 | 
|  | 713 TEST_F(Canvas2DLayerBridgeTest, HibernationAbortedDueToVisibilityChange) | 
|  | 714 { | 
|  | 715     MockCanvasContext mainMock; | 
|  | 716     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 717 | 
|  | 718     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 719     // to avoid WeakPtr thread check issues. | 
|  | 720     Canvas2DLayerBridgePtr bridge; | 
|  | 721     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 722     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 723     bridgeCreatedEvent->wait(); | 
|  | 724 | 
|  | 725     // Register an alternate Logger for tracking hibernation events | 
|  | 726     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 727     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 728     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 729 | 
|  | 730     // Test entering hibernation | 
|  | 731     OwnPtr<WebWaitableEvent> hibernationAbortedEvent = adoptPtr(Platform::curren
     t()->createWaitableEvent()); | 
|  | 732     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 733     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationAbortedDueToVisibilityChange)) | 
|  | 734         .WillOnce(testing::InvokeWithoutArgs(hibernationAbortedEvent.get(), &Web
     WaitableEvent::signal)); | 
|  | 735     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true)); | 
|  | 736     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), false)); | 
|  | 737     hibernationAbortedEvent->wait(); | 
|  | 738     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 739     EXPECT_TRUE(bridge->isAccelerated()); | 
|  | 740     EXPECT_FALSE(bridge->isHibernating()); | 
|  | 741 | 
|  | 742     // Tear down the bridge on the thread so that 'bridge' can go out of scope | 
|  | 743     // without crashing due to thread checks | 
|  | 744     OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()
     ->createWaitableEvent()); | 
|  | 745     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge, bridgeDestroyedEvent.get())); | 
|  | 746     bridgeDestroyedEvent->wait(); | 
|  | 747 | 
|  | 748     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 749 } | 
|  | 750 | 
|  | 751 TEST_F(Canvas2DLayerBridgeTest, HibernationAbortedDueToLostContext) | 
|  | 752 { | 
|  | 753     MockCanvasContext mainMock; | 
|  | 754     OwnPtr<WebThread> testThread = adoptPtr(Platform::current()->createThread("T
     estThread")); | 
|  | 755 | 
|  | 756     // The Canvas2DLayerBridge has to be created on the thread that will use it | 
|  | 757     // to avoid WeakPtr thread check issues. | 
|  | 758     Canvas2DLayerBridgePtr bridge; | 
|  | 759     OwnPtr<WebWaitableEvent> bridgeCreatedEvent = adoptPtr(Platform::current()->
     createWaitableEvent()); | 
|  | 760     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new CreateBridgeTask(&br
     idge, &mainMock, this, bridgeCreatedEvent.get())); | 
|  | 761     bridgeCreatedEvent->wait(); | 
|  | 762 | 
|  | 763     // Register an alternate Logger for tracking hibernation events | 
|  | 764     OwnPtr<MockLogger> mockLogger = adoptPtr(new MockLogger); | 
|  | 765     MockLogger* mockLoggerPtr = mockLogger.get(); | 
|  | 766     bridge->setLoggerForTesting(mockLogger.release()); | 
|  | 767 | 
|  | 768     mainMock.fakeContextLost(); | 
|  | 769     // Test entering hibernation | 
|  | 770     OwnPtr<WebWaitableEvent> hibernationAbortedEvent = adoptPtr(Platform::curren
     t()->createWaitableEvent()); | 
|  | 771     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationScheduled)); | 
|  | 772     EXPECT_CALL(*mockLoggerPtr, reportHibernationEvent(Canvas2DLayerBridge::Hibe
     rnationAbortedDueGpuContextLoss)) | 
|  | 773         .WillOnce(testing::InvokeWithoutArgs(hibernationAbortedEvent.get(), &Web
     WaitableEvent::signal)); | 
|  | 774     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new SetIsHiddenTask(brid
     ge.get(), true)); | 
|  | 775     hibernationAbortedEvent->wait(); | 
|  | 776     ::testing::Mock::VerifyAndClearExpectations(mockLoggerPtr); | 
|  | 777     EXPECT_FALSE(bridge->isHibernating()); | 
|  | 778 | 
|  | 779     // Tear down the bridge on the thread so that 'bridge' can go out of scope | 
|  | 780     // without crashing due to thread checks | 
|  | 781     OwnPtr<WebWaitableEvent> bridgeDestroyedEvent = adoptPtr(Platform::current()
     ->createWaitableEvent()); | 
|  | 782     testThread->taskRunner()->postTask(BLINK_FROM_HERE, new DestroyBridgeTask(&b
     ridge, bridgeDestroyedEvent.get())); | 
|  | 783     bridgeDestroyedEvent->wait(); | 
|  | 784 | 
|  | 785     ::testing::Mock::VerifyAndClearExpectations(&mainMock); | 
|  | 786 } | 
|  | 787 | 
| 339 } // namespace blink | 788 } // namespace blink | 
| OLD | NEW | 
|---|