Index: third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
index 8e99446dee9e8ad1b9c2214f17fc9ed79f334952..cc665a95d8e4f433b589de568dec396d959d7603 100644 |
--- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp |
@@ -42,11 +42,16 @@ |
#include "core/animation/animatable/AnimatableTransform.h" |
#include "core/animation/animatable/AnimatableValueTestHelper.h" |
#include "core/dom/Document.h" |
+#include "core/layout/LayoutBox.h" |
#include "core/layout/LayoutObject.h" |
+#include "core/loader/EmptyClients.h" |
+#include "core/paint/PaintLayer.h" |
#include "core/testing/DummyPageHolder.h" |
#include "platform/geometry/FloatBox.h" |
#include "platform/geometry/IntSize.h" |
#include "platform/graphics/filters/FilterOperations.h" |
+#include "platform/graphics/paint/PaintArtifact.h" |
+#include "platform/graphics/test/FakeGraphicsLayerFactory.h" |
#include "platform/transforms/TransformOperations.h" |
#include "platform/transforms/TranslateTransformOperation.h" |
#include "public/platform/WebCompositorAnimation.h" |
@@ -65,6 +70,15 @@ using ::testing::Ref; |
using ::testing::Return; |
using ::testing::_; |
+class MockChromeClient : public EmptyChromeClient { |
+public: |
+ MockChromeClient() {} |
+ GraphicsLayerFactory* graphicsLayerFactory() const override |
+ { |
+ return FakeGraphicsLayerFactory::instance(); |
+ } |
+}; |
+ |
class AnimationCompositorAnimationsTest : public AnimationCompositorAnimationsTestBase { |
protected: |
RefPtr<TimingFunction> m_linearTimingFunction; |
@@ -82,11 +96,14 @@ protected: |
RefPtrWillBePersistent<Document> m_document; |
RefPtrWillBePersistent<Element> m_element; |
Persistent<AnimationTimeline> m_timeline; |
+ OwnPtrWillBePersistent<MockChromeClient> m_chromeClient; |
OwnPtr<DummyPageHolder> m_pageHolder; |
WebCompositorSupportMock m_mockCompositor; |
virtual void SetUp() |
{ |
+ m_chromeClient = adoptPtrWillBeNoop(new MockChromeClient); |
+ |
AnimationCompositorAnimationsTestBase::SetUp(); |
setCompositorForTesting(m_mockCompositor); |
@@ -111,7 +128,12 @@ protected: |
EXPECT_CALL(m_mockCompositor, createAnimationTimeline()) |
.WillOnce(Return(new WebCompositorAnimationTimelineMock())); |
} |
- m_pageHolder = DummyPageHolder::create(); |
+ |
+ Page::PageClients clients; |
+ fillWithEmptyClients(clients); |
+ clients.chromeClient = m_chromeClient.get(); |
+ m_pageHolder = DummyPageHolder::create(IntSize(), &clients); |
+ |
m_document = &m_pageHolder->document(); |
m_document->animationClock().resetTimeForTesting(); |
@@ -264,11 +286,38 @@ public: |
m_document->compositorPendingAnimations().update(false); |
m_timeline->serviceAnimations(TimingUpdateForAnimationFrame); |
} |
+ |
+ void preCommit(Animation* animation) |
+ { |
+ WebFloatAnimationCurveMock* mockCurvePtr = new WebFloatAnimationCurveMock; |
+ ExpectationSet usesMockCurve; |
+ EXPECT_CALL(m_mockCompositor, createFloatAnimationCurve()) |
+ .WillOnce(Return(mockCurvePtr)); |
+ |
+ WebCompositorAnimationMock* mockAnimationPtr = new WebCompositorAnimationMock(WebCompositorAnimation::TargetPropertyOpacity); |
+ EXPECT_CALL(m_mockCompositor, createAnimation(Ref(*mockCurvePtr), WebCompositorAnimation::TargetPropertyOpacity, _, _)) |
+ .WillOnce(Return(mockAnimationPtr)); |
+ |
+ if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) { |
+ EXPECT_TRUE(m_timeline->compositorTimeline()); |
+ EXPECT_CALL(m_mockCompositor, createAnimationPlayer()) |
+ .WillOnce(Return(new WebCompositorAnimationPlayerMock())); |
+ } |
+ |
+ const int compositorGroup = 1; |
+ DisableCompositingQueryAsserts disabler; |
+ EXPECT_TRUE(animation->preCommit(compositorGroup, true)); |
+ |
+ if (RuntimeEnabledFeatures::compositorAnimationTimelinesEnabled()) |
+ EXPECT_TRUE(animation->compositorPlayer()); |
+ |
+ EXPECT_TRUE(animation->hasActiveAnimationsOnCompositor()); |
+ } |
}; |
-class LayoutObjectProxy : public LayoutObject { |
+class LayoutObjectProxy : public LayoutBox { |
public: |
- static LayoutObjectProxy* create(Node* node) |
+ static LayoutObjectProxy* create(ContainerNode* node) |
{ |
return new LayoutObjectProxy(node); |
} |
@@ -279,12 +328,27 @@ public: |
} |
const char* name() const override { return nullptr; } |
- void layout() override { } |
+ |
+ void createCompositedLayer() |
+ { |
+ RefPtr<ComputedStyle> computedStyle = ComputedStyle::create(); |
+ styleWillChange(StyleDifference(), *computedStyle.get()); |
+ setStyle(computedStyle); |
+ styleDidChange(StyleDifference(), nullptr); |
+ |
+ DisableCompositingQueryAsserts disabler; |
+ layer()->ensureCompositedLayerMapping(); |
+ } |
private: |
- explicit LayoutObjectProxy(Node* node) |
- : LayoutObject(node) |
+ explicit LayoutObjectProxy(ContainerNode* node) |
+ : LayoutBox(node) |
+ { |
+ } |
+ |
+ PaintLayerType layerTypeRequired() const override |
{ |
+ return NormalPaintLayer; |
} |
}; |
@@ -1175,12 +1239,51 @@ TEST_F(AnimationCompositorAnimationsTest, createSimpleOpacityAnimationWithTiming |
result[0].clear(); |
} |
+TEST_F(AnimationCompositorAnimationsTest, CancelCompositorAnimationIfAnimationDisposed) |
+{ |
+ RefPtrWillBePersistent<Element> element = m_document->createElement("shared", ASSERT_NO_EXCEPTION); |
+ |
+ LayoutObjectProxy* layoutObject = LayoutObjectProxy::create(element.get()); |
+ element->setLayoutObject(layoutObject); |
+ layoutObject->createCompositedLayer(); |
+ |
+ AnimatableValueKeyframeVector keyFrames; |
+ keyFrames.append(createDefaultKeyframe(CSSPropertyOpacity, EffectModel::CompositeReplace, 0.0).get()); |
+ keyFrames.append(createDefaultKeyframe(CSSPropertyOpacity, EffectModel::CompositeReplace, 1.0).get()); |
+ EffectModel* animationEffect = AnimatableValueKeyframeEffectModel::create(keyFrames); |
+ |
+ Timing timing; |
+ timing.iterationDuration = 1.f; |
+ |
+ KeyframeEffect* keyframeEffect = KeyframeEffect::create(element.get(), animationEffect, timing); |
+ Animation* animation = m_timeline->play(keyframeEffect); |
+ EXPECT_TRUE(animation->isCandidateForAnimationOnCompositor()); |
+ |
+ preCommit(animation); |
+ |
+ animation->dispose(); |
+ animation->cancelAnimationOnCompositor(); |
Ian Vollick
2015/12/29 20:32:24
I may be misreading the purpose of this test -- it
loyso (OOO)
2015/12/29 23:54:25
That was just my assumption about the crash (ideas
|
+ |
+ EXPECT_FALSE(animation->hasActiveAnimationsOnCompositor()); |
+ |
+ simulateFrame(0); |
+ EXPECT_EQ(1U, element->elementAnimations()->animations().size()); |
+ simulateFrame(1.); |
+ |
+ element->setLayoutObject(nullptr); |
+ LayoutObjectProxy::dispose(layoutObject); |
+ |
+ Heap::collectAllGarbage(); |
+ EXPECT_TRUE(element->elementAnimations()->animations().isEmpty()); |
+} |
+ |
TEST_F(AnimationCompositorAnimationsTest, CancelIncompatibleCompositorAnimations) |
{ |
RefPtrWillBePersistent<Element> element = m_document->createElement("shared", ASSERT_NO_EXCEPTION); |
LayoutObjectProxy* layoutObject = LayoutObjectProxy::create(element.get()); |
element->setLayoutObject(layoutObject); |
+ layoutObject->createCompositedLayer(); |
AnimatableValueKeyframeVector keyFrames; |
keyFrames.append(createDefaultKeyframe(CSSPropertyOpacity, EffectModel::CompositeReplace, 0.0).get()); |
@@ -1194,18 +1297,15 @@ TEST_F(AnimationCompositorAnimationsTest, CancelIncompatibleCompositorAnimations |
// The first animation for opacity is ok to run on compositor. |
KeyframeEffect* keyframeEffect1 = KeyframeEffect::create(element.get(), animationEffect1, timing); |
Animation* animation1 = m_timeline->play(keyframeEffect1); |
- EXPECT_TRUE(CompositorAnimations::instance()->isCandidateForAnimationOnCompositor(timing, *element.get(), animation1, *animationEffect1, 1)); |
+ EXPECT_TRUE(animation1->isCandidateForAnimationOnCompositor()); |
- // simulate KeyframeEffect::maybeStartAnimationOnCompositor |
- Vector<int> compositorAnimationIds; |
- compositorAnimationIds.append(1); |
- keyframeEffect1->setCompositorAnimationIdsForTesting(compositorAnimationIds); |
- EXPECT_TRUE(animation1->hasActiveAnimationsOnCompositor()); |
+ preCommit(animation1); |
// The second animation for opacity is not ok to run on compositor. |
KeyframeEffect* keyframeEffect2 = KeyframeEffect::create(element.get(), animationEffect2, timing); |
Animation* animation2 = m_timeline->play(keyframeEffect2); |
EXPECT_FALSE(CompositorAnimations::instance()->isCandidateForAnimationOnCompositor(timing, *element.get(), animation2, *animationEffect2, 1)); |
+ EXPECT_FALSE(animation2->isCandidateForAnimationOnCompositor()); |
EXPECT_FALSE(animation2->hasActiveAnimationsOnCompositor()); |
// A fallback to blink implementation needed, so cancel all compositor-side opacity animations for this element. |