Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/AnimationInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "AnimationInfo.h"
8
#include "mozilla/layers/WebRenderLayerManager.h"
9
#include "mozilla/layers/AnimationHelper.h"
10
#include "mozilla/dom/Animation.h"
11
12
namespace mozilla {
13
namespace layers {
14
15
AnimationInfo::AnimationInfo(LayerManager* aManager) :
16
  mManager(aManager),
17
  mCompositorAnimationsId(0),
18
  mAnimationGeneration(0),
19
  mMutated(false)
20
0
{
21
0
}
22
23
AnimationInfo::~AnimationInfo()
24
0
{
25
0
}
26
27
void
28
AnimationInfo::EnsureAnimationsId()
29
0
{
30
0
  if (!mCompositorAnimationsId) {
31
0
    mCompositorAnimationsId = AnimationHelper::GetNextCompositorAnimationsId();
32
0
  }
33
0
}
34
35
Animation*
36
AnimationInfo::AddAnimation()
37
0
{
38
0
  // Here generates a new id when the first animation is added and
39
0
  // this id is used to represent the animations in this layer.
40
0
  EnsureAnimationsId();
41
0
42
0
  MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first");
43
0
44
0
  Animation* anim = mAnimations.AppendElement();
45
0
46
0
  mMutated = true;
47
0
48
0
  return anim;
49
0
}
50
51
Animation*
52
AnimationInfo::AddAnimationForNextTransaction()
53
0
{
54
0
  MOZ_ASSERT(mPendingAnimations,
55
0
             "should have called ClearAnimationsForNextTransaction first");
56
0
57
0
  Animation* anim = mPendingAnimations->AppendElement();
58
0
59
0
  return anim;
60
0
}
61
62
void
63
AnimationInfo::ClearAnimations()
64
0
{
65
0
  mPendingAnimations = nullptr;
66
0
67
0
  if (mAnimations.IsEmpty() && mAnimationData.IsEmpty()) {
68
0
    return;
69
0
  }
70
0
71
0
  mAnimations.Clear();
72
0
  mAnimationData.Clear();
73
0
74
0
  mMutated = true;
75
0
}
76
77
void
78
AnimationInfo::ClearAnimationsForNextTransaction()
79
0
{
80
0
  // Ensure we have a non-null mPendingAnimations to mark a future clear.
81
0
  if (!mPendingAnimations) {
82
0
    mPendingAnimations = new AnimationArray;
83
0
  }
84
0
85
0
  mPendingAnimations->Clear();
86
0
}
87
88
void
89
AnimationInfo::SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations)
90
0
{
91
0
  mAnimations = aCompositorAnimations.animations();
92
0
  mCompositorAnimationsId = aCompositorAnimations.id();
93
0
  mAnimationData.Clear();
94
0
  AnimationHelper::SetAnimations(mAnimations,
95
0
                                 mAnimationData,
96
0
                                 mBaseAnimationStyle);
97
0
}
98
99
bool
100
AnimationInfo::StartPendingAnimations(const TimeStamp& aReadyTime)
101
0
{
102
0
  bool updated = false;
103
0
  for (size_t animIdx = 0, animEnd = mAnimations.Length();
104
0
       animIdx < animEnd; animIdx++) {
105
0
    Animation& anim = mAnimations[animIdx];
106
0
107
0
    // If the animation is doing an async update of its playback rate, then we
108
0
    // want to match whatever its current time would be at *aReadyTime*.
109
0
    if (!std::isnan(anim.previousPlaybackRate()) &&
110
0
        anim.startTime().type() == MaybeTimeDuration::TTimeDuration &&
111
0
        !anim.originTime().IsNull() && !anim.isNotPlaying()) {
112
0
      TimeDuration readyTime = aReadyTime - anim.originTime();
113
0
      anim.holdTime() = dom::Animation::CurrentTimeFromTimelineTime(
114
0
        readyTime,
115
0
        anim.startTime().get_TimeDuration(),
116
0
        anim.previousPlaybackRate());
117
0
      // Make start time null so that we know to update it below.
118
0
      anim.startTime() = null_t();
119
0
    }
120
0
121
0
    // If the animation is play-pending, resolve the start time.
122
0
    if (anim.startTime().type() == MaybeTimeDuration::Tnull_t &&
123
0
        !anim.originTime().IsNull() &&
124
0
        !anim.isNotPlaying()) {
125
0
      TimeDuration readyTime = aReadyTime - anim.originTime();
126
0
      anim.startTime() = dom::Animation::StartTimeFromTimelineTime(
127
0
        readyTime, anim.holdTime(), anim.playbackRate());
128
0
      updated = true;
129
0
    }
130
0
  }
131
0
  return updated;
132
0
}
133
134
void
135
AnimationInfo::TransferMutatedFlagToLayer(Layer* aLayer)
136
0
{
137
0
  if (mMutated) {
138
0
    aLayer->Mutated();
139
0
    mMutated = false;
140
0
  }
141
0
}
142
143
bool
144
AnimationInfo::ApplyPendingUpdatesForThisTransaction()
145
0
{
146
0
  if (mPendingAnimations) {
147
0
    mPendingAnimations->SwapElements(mAnimations);
148
0
    mPendingAnimations = nullptr;
149
0
    return true;
150
0
  }
151
0
152
0
  return false;
153
0
}
154
155
bool
156
AnimationInfo::HasTransformAnimation() const
157
0
{
158
0
  for (uint32_t i = 0; i < mAnimations.Length(); i++) {
159
0
    if (mAnimations[i].property() == eCSSProperty_transform) {
160
0
      return true;
161
0
    }
162
0
  }
163
0
  return false;
164
0
}
165
166
/* static */ Maybe<uint64_t>
167
AnimationInfo::GetGenerationFromFrame(nsIFrame* aFrame,
168
                                      DisplayItemType aDisplayItemKey)
169
0
{
170
0
  MOZ_ASSERT(aFrame->IsPrimaryFrame() ||
171
0
             nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame));
172
0
173
0
  layers::Layer* layer =
174
0
    FrameLayerBuilder::GetDedicatedLayer(aFrame, aDisplayItemKey);
175
0
  if (layer) {
176
0
    return Some(layer->GetAnimationInfo().GetAnimationGeneration());
177
0
  }
178
0
179
0
  // In case of continuation, KeyframeEffectReadOnly uses its first frame,
180
0
  // whereas nsDisplayItem uses its last continuation, so we have to use the
181
0
  // last continuation frame here.
182
0
  if (nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) {
183
0
    aFrame = nsLayoutUtils::LastContinuationOrIBSplitSibling(aFrame);
184
0
  }
185
0
  RefPtr<WebRenderAnimationData> animationData =
186
0
      GetWebRenderUserData<WebRenderAnimationData>(aFrame, (uint32_t)aDisplayItemKey);
187
0
  if (animationData) {
188
0
    return Some(animationData->GetAnimationInfo().GetAnimationGeneration());
189
0
  }
190
0
191
0
  return Nothing();
192
0
}
193
194
} // namespace layers
195
} // namespace mozilla