Commit 2d136863 authored by alancutter's avatar alancutter Committed by Commit bot

Refactor how UseCounter::SyntheticKeyframesInCompositedCSSAnimation is counted

This patch rewrites the detection logic for composited animations that
have neutral keyframes.

The previous code was relatively expensive and failed a DCHECK when
custom properties were used. This patch moves the use counting down into
where we actually handle compositing neutral keyframes.

BUG=679994

Review-Url: https://codereview.chromium.org/2620303002
Cr-Commit-Position: refs/heads/master@{#443180}
parent c162e0c6
<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<style>
@keyframes noSyntheticKeyframes {
from { color: black; }
to { color: green; }
}
@keyframes customPropertySyntheticKeyframes {
to { --x: pants; }
}
@keyframes nonCompositedSyntheticKeyframes {
to { color: green; }
}
@keyframes compositedSyntheticKeyframes {
from {
opacity: 0;
}
to {
transform: rotate(45deg);
opacity: 1;
}
}
#target {
animation-duration: 1s;
}
</style>
<div id="target"></div>
<script>
// From UseCounter.h.
var SyntheticKeyframesInCompositedCSSAnimation = 664;
function forceStyleRecalc() {
getComputedStyle(target).left;
}
test(() => {
forceStyleRecalc();
assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'No animations started');
target.style.animationName = 'noSyntheticKeyframes';
forceStyleRecalc();
assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'noSyntheticKeyframes');
target.style.animationName = 'customPropertySyntheticKeyframes';
forceStyleRecalc();
assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'customPropertySyntheticKeyframes');
target.style.animationName = 'nonCompositedSyntheticKeyframes';
forceStyleRecalc();
assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'nonCompositedSyntheticKeyframes');
target.style.animationName = 'compositedSyntheticKeyframes';
forceStyleRecalc();
assert_true(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'compositedSyntheticKeyframes');
}, 'The SyntheticKeyframesInCompositedCSSAnimation use counter should only be triggered by animations with composited properties with neutral keyframes');
</script>
......@@ -73,10 +73,7 @@ class CORE_EXPORT Keyframe : public RefCounted<Keyframe> {
double underlyingFraction() const {
return m_composite == EffectModel::CompositeReplace ? 0 : 1;
}
virtual bool isNeutral() const {
NOTREACHED();
return false;
}
virtual bool isNeutral() const = 0;
virtual PassRefPtr<PropertySpecificKeyframe> cloneWithOffset(
double offset) const = 0;
......
......@@ -36,6 +36,7 @@
#include "core/css/CSSPropertyEquality.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Document.h"
#include "core/frame/UseCounter.h"
#include "platform/animation/AnimationUtilities.h"
#include "platform/geometry/FloatBox.h"
#include "platform/transforms/TransformationMatrix.h"
......@@ -110,15 +111,22 @@ bool KeyframeEffectModelBase::snapshotAllCompositorKeyframes(
const ComputedStyle* parentStyle) const {
m_needsCompositorKeyframesSnapshot = false;
bool updated = false;
bool hasNeutralCompositableKeyframe = false;
ensureKeyframeGroups();
for (CSSPropertyID property : CompositorAnimations::compositableProperties) {
PropertySpecificKeyframeGroup* keyframeGroup =
m_keyframeGroups->get(PropertyHandle(property));
if (!keyframeGroup)
continue;
for (auto& keyframe : keyframeGroup->m_keyframes)
for (auto& keyframe : keyframeGroup->m_keyframes) {
updated |= keyframe->populateAnimatableValue(property, element, baseStyle,
parentStyle);
hasNeutralCompositableKeyframe |= keyframe->isNeutral();
}
}
if (updated && hasNeutralCompositableKeyframe) {
UseCounter::count(element.document(),
UseCounter::SyntheticKeyframesInCompositedCSSAnimation);
}
return updated;
}
......
......@@ -46,6 +46,7 @@ class CORE_EXPORT AnimatableValueKeyframe : public Keyframe {
return m_value;
}
bool isNeutral() const final { return m_value->isNeutral(); }
PassRefPtr<Keyframe::PropertySpecificKeyframe> neutralKeyframe(
double offset,
PassRefPtr<TimingFunction> easing) const final;
......
......@@ -172,35 +172,6 @@ static StringKeyframeEffectModel* createKeyframeEffectModel(
DCHECK(!keyframes.front()->offset());
DCHECK_EQ(keyframes.back()->offset(), 1);
// This is used for use counting neutral keyframes running on the compositor.
PropertySet allProperties;
for (const auto& keyframe : keyframes) {
for (const auto& property : keyframe->properties())
allProperties.add(property.cssProperty());
}
const PropertyHandleSet& startKeyframeProperties =
startKeyframe->properties();
const PropertyHandleSet& endKeyframeProperties = endKeyframe->properties();
bool missingStartValues =
startKeyframeProperties.size() < allProperties.size();
bool missingEndValues = endKeyframeProperties.size() < allProperties.size();
if (missingStartValues || missingEndValues) {
for (CSSPropertyID property : allProperties) {
bool startNeedsValue =
missingStartValues &&
!startKeyframeProperties.contains(PropertyHandle(property));
bool endNeedsValue =
missingEndValues &&
!endKeyframeProperties.contains(PropertyHandle(property));
if (!startNeedsValue && !endNeedsValue)
continue;
if (CompositorAnimations::isCompositableProperty(property))
UseCounter::count(
elementForScoping->document(),
UseCounter::SyntheticKeyframesInCompositedCSSAnimation);
}
}
StringKeyframeEffectModel* model =
StringKeyframeEffectModel::create(keyframes, &keyframes[0]->easing());
if (animationIndex > 0 && model->hasSyntheticKeyframes())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment