Bug 1769952 - Fix running raptor on a Win10-64 VM r=sparky
[gecko.git] / dom / animation / EffectSet.cpp
blob550d0cf1b096eabb4f4e29d5f8393e4d798dc6e6
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/. */
7 #include "EffectSet.h"
8 #include "mozilla/dom/Element.h" // For Element
9 #include "mozilla/RestyleManager.h"
10 #include "mozilla/LayerAnimationInfo.h"
11 #include "nsCSSPseudoElements.h" // For PseudoStyleType
12 #include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
13 #include "nsPresContext.h"
14 #include "nsLayoutUtils.h"
16 namespace mozilla {
18 /* static */
19 void EffectSet::PropertyDtor(void* aObject, nsAtom* aPropertyName,
20 void* aPropertyValue, void* aData) {
21 EffectSet* effectSet = static_cast<EffectSet*>(aPropertyValue);
23 #ifdef DEBUG
24 MOZ_ASSERT(!effectSet->mCalledPropertyDtor, "Should not call dtor twice");
25 effectSet->mCalledPropertyDtor = true;
26 #endif
28 delete effectSet;
31 void EffectSet::Traverse(nsCycleCollectionTraversalCallback& aCallback) {
32 for (const auto& key : mEffects) {
33 CycleCollectionNoteChild(aCallback, key, "EffectSet::mEffects[]",
34 aCallback.Flags());
38 /* static */
39 EffectSet* EffectSet::GetEffectSet(const dom::Element* aElement,
40 PseudoStyleType aPseudoType) {
41 if (!aElement->MayHaveAnimations()) {
42 return nullptr;
45 nsAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
46 return static_cast<EffectSet*>(aElement->GetProperty(propName));
49 /* static */
50 EffectSet* EffectSet::GetOrCreateEffectSet(dom::Element* aElement,
51 PseudoStyleType aPseudoType) {
52 EffectSet* effectSet = GetEffectSet(aElement, aPseudoType);
53 if (effectSet) {
54 return effectSet;
57 nsAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
58 effectSet = new EffectSet();
60 nsresult rv = aElement->SetProperty(propName, effectSet,
61 &EffectSet::PropertyDtor, true);
62 if (NS_FAILED(rv)) {
63 NS_WARNING("SetProperty failed");
64 // The set must be destroyed via PropertyDtor, otherwise
65 // mCalledPropertyDtor assertion is triggered in destructor.
66 EffectSet::PropertyDtor(aElement, propName, effectSet, nullptr);
67 return nullptr;
70 aElement->SetMayHaveAnimations();
72 return effectSet;
75 /* static */
76 EffectSet* EffectSet::GetEffectSetForFrame(
77 const nsIFrame* aFrame, const nsCSSPropertyIDSet& aProperties) {
78 MOZ_ASSERT(aFrame);
80 // Transform animations are run on the primary frame (but stored on the
81 // content associated with the style frame).
82 const nsIFrame* frameToQuery = nullptr;
83 if (aProperties.IsSubsetOf(nsCSSPropertyIDSet::TransformLikeProperties())) {
84 // Make sure to return nullptr if we're looking for transform animations on
85 // the inner table frame.
86 if (!aFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
87 return nullptr;
89 frameToQuery = nsLayoutUtils::GetStyleFrame(aFrame);
90 } else {
91 MOZ_ASSERT(
92 !aProperties.Intersects(nsCSSPropertyIDSet::TransformLikeProperties()),
93 "We should have only transform properties or no transform properties");
94 // We don't need to explicitly return nullptr when |aFrame| is NOT the style
95 // frame since there will be no effect set in that case.
96 frameToQuery = aFrame;
99 Maybe<NonOwningAnimationTarget> target =
100 EffectCompositor::GetAnimationElementAndPseudoForFrame(frameToQuery);
101 if (!target) {
102 return nullptr;
105 return GetEffectSet(target->mElement, target->mPseudoType);
108 /* static */
109 EffectSet* EffectSet::GetEffectSetForFrame(const nsIFrame* aFrame,
110 DisplayItemType aDisplayItemType) {
111 return EffectSet::GetEffectSetForFrame(
112 aFrame, LayerAnimationInfo::GetCSSPropertiesFor(aDisplayItemType));
115 /* static */
116 EffectSet* EffectSet::GetEffectSetForStyleFrame(const nsIFrame* aStyleFrame) {
117 Maybe<NonOwningAnimationTarget> target =
118 EffectCompositor::GetAnimationElementAndPseudoForFrame(aStyleFrame);
120 if (!target) {
121 return nullptr;
124 return GetEffectSet(target->mElement, target->mPseudoType);
127 /* static */
128 EffectSet* EffectSet::GetEffectSetForEffect(
129 const dom::KeyframeEffect* aEffect) {
130 NonOwningAnimationTarget target = aEffect->GetAnimationTarget();
131 if (!target) {
132 return nullptr;
135 return EffectSet::GetEffectSet(target.mElement, target.mPseudoType);
138 /* static */
139 void EffectSet::DestroyEffectSet(dom::Element* aElement,
140 PseudoStyleType aPseudoType) {
141 nsAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
142 EffectSet* effectSet =
143 static_cast<EffectSet*>(aElement->GetProperty(propName));
144 if (!effectSet) {
145 return;
148 MOZ_ASSERT(!effectSet->IsBeingEnumerated(),
149 "Should not destroy an effect set while it is being enumerated");
150 effectSet = nullptr;
152 aElement->RemoveProperty(propName);
155 void EffectSet::UpdateAnimationGeneration(nsPresContext* aPresContext) {
156 mAnimationGeneration =
157 aPresContext->RestyleManager()->GetAnimationGeneration();
160 /* static */
161 nsAtom** EffectSet::GetEffectSetPropertyAtoms() {
162 static nsAtom* effectSetPropertyAtoms[] = {
163 nsGkAtoms::animationEffectsProperty,
164 nsGkAtoms::animationEffectsForBeforeProperty,
165 nsGkAtoms::animationEffectsForAfterProperty,
166 nsGkAtoms::animationEffectsForMarkerProperty, nullptr};
168 return effectSetPropertyAtoms;
171 /* static */
172 nsAtom* EffectSet::GetEffectSetPropertyAtom(PseudoStyleType aPseudoType) {
173 switch (aPseudoType) {
174 case PseudoStyleType::NotPseudo:
175 return nsGkAtoms::animationEffectsProperty;
177 case PseudoStyleType::before:
178 return nsGkAtoms::animationEffectsForBeforeProperty;
180 case PseudoStyleType::after:
181 return nsGkAtoms::animationEffectsForAfterProperty;
183 case PseudoStyleType::marker:
184 return nsGkAtoms::animationEffectsForMarkerProperty;
186 default:
187 MOZ_ASSERT_UNREACHABLE(
188 "Should not try to get animation effects for "
189 "a pseudo other that :before, :after or ::marker");
190 return nullptr;
194 void EffectSet::AddEffect(dom::KeyframeEffect& aEffect) {
195 if (!mEffects.EnsureInserted(&aEffect)) {
196 return;
199 MarkCascadeNeedsUpdate();
202 void EffectSet::RemoveEffect(dom::KeyframeEffect& aEffect) {
203 if (!mEffects.EnsureRemoved(&aEffect)) {
204 return;
207 MarkCascadeNeedsUpdate();
210 } // namespace mozilla