2017-10-28 02:10:06 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2017-07-21 09:21:47 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "AnimationInfo.h"
|
2018-11-13 13:23:20 +03:00
|
|
|
#include "mozilla/LayerAnimationInfo.h"
|
2017-07-21 09:21:47 +03:00
|
|
|
#include "mozilla/layers/WebRenderLayerManager.h"
|
|
|
|
#include "mozilla/layers/AnimationHelper.h"
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
#include "mozilla/layers/CompositorThread.h"
|
2018-02-13 09:04:18 +03:00
|
|
|
#include "mozilla/dom/Animation.h"
|
2018-11-13 13:23:20 +03:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "PuppetWidget.h"
|
2017-07-21 09:21:47 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
|
2018-11-07 06:09:05 +03:00
|
|
|
AnimationInfo::AnimationInfo() : mCompositorAnimationsId(0), mMutated(false) {}
|
2017-07-21 09:21:47 +03:00
|
|
|
|
|
|
|
AnimationInfo::~AnimationInfo() {}
|
|
|
|
|
|
|
|
void AnimationInfo::EnsureAnimationsId() {
|
|
|
|
if (!mCompositorAnimationsId) {
|
|
|
|
mCompositorAnimationsId = AnimationHelper::GetNextCompositorAnimationsId();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Animation* AnimationInfo::AddAnimation() {
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
MOZ_ASSERT(!CompositorThreadHolder::IsInCompositorThread());
|
2017-07-21 09:21:47 +03:00
|
|
|
// Here generates a new id when the first animation is added and
|
|
|
|
// this id is used to represent the animations in this layer.
|
|
|
|
EnsureAnimationsId();
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mPendingAnimations, "should have called ClearAnimations first");
|
|
|
|
|
|
|
|
Animation* anim = mAnimations.AppendElement();
|
|
|
|
|
|
|
|
mMutated = true;
|
|
|
|
|
|
|
|
return anim;
|
|
|
|
}
|
|
|
|
|
|
|
|
Animation* AnimationInfo::AddAnimationForNextTransaction() {
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
MOZ_ASSERT(!CompositorThreadHolder::IsInCompositorThread());
|
2017-07-21 09:21:47 +03:00
|
|
|
MOZ_ASSERT(mPendingAnimations,
|
|
|
|
"should have called ClearAnimationsForNextTransaction first");
|
|
|
|
|
|
|
|
Animation* anim = mPendingAnimations->AppendElement();
|
|
|
|
|
|
|
|
return anim;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationInfo::ClearAnimations() {
|
|
|
|
mPendingAnimations = nullptr;
|
|
|
|
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
if (mAnimations.IsEmpty() && mPropertyAnimationGroups.IsEmpty()) {
|
2017-07-21 09:21:47 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mAnimations.Clear();
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
mPropertyAnimationGroups.Clear();
|
2019-11-01 00:36:39 +03:00
|
|
|
mCachedMotionPath = nullptr;
|
2017-07-21 09:21:47 +03:00
|
|
|
|
|
|
|
mMutated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationInfo::ClearAnimationsForNextTransaction() {
|
|
|
|
// Ensure we have a non-null mPendingAnimations to mark a future clear.
|
|
|
|
if (!mPendingAnimations) {
|
|
|
|
mPendingAnimations = new AnimationArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
mPendingAnimations->Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationInfo::SetCompositorAnimations(
|
|
|
|
const CompositorAnimations& aCompositorAnimations) {
|
|
|
|
mCompositorAnimationsId = aCompositorAnimations.id();
|
2019-11-01 00:36:39 +03:00
|
|
|
|
|
|
|
AnimationStorageData data =
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
AnimationHelper::ExtractAnimations(aCompositorAnimations.animations());
|
2019-11-01 00:36:39 +03:00
|
|
|
mPropertyAnimationGroups.SwapElements(data.mAnimation);
|
|
|
|
mCachedMotionPath.swap(data.mCachedMotionPath);
|
2017-07-21 09:21:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AnimationInfo::StartPendingAnimations(const TimeStamp& aReadyTime) {
|
|
|
|
bool updated = false;
|
|
|
|
for (size_t animIdx = 0, animEnd = mAnimations.Length(); animIdx < animEnd;
|
|
|
|
animIdx++) {
|
|
|
|
Animation& anim = mAnimations[animIdx];
|
|
|
|
|
2018-02-13 09:04:18 +03:00
|
|
|
// If the animation is doing an async update of its playback rate, then we
|
|
|
|
// want to match whatever its current time would be at *aReadyTime*.
|
2019-03-25 22:29:46 +03:00
|
|
|
if (!std::isnan(anim.previousPlaybackRate()) && anim.startTime().isSome() &&
|
2018-02-13 09:04:18 +03:00
|
|
|
!anim.originTime().IsNull() && !anim.isNotPlaying()) {
|
|
|
|
TimeDuration readyTime = aReadyTime - anim.originTime();
|
|
|
|
anim.holdTime() = dom::Animation::CurrentTimeFromTimelineTime(
|
2019-03-25 22:29:46 +03:00
|
|
|
readyTime, anim.startTime().ref(), anim.previousPlaybackRate());
|
2018-02-13 09:04:18 +03:00
|
|
|
// Make start time null so that we know to update it below.
|
2019-03-25 22:29:46 +03:00
|
|
|
anim.startTime() = Nothing();
|
2018-02-13 09:04:18 +03:00
|
|
|
}
|
|
|
|
|
2017-07-21 09:21:47 +03:00
|
|
|
// If the animation is play-pending, resolve the start time.
|
2019-03-25 22:29:46 +03:00
|
|
|
if (anim.startTime().isNothing() && !anim.originTime().IsNull() &&
|
|
|
|
!anim.isNotPlaying()) {
|
2017-07-21 09:21:47 +03:00
|
|
|
TimeDuration readyTime = aReadyTime - anim.originTime();
|
2019-03-25 22:29:46 +03:00
|
|
|
anim.startTime() = Some(dom::Animation::StartTimeFromTimelineTime(
|
|
|
|
readyTime, anim.holdTime(), anim.playbackRate()));
|
2017-07-21 09:21:47 +03:00
|
|
|
updated = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return updated;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AnimationInfo::TransferMutatedFlagToLayer(Layer* aLayer) {
|
|
|
|
if (mMutated) {
|
|
|
|
aLayer->Mutated();
|
|
|
|
mMutated = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnimationInfo::ApplyPendingUpdatesForThisTransaction() {
|
|
|
|
if (mPendingAnimations) {
|
|
|
|
mPendingAnimations->SwapElements(mAnimations);
|
|
|
|
mPendingAnimations = nullptr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnimationInfo::HasTransformAnimation() const {
|
2019-03-18 21:04:58 +03:00
|
|
|
const nsCSSPropertyIDSet& transformSet =
|
|
|
|
LayerAnimationInfo::GetCSSPropertiesFor(DisplayItemType::TYPE_TRANSFORM);
|
2017-07-21 09:21:47 +03:00
|
|
|
for (uint32_t i = 0; i < mAnimations.Length(); i++) {
|
2019-03-18 21:04:58 +03:00
|
|
|
if (transformSet.HasProperty(mAnimations[i].property())) {
|
2017-07-21 09:21:47 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
|
|
|
Maybe<uint64_t> AnimationInfo::GetGenerationFromFrame(
|
2018-04-06 17:06:54 +03:00
|
|
|
nsIFrame* aFrame, DisplayItemType aDisplayItemKey) {
|
2018-05-08 23:54:10 +03:00
|
|
|
MOZ_ASSERT(aFrame->IsPrimaryFrame() ||
|
2018-05-07 04:50:40 +03:00
|
|
|
nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame));
|
|
|
|
|
2018-04-06 17:06:54 +03:00
|
|
|
layers::Layer* layer =
|
|
|
|
FrameLayerBuilder::GetDedicatedLayer(aFrame, aDisplayItemKey);
|
|
|
|
if (layer) {
|
2018-11-07 06:13:04 +03:00
|
|
|
return layer->GetAnimationInfo().GetAnimationGeneration();
|
2018-04-06 17:06:54 +03:00
|
|
|
}
|
|
|
|
|
2018-05-07 04:50:40 +03:00
|
|
|
// In case of continuation, KeyframeEffectReadOnly uses its first frame,
|
|
|
|
// whereas nsDisplayItem uses its last continuation, so we have to use the
|
|
|
|
// last continuation frame here.
|
|
|
|
if (nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) {
|
|
|
|
aFrame = nsLayoutUtils::LastContinuationOrIBSplitSibling(aFrame);
|
|
|
|
}
|
2018-04-06 17:06:54 +03:00
|
|
|
RefPtr<WebRenderAnimationData> animationData =
|
|
|
|
GetWebRenderUserData<WebRenderAnimationData>(aFrame,
|
|
|
|
(uint32_t)aDisplayItemKey);
|
|
|
|
if (animationData) {
|
2018-11-07 06:13:04 +03:00
|
|
|
return animationData->GetAnimationInfo().GetAnimationGeneration();
|
2018-04-06 17:06:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return Nothing();
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
|
|
|
void AnimationInfo::EnumerateGenerationOnFrame(
|
2018-11-13 13:23:20 +03:00
|
|
|
const nsIFrame* aFrame, const nsIContent* aContent,
|
|
|
|
const CompositorAnimatableDisplayItemTypes& aDisplayItemTypes,
|
|
|
|
const AnimationGenerationCallback& aCallback) {
|
|
|
|
if (XRE_IsContentProcess()) {
|
|
|
|
if (nsIWidget* widget = nsContentUtils::WidgetForContent(aContent)) {
|
|
|
|
// In case of child processes, we might not have yet created the layer
|
|
|
|
// manager. That means there is no animation generation we have, thus
|
|
|
|
// we call the callback function with |Nothing()| for the generation.
|
|
|
|
//
|
|
|
|
// Note that we need to use nsContentUtils::WidgetForContent() instead of
|
2019-04-10 01:39:01 +03:00
|
|
|
// BrowserChild::GetFrom(aFrame->PresShell())->WebWidget() because in the
|
|
|
|
// case of child popup content PuppetWidget::mBrowserChild is the same as
|
|
|
|
// the parent's one, which means mBrowserChild->IsLayersConnected() check
|
|
|
|
// in PuppetWidget::GetLayerManager queries the parent state, it results
|
|
|
|
// the assertion in the function failure.
|
|
|
|
if (widget->GetOwningBrowserChild() &&
|
2018-11-13 13:23:20 +03:00
|
|
|
!static_cast<widget::PuppetWidget*>(widget)->HasLayerManager()) {
|
|
|
|
for (auto displayItem : LayerAnimationInfo::sDisplayItemTypes) {
|
|
|
|
aCallback(Nothing(), displayItem);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<LayerManager> layerManager =
|
|
|
|
nsContentUtils::LayerManagerForContent(aContent);
|
|
|
|
|
|
|
|
if (layerManager &&
|
|
|
|
layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
|
|
|
|
// In case of continuation, nsDisplayItem uses its last continuation, so we
|
|
|
|
// have to use the last continuation frame here.
|
|
|
|
if (nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) {
|
|
|
|
aFrame = nsLayoutUtils::LastContinuationOrIBSplitSibling(aFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto displayItem : LayerAnimationInfo::sDisplayItemTypes) {
|
2019-03-07 08:40:51 +03:00
|
|
|
// For transform animations, the animation is on the primary frame but
|
|
|
|
// |aFrame| is the style frame.
|
|
|
|
const nsIFrame* frameToQuery =
|
|
|
|
displayItem == DisplayItemType::TYPE_TRANSFORM
|
|
|
|
? nsLayoutUtils::GetPrimaryFrameFromStyleFrame(aFrame)
|
|
|
|
: aFrame;
|
2018-11-13 13:23:20 +03:00
|
|
|
RefPtr<WebRenderAnimationData> animationData =
|
2019-03-07 08:40:51 +03:00
|
|
|
GetWebRenderUserData<WebRenderAnimationData>(frameToQuery,
|
2018-11-13 13:23:20 +03:00
|
|
|
(uint32_t)displayItem);
|
|
|
|
Maybe<uint64_t> generation;
|
|
|
|
if (animationData) {
|
|
|
|
generation = animationData->GetAnimationInfo().GetAnimationGeneration();
|
|
|
|
}
|
|
|
|
aCallback(generation, displayItem);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-07 08:40:24 +03:00
|
|
|
FrameLayerBuilder::EnumerateGenerationForDedicatedLayers(aFrame, aCallback);
|
2018-11-13 13:23:20 +03:00
|
|
|
}
|
|
|
|
|
2017-07-21 09:21:47 +03:00
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|