Commit 8454c40e authored by George Steel's avatar George Steel Committed by Commit Bot

Invalidate compositor transform animations with percents on box size.

When looping over transform animations in UpdateTransform, originally to
check whether they preserve axis alignment, we also check for box size
box size dependencies. If such dependencies are found, check whether the
relevant sizes have changed (using a current value stored in the
KeyframeEffect), and if so, restart the animation on the compositor
(note that RestartAnimationOnCompositor is a no-op if the animation is
not already composited).

This makes composited relative transform keyframes (implemented behind a
flag) fully working for CSS boxes, which could potentially be selectively
enabled ahead of doing so for SVG.

Design doc: https://docs.google.com/document/d/1zgr5CHRMpvlqodn1e0eM9J3MjL2eEMfAHrHsZUK7gMM/

Bug: 389359
Change-Id: I9b8189a3f3e002902b5eec58c08bb54644039536
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2492893
Commit-Queue: George Steel <gtsteel@chromium.org>
Reviewed-by: default avatarKevin Ellis <kevers@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820296}
parent 84cc8ac5
...@@ -136,15 +136,17 @@ void ElementAnimations::ClearBaseComputedStyle() { ...@@ -136,15 +136,17 @@ void ElementAnimations::ClearBaseComputedStyle() {
base_important_set_ = nullptr; base_important_set_ = nullptr;
} }
bool ElementAnimations::AnimationsPreserveAxisAlignment() const { bool ElementAnimations::UpdateBoxSizeAndCheckTransformAxisAlignment(
for (const auto& entry : animations_) { const FloatSize& box_size) {
const Animation& animation = *entry.key; bool preserves_axis_alignment = true;
if (const auto* effect = DynamicTo<KeyframeEffect>(animation.effect())) { for (auto& entry : animations_) {
if (!effect->AnimationsPreserveAxisAlignment()) Animation& animation = *entry.key;
return false; if (auto* effect = DynamicTo<KeyframeEffect>(animation.effect())) {
if (!effect->UpdateBoxSizeAndCheckTransformAxisAlignment(box_size))
preserves_axis_alignment = false;
} }
} }
return true; return preserves_axis_alignment;
} }
} // namespace blink } // namespace blink
...@@ -88,7 +88,7 @@ class CORE_EXPORT ElementAnimations final ...@@ -88,7 +88,7 @@ class CORE_EXPORT ElementAnimations final
std::unique_ptr<CSSBitset> base_important_set); std::unique_ptr<CSSBitset> base_important_set);
void ClearBaseComputedStyle(); void ClearBaseComputedStyle();
bool AnimationsPreserveAxisAlignment() const; bool UpdateBoxSizeAndCheckTransformAxisAlignment(const FloatSize& box_size);
void Trace(Visitor*) const; void Trace(Visitor*) const;
......
...@@ -456,24 +456,6 @@ void KeyframeEffect::Trace(Visitor* visitor) const { ...@@ -456,24 +456,6 @@ void KeyframeEffect::Trace(Visitor* visitor) const {
AnimationEffect::Trace(visitor); AnimationEffect::Trace(visitor);
} }
bool KeyframeEffect::AnimationsPreserveAxisAlignment(
const PropertyHandle& property) const {
const auto* keyframes = Model()->GetPropertySpecificKeyframes(property);
if (!keyframes)
return true;
for (const auto& keyframe : *keyframes) {
const auto* value = keyframe->GetCompositorKeyframeValue();
if (!value)
continue;
DCHECK(value->IsTransform());
const auto& transform_operations =
To<CompositorKeyframeTransform>(value)->GetTransformOperations();
if (!transform_operations.PreservesAxisAlignment())
return false;
}
return true;
}
namespace { namespace {
static const size_t num_transform_properties = 4; static const size_t num_transform_properties = 4;
...@@ -487,14 +469,52 @@ const CSSProperty** TransformProperties() { ...@@ -487,14 +469,52 @@ const CSSProperty** TransformProperties() {
} // namespace } // namespace
bool KeyframeEffect::AnimationsPreserveAxisAlignment() const { bool KeyframeEffect::UpdateBoxSizeAndCheckTransformAxisAlignment(
const FloatSize& box_size) {
static const auto** properties = TransformProperties(); static const auto** properties = TransformProperties();
bool preserves_axis_alignment = true;
bool has_transform = false;
TransformOperation::BoxSizeDependency size_dependencies =
TransformOperation::kDependsNone;
for (size_t i = 0; i < num_transform_properties; i++) { for (size_t i = 0; i < num_transform_properties; i++) {
if (!AnimationsPreserveAxisAlignment(PropertyHandle(*properties[i]))) const auto* keyframes =
return false; Model()->GetPropertySpecificKeyframes(PropertyHandle(*properties[i]));
if (!keyframes)
continue;
has_transform = true;
for (const auto& keyframe : *keyframes) {
const auto* value = keyframe->GetCompositorKeyframeValue();
if (!value)
continue;
const auto& transform_operations =
To<CompositorKeyframeTransform>(value)->GetTransformOperations();
if (!transform_operations.PreservesAxisAlignment())
preserves_axis_alignment = false;
size_dependencies = TransformOperation::CombineDependencies(
size_dependencies, transform_operations.BoxSizeDependencies());
}
} }
if (!has_transform)
return true; return true;
if (HasAnimation()) {
if (effect_target_size_) {
if ((size_dependencies & TransformOperation::kDependsWidth) &&
(effect_target_size_->Width() != box_size.Width()))
GetAnimation()->RestartAnimationOnCompositor();
else if ((size_dependencies & TransformOperation::kDependsHeight) &&
(effect_target_size_->Width() != box_size.Height()))
GetAnimation()->RestartAnimationOnCompositor();
} else if (size_dependencies) {
GetAnimation()->RestartAnimationOnCompositor();
}
}
effect_target_size_ = box_size;
return preserves_axis_alignment;
} }
EffectModel::CompositeOperation KeyframeEffect::CompositeInternal() const { EffectModel::CompositeOperation KeyframeEffect::CompositeInternal() const {
......
...@@ -31,11 +31,13 @@ ...@@ -31,11 +31,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_KEYFRAME_EFFECT_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_KEYFRAME_EFFECT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_KEYFRAME_EFFECT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_KEYFRAME_EFFECT_H_
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h" #include "third_party/blink/renderer/core/animation/animation_effect.h"
#include "third_party/blink/renderer/core/animation/compositor_animations.h" #include "third_party/blink/renderer/core/animation/compositor_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h" #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
namespace blink { namespace blink {
...@@ -133,7 +135,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect { ...@@ -133,7 +135,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
void Trace(Visitor*) const override; void Trace(Visitor*) const override;
bool AnimationsPreserveAxisAlignment() const; bool UpdateBoxSizeAndCheckTransformAxisAlignment(const FloatSize& box_size);
ActiveInterpolationsMap InterpolationsForCommitStyles(); ActiveInterpolationsMap InterpolationsForCommitStyles();
...@@ -164,8 +166,6 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect { ...@@ -164,8 +166,6 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
bool HasIncompatibleStyle() const; bool HasIncompatibleStyle() const;
bool HasMultipleTransformProperties() const; bool HasMultipleTransformProperties() const;
bool AnimationsPreserveAxisAlignment(const PropertyHandle&) const;
Member<Element> effect_target_; Member<Element> effect_target_;
Member<Element> target_element_; Member<Element> target_element_;
String target_pseudo_; String target_pseudo_;
...@@ -177,6 +177,8 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect { ...@@ -177,6 +177,8 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
Vector<int> compositor_keyframe_model_ids_; Vector<int> compositor_keyframe_model_ids_;
bool ignore_css_keyframes_; bool ignore_css_keyframes_;
base::Optional<FloatSize> effect_target_size_;
}; };
template <> template <>
......
...@@ -500,25 +500,27 @@ TEST_F(KeyframeEffectTest, TranslationTransformsPreserveAxisAlignment) { ...@@ -500,25 +500,27 @@ TEST_F(KeyframeEffectTest, TranslationTransformsPreserveAxisAlignment) {
auto* effect = auto* effect =
GetTwoFrameEffect(CSSPropertyID::kTransform, "translate(10px, 10px)", GetTwoFrameEffect(CSSPropertyID::kTransform, "translate(10px, 10px)",
"translate(20px, 20px)"); "translate(20px, 20px)");
EXPECT_TRUE(effect->AnimationsPreserveAxisAlignment()); EXPECT_TRUE(effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
} }
TEST_F(KeyframeEffectTest, ScaleTransformsPreserveAxisAlignment) { TEST_F(KeyframeEffectTest, ScaleTransformsPreserveAxisAlignment) {
auto* effect = auto* effect =
GetTwoFrameEffect(CSSPropertyID::kTransform, "scale(2)", "scale(3)"); GetTwoFrameEffect(CSSPropertyID::kTransform, "scale(2)", "scale(3)");
EXPECT_TRUE(effect->AnimationsPreserveAxisAlignment()); EXPECT_TRUE(effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
} }
TEST_F(KeyframeEffectTest, RotationTransformsDoNotPreserveAxisAlignment) { TEST_F(KeyframeEffectTest, RotationTransformsDoNotPreserveAxisAlignment) {
auto* effect = GetTwoFrameEffect(CSSPropertyID::kTransform, "rotate(10deg)", auto* effect = GetTwoFrameEffect(CSSPropertyID::kTransform, "rotate(10deg)",
"rotate(20deg)"); "rotate(20deg)");
EXPECT_FALSE(effect->AnimationsPreserveAxisAlignment()); EXPECT_FALSE(
effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
} }
TEST_F(KeyframeEffectTest, RotationsDoNotPreserveAxisAlignment) { TEST_F(KeyframeEffectTest, RotationsDoNotPreserveAxisAlignment) {
auto* effect = GetTwoFrameEffect(CSSPropertyID::kRotate, "10deg", "20deg"); auto* effect = GetTwoFrameEffect(CSSPropertyID::kRotate, "10deg", "20deg");
EXPECT_FALSE(effect->AnimationsPreserveAxisAlignment()); EXPECT_FALSE(
effect->UpdateBoxSizeAndCheckTransformAxisAlignment(FloatSize()));
} }
} // namespace blink } // namespace blink
...@@ -844,8 +844,8 @@ static bool NeedsTransform(const LayoutObject& object, ...@@ -844,8 +844,8 @@ static bool NeedsTransform(const LayoutObject& object,
return false; return false;
} }
static bool ActiveTransformAnimationIsAxisAligned( static bool UpdateBoxSizeAndCheckActiveAnimationAxisAlignment(
const LayoutObject& object, const LayoutBox& object,
CompositingReasons compositing_reasons) { CompositingReasons compositing_reasons) {
if (!(compositing_reasons & CompositingReason::kActiveTransformAnimation)) if (!(compositing_reasons & CompositingReason::kActiveTransformAnimation))
return false; return false;
...@@ -853,9 +853,10 @@ static bool ActiveTransformAnimationIsAxisAligned( ...@@ -853,9 +853,10 @@ static bool ActiveTransformAnimationIsAxisAligned(
if (!object.GetNode() || !object.GetNode()->IsElementNode()) if (!object.GetNode() || !object.GetNode()->IsElementNode())
return false; return false;
const Element* element = To<Element>(object.GetNode()); const Element* element = To<Element>(object.GetNode());
const auto* animations = element->GetElementAnimations(); auto* animations = element->GetElementAnimations();
DCHECK(animations); DCHECK(animations);
return animations->AnimationsPreserveAxisAlignment(); return animations->UpdateBoxSizeAndCheckTransformAxisAlignment(
FloatSize(object.Size()));
} }
void FragmentPaintPropertyTreeBuilder::UpdateTransform() { void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
...@@ -912,8 +913,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() { ...@@ -912,8 +913,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
// calculate most of the compositable animation reasons up front to // calculate most of the compositable animation reasons up front to
// only consider animations which are candidates for compositing. // only consider animations which are candidates for compositing.
state.flags.animation_is_axis_aligned = state.flags.animation_is_axis_aligned =
ActiveTransformAnimationIsAxisAligned( UpdateBoxSizeAndCheckActiveAnimationAxisAlignment(
object_, full_context_.direct_compositing_reasons); box, full_context_.direct_compositing_reasons);
} }
state.direct_compositing_reasons = state.direct_compositing_reasons =
......
...@@ -6355,12 +6355,7 @@ crbug.com/1083605 media/controls-styling-strict.html [ Pass Failure ] ...@@ -6355,12 +6355,7 @@ crbug.com/1083605 media/controls-styling-strict.html [ Pass Failure ]
# Transform animation reftests # Transform animation reftests
crbug.com/1133901 virtual/threaded/external/wpt/css/css-transforms/animation/transform-interpolation-translate-em.html [ Failure ] crbug.com/1133901 virtual/threaded/external/wpt/css/css-transforms/animation/transform-interpolation-translate-em.html [ Failure ]
# Composited Transform animations WIP:
# Existing failure
crbug.com/1133901 virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/transform-interpolation-translate-em.html [ Failure ] crbug.com/1133901 virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/transform-interpolation-translate-em.html [ Failure ]
# Failures from incomplete implementation
crbug.com/389359 virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/transform-interpolation-translate.html [ Failure ]
crbug.com/1136163 [ Linux ] external/wpt/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html [ Failure ] crbug.com/1136163 [ Linux ] external/wpt/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html [ Failure ]
......
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