blob: 9d35658bbbc91087cf1a9b275e8d9a81ce9352cb [file] [log] [blame]
/*
* Copyright (C) 2013 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "core/animation/EffectStack.h"
#include <algorithm>
#include "core/animation/CompositorAnimations.h"
#include "core/animation/InvalidatableInterpolation.h"
#include "core/animation/css/CSSAnimations.h"
#include "platform/runtime_enabled_features.h"
#include "platform/wtf/NonCopyingSort.h"
namespace blink {
namespace {
void CopyToActiveInterpolationsMap(
const Vector<scoped_refptr<Interpolation>>& source,
EffectStack::PropertyHandleFilter property_handle_filter,
ActiveInterpolationsMap& target) {
for (const auto& interpolation : source) {
PropertyHandle property = interpolation->GetProperty();
if (property_handle_filter && !property_handle_filter(property))
continue;
ActiveInterpolationsMap::AddResult entry =
target.insert(property, ActiveInterpolations(1));
ActiveInterpolations& active_interpolations = entry.stored_value->value;
if (!entry.is_new_entry &&
(RuntimeEnabledFeatures::StackedCSSPropertyAnimationsEnabled() ||
!property.IsCSSProperty() || property.IsPresentationAttribute()) &&
interpolation->IsInvalidatableInterpolation() &&
ToInvalidatableInterpolation(*interpolation)
.DependsOnUnderlyingValue()) {
active_interpolations.push_back(interpolation.get());
} else {
active_interpolations.at(0) = interpolation.get();
}
}
}
bool CompareSampledEffects(const Member<SampledEffect>& sampled_effect1,
const Member<SampledEffect>& sampled_effect2) {
DCHECK(sampled_effect1 && sampled_effect2);
return sampled_effect1->SequenceNumber() < sampled_effect2->SequenceNumber();
}
void CopyNewAnimationsToActiveInterpolationsMap(
const HeapVector<Member<const InertEffect>>& new_animations,
EffectStack::PropertyHandleFilter property_handle_filter,
ActiveInterpolationsMap& result) {
for (const auto& new_animation : new_animations) {
Vector<scoped_refptr<Interpolation>> sample;
new_animation->Sample(sample);
if (!sample.IsEmpty())
CopyToActiveInterpolationsMap(sample, property_handle_filter, result);
}
}
} // namespace
EffectStack::EffectStack() = default;
bool EffectStack::HasActiveAnimationsOnCompositor(
const PropertyHandle& property) const {
for (const auto& sampled_effect : sampled_effects_) {
// TODO(dstockwell): move the playing check into AnimationEffectReadOnly and
// expose both hasAnimations and hasActiveAnimations
if (sampled_effect->Effect() &&
sampled_effect->Effect()->GetAnimation()->Playing() &&
sampled_effect->Effect()->HasActiveAnimationsOnCompositor(property))
return true;
}
return false;
}
bool EffectStack::AffectsProperties(PropertyHandleFilter filter) const {
for (const auto& sampled_effect : sampled_effects_) {
for (const auto& interpolation : sampled_effect->Interpolations()) {
if (filter(interpolation->GetProperty()))
return true;
}
}
return false;
}
ActiveInterpolationsMap EffectStack::ActiveInterpolations(
EffectStack* effect_stack,
const HeapVector<Member<const InertEffect>>* new_animations,
const HeapHashSet<Member<const Animation>>* suppressed_animations,
KeyframeEffectReadOnly::Priority priority,
PropertyHandleFilter property_handle_filter) {
ActiveInterpolationsMap result;
if (effect_stack) {
HeapVector<Member<SampledEffect>>& sampled_effects =
effect_stack->sampled_effects_;
// std::sort doesn't work with OwnPtrs
NonCopyingSort(sampled_effects.begin(), sampled_effects.end(),
CompareSampledEffects);
effect_stack->RemoveRedundantSampledEffects();
for (const auto& sampled_effect : sampled_effects) {
if (sampled_effect->GetPriority() != priority ||
(suppressed_animations && sampled_effect->Effect() &&
suppressed_animations->Contains(
sampled_effect->Effect()->GetAnimation())))
continue;
CopyToActiveInterpolationsMap(sampled_effect->Interpolations(),
property_handle_filter, result);
}
}
if (new_animations) {
CopyNewAnimationsToActiveInterpolationsMap(*new_animations,
property_handle_filter, result);
}
return result;
}
void EffectStack::RemoveRedundantSampledEffects() {
HashSet<PropertyHandle> replaced_properties;
for (size_t i = sampled_effects_.size(); i--;) {
SampledEffect& sampled_effect = *sampled_effects_[i];
if (sampled_effect.WillNeverChange()) {
sampled_effect.RemoveReplacedInterpolations(replaced_properties);
sampled_effect.UpdateReplacedProperties(replaced_properties);
}
}
size_t new_size = 0;
for (auto& sampled_effect : sampled_effects_) {
if (!sampled_effect->Interpolations().IsEmpty())
sampled_effects_[new_size++].Swap(sampled_effect);
else if (sampled_effect->Effect())
sampled_effect->Effect()->NotifySampledEffectRemovedFromEffectStack();
}
sampled_effects_.Shrink(new_size);
}
void EffectStack::Trace(blink::Visitor* visitor) {
visitor->Trace(sampled_effects_);
}
} // namespace blink