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 |