0

Added support for composited progress based animations

Composited progress based animations were still using specified timing
instead of the recently added normalized timing. This change makes it so
the correct timings are now being passed to the compositor.

Removed timeRange from composited progress based animation tests.

Bug: 1216655, 1140602

Change-Id: Iba862da3645e3c8856be8f7de01140952abd168f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3086410
Commit-Queue: Jordan Taylor <jortaylo@microsoft.com>
Reviewed-by: Robert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#912769}
This commit is contained in:
Jordan Taylor
2021-08-17 22:20:59 +00:00
committed by Chromium LUCI CQ
parent 595adab982
commit ac059d80d2
21 changed files with 318 additions and 184 deletions

@ -260,7 +260,8 @@ bool Animation1TimeEquals20(MutatorInputState* input) {
return in && in->added_and_updated_animations.size() == 1 &&
in->added_and_updated_animations[0]
.worklet_animation_id.animation_id == 22 &&
in->added_and_updated_animations[0].current_time == 20;
in->added_and_updated_animations[0].current_time ==
0.2 * ScrollTimeline::kScrollTimelineDurationMs;
}
void CreateScrollingNodeForElement(ElementId element_id,
@ -331,12 +332,12 @@ TEST_F(AnimationHostTest, LayerTreeMutatorUpdateReflectsScrollAnimations) {
host_impl_->AddToTicking(mock_scroll_animation);
// Create scroll timeline that links scroll animation and worklet animation
// together. Use timerange so that we have 1:1 time & scroll mapping.
// together.
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0);
scroll_offsets.push_back(100);
auto scroll_timeline = ScrollTimeline::Create(
element_id, ScrollTimeline::ScrollDown, scroll_offsets, 100);
element_id, ScrollTimeline::ScrollDown, scroll_offsets);
// Create a worklet animation that is bound to the scroll timeline.
scoped_refptr<WorkletAnimation> worklet_animation(
@ -379,7 +380,7 @@ TEST_F(AnimationHostTest, TickScrollLinkedAnimation) {
scroll_offsets.push_back(0);
scroll_offsets.push_back(100);
auto scroll_timeline = ScrollTimeline::Create(
element_id_, ScrollTimeline::ScrollDown, scroll_offsets, 1000);
element_id_, ScrollTimeline::ScrollDown, scroll_offsets);
int animation_id = 11;
// Create an animation that is bound to the scroll timeline.
@ -404,8 +405,8 @@ TEST_F(AnimationHostTest, TickScrollLinkedAnimation) {
EXPECT_EQ(keyframe_model->run_state(), KeyframeModel::STARTING);
double tick_time = (scroll_timeline->CurrentTime(scroll_tree, false).value() -
base::TimeTicks())
.InSecondsF();
EXPECT_EQ(tick_time, 0.2);
.InMillisecondsF();
EXPECT_EQ(tick_time, 0.2 * ScrollTimeline::kScrollTimelineDurationMs);
scroll_timeline->DetachAnimation(animation);
EXPECT_FALSE(host_impl_->TickAnimations(base::TimeTicks(),
@ -458,7 +459,7 @@ TEST_F(AnimationHostTest, ScrollTimelineOffsetUpdatedByScrollAnimation) {
scroll_offsets.push_back(100);
auto scroll_timeline = ScrollTimeline::Create(
element_id_, ScrollTimeline::ScrollDown, scroll_offsets, 1000);
element_id_, ScrollTimeline::ScrollDown, scroll_offsets);
host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree,
false);
@ -466,8 +467,8 @@ TEST_F(AnimationHostTest, ScrollTimelineOffsetUpdatedByScrollAnimation) {
double tick_time =
(scroll_timeline->CurrentTime(property_trees.scroll_tree, false).value() -
base::TimeTicks())
.InSecondsF();
EXPECT_EQ(tick_time, 0.2);
.InMillisecondsF();
EXPECT_EQ(tick_time, 0.2 * ScrollTimeline::kScrollTimelineDurationMs);
}
} // namespace

@ -40,13 +40,11 @@ template double ComputeProgress<std::vector<double>>(
ScrollTimeline::ScrollTimeline(absl::optional<ElementId> scroller_id,
ScrollDirection direction,
const std::vector<double> scroll_offsets,
double time_range,
int animation_timeline_id)
: AnimationTimeline(animation_timeline_id),
pending_id_(scroller_id),
direction_(direction),
scroll_offsets_(scroll_offsets),
time_range_(time_range) {
scroll_offsets_(scroll_offsets) {
DCHECK(ValidateScrollOffsets(scroll_offsets_));
}
@ -55,16 +53,15 @@ ScrollTimeline::~ScrollTimeline() = default;
scoped_refptr<ScrollTimeline> ScrollTimeline::Create(
absl::optional<ElementId> scroller_id,
ScrollTimeline::ScrollDirection direction,
const std::vector<double> scroll_offsets,
double time_range) {
const std::vector<double> scroll_offsets) {
return base::WrapRefCounted(
new ScrollTimeline(scroller_id, direction, scroll_offsets, time_range,
new ScrollTimeline(scroller_id, direction, scroll_offsets,
AnimationIdProvider::NextTimelineId()));
}
scoped_refptr<AnimationTimeline> ScrollTimeline::CreateImplInstance() const {
return base::WrapRefCounted(new ScrollTimeline(
pending_id_, direction_, scroll_offsets_, time_range_, id()));
return base::WrapRefCounted(
new ScrollTimeline(pending_id_, direction_, scroll_offsets_, id()));
}
bool ScrollTimeline::IsActive(const ScrollTree& scroll_tree,
@ -135,18 +132,19 @@ absl::optional<base::TimeTicks> ScrollTimeline::CurrentTime(
// 4. If current scroll offset is greater than or equal to endScrollOffset:
if (current_offset >= resolved_end_scroll_offset) {
return base::TimeTicks() + base::TimeDelta::FromMillisecondsD(time_range_);
return base::TimeTicks() +
base::TimeDelta::FromMillisecondsD(kScrollTimelineDurationMs);
}
// Otherwise,
// 5.1 Let progress be a result of applying calculate scroll timeline progress
// procedure for current scroll offset.
// 5.2 The current time is the result of evaluating the following expression:
// progress × effective time range
// progress × timeline duration to get the percentage
return base::TimeTicks() + base::TimeDelta::FromMillisecondsD(
ComputeProgress<std::vector<double>>(
current_offset, scroll_offsets_) *
time_range_);
kScrollTimelineDurationMs);
}
void ScrollTimeline::PushPropertiesTo(AnimationTimeline* impl_timeline) {

@ -35,17 +35,19 @@ class CC_ANIMATION_EXPORT ScrollTimeline : public AnimationTimeline {
ScrollRight,
};
// 100% is represented as 100s or 100000ms. We store it here in Milliseconds
// because that is the time unit returned by functions like CurrentTime.
static constexpr double kScrollTimelineDurationMs = 100000;
ScrollTimeline(absl::optional<ElementId> scroller_id,
ScrollDirection direction,
const std::vector<double> scroll_offsets,
double time_range,
int animation_timeline_id);
static scoped_refptr<ScrollTimeline> Create(
absl::optional<ElementId> scroller_id,
ScrollDirection direction,
const std::vector<double> scroll_offsets,
double time_range);
const std::vector<double> scroll_offsets);
// Create a copy of this ScrollTimeline intended for the impl thread in the
// compositor.
@ -89,7 +91,6 @@ class CC_ANIMATION_EXPORT ScrollTimeline : public AnimationTimeline {
return absl::nullopt;
return scroll_offsets_[1];
}
double GetTimeRangeForTest() const { return time_range_; }
bool IsScrollTimeline() const override;
@ -110,11 +111,6 @@ class CC_ANIMATION_EXPORT ScrollTimeline : public AnimationTimeline {
// This defines scroll ranges of the scroller that the ScrollTimeline is
// active within. If no ranges are defined the timeline is inactive.
std::vector<double> scroll_offsets_;
// A ScrollTimeline maps from the scroll offset in the scroller to a time
// value based on a 'time range'. See the implementation of CurrentTime or the
// spec for details.
double time_range_;
};
inline ScrollTimeline* ToScrollTimeline(AnimationTimeline* timeline) {

@ -64,11 +64,10 @@ void CreateScrollingElement(PropertyTrees* property_trees,
// https://wicg.github.io/scroll-animations/#current-time-algorithm
double CalculateCurrentTime(double current_scroll_offset,
double start_scroll_offset,
double end_scroll_offset,
double effective_time_range) {
double end_scroll_offset) {
return ((current_scroll_offset - start_scroll_offset) /
(end_scroll_offset - start_scroll_offset)) *
effective_time_range;
ScrollTimeline::kScrollTimelineDurationMs;
}
// Helper method to convert base::TimeTicks to double.
@ -112,19 +111,14 @@ class ScrollTimelineTest : public ::testing::Test {
};
TEST_F(ScrollTimelineTest, BasicCurrentTimeCalculations) {
// For simplicity, we set the time range such that the current time maps
// directly to the scroll offset. We have a square scroller/contents, so can
// just compute one edge and use it for vertical/horizontal.
double time_range = content_size().height() - container_size().height();
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0);
scroll_offsets.push_back(time_range);
scroll_offsets.push_back(100);
scoped_refptr<ScrollTimeline> vertical_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
scoped_refptr<ScrollTimeline> horizontal_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollRight, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollRight, scroll_offsets);
// Unscrolled, both timelines should read a current time of 0.
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset());
@ -136,139 +130,126 @@ TEST_F(ScrollTimelineTest, BasicCurrentTimeCalculations) {
// Now do some scrolling and make sure that the ScrollTimelines update.
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(75, 50));
// As noted above, we have mapped the time range such that current time should
// just be the scroll offset.
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
50, vertical_timeline->CurrentTime(scroll_tree(), false));
0.5 * ScrollTimeline::kScrollTimelineDurationMs,
vertical_timeline->CurrentTime(scroll_tree(), false));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
75, horizontal_timeline->CurrentTime(scroll_tree(), false));
0.75 * ScrollTimeline::kScrollTimelineDurationMs,
horizontal_timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, MultipleScrollOffsetsCurrentTimeCalculations) {
// For simplicity, we set the time range such that the current time maps
// directly to the scroll offset. We have a square scroller/contents, so can
// just compute one edge and use it for vertical/horizontal.
double time_range =
double scroll_size =
content_size().height() - container_size().height(); // 400
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0);
scroll_offsets.push_back(100.0);
scroll_offsets.push_back(250.0);
scroll_offsets.push_back(time_range);
scroll_offsets.push_back(scroll_size);
scoped_refptr<ScrollTimeline> vertical_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
unsigned int offset = 0;
double w = 1.0 / 3.0; // offset weight
double p = 0; // progress within the offset
// Scale necessary to convert absolute unit times to progress based values
double scale = ScrollTimeline::kScrollTimelineDurationMs / scroll_size;
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset());
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
(offset + p) * w * time_range,
(offset + p) * w * scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
p = (70.0 - 0.0) / (100.0 - 0.0);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 70));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
(offset + p) * w * time_range,
(offset + p) * w * scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
offset = 1;
p = 0;
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 100));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
(offset + p) * w * time_range,
(offset + p) * w * scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
p = (150.0 - 100.0) / (250.0 - 100.0);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 150));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
(offset + p) * w * time_range,
(offset + p) * w * scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
offset = 2;
p = 0;
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 250));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
(offset + p) * w * time_range,
(offset + p) * w * scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
p = (350.0 - 250.0) / (400.0 - 250.0);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 350));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
(offset + p) * w * time_range,
(offset + p) * w * scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 400));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
time_range, vertical_timeline->CurrentTime(scroll_tree(), false));
ScrollTimeline::kScrollTimelineDurationMs,
vertical_timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, OverlappingScrollOffsets) {
double time_range = 100.0;
double scroll_size = 100.0;
// Start offset is greater than end offset ==> animation progress is
// either 0% or 100%.
std::vector<double> scroll_offsets = {350.0, 200.0, 50.0};
scoped_refptr<ScrollTimeline> vertical_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
// Offset is less than start offset ==> current time is 0.
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 300));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
0, vertical_timeline->CurrentTime(scroll_tree(), false));
// Offset is greater than end offset ==> current time is time_range.
// Scale necessary to convert absolute unit times to progress based values
double scale = ScrollTimeline::kScrollTimelineDurationMs / scroll_size;
// Offset is greater than end offset ==> current time is 100%.
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 360));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
time_range, vertical_timeline->CurrentTime(scroll_tree(), false));
scroll_size * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
scroll_offsets = {0.0, 400.0, 200.0};
vertical_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 100));
// Scroll offset is 25% of [0, 400) range, which maps to [0% 50%) of the
// entire scroll range.
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
time_range * 0.5 * 0.25,
scroll_size * 0.5 * 0.25 * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
scroll_offsets = {200.0, 0.0, 400.0};
vertical_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 300));
// Scroll offset is 75% of [0, 400) range, which maps to [50% 100%) of the
// entire scroll range.
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
time_range * (0.5 + 0.5 * 0.75),
scroll_size * (0.5 + 0.5 * 0.75) * scale,
vertical_timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, CurrentTimeIsAdjustedForTimeRange) {
double time_range = content_size().height() - container_size().height();
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0);
scroll_offsets.push_back(time_range);
// Here we set a time range to 100, which gives the current time the form of
// 'percentage scrolled'.
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, 100);
double halfwayY = time_range / 2.;
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, halfwayY));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(50,
timeline->CurrentTime(scroll_tree(), false));
}
// This test ensures that the ScrollTimeline's active scroller id is correct. We
// had a few crashes caused by assuming that the id would be available in the
// active tree before the activation happened; see http://crbug.com/853231
@ -289,16 +270,17 @@ TEST_F(ScrollTimelineTest, ActiveTimeIsSetOnlyAfterPromotion) {
CreateScrollingElement(&pending_tree, scroller_id, content_size(),
container_size());
double time_range = content_size().height() - container_size().height();
double scroll_size = content_size().height() - container_size().height();
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0);
scroll_offsets.push_back(time_range);
scroll_offsets.push_back(scroll_size);
double halfwayY = time_range / 2.;
double halfwayY = scroll_size / 2.;
double expectedTime = 0.5 * ScrollTimeline::kScrollTimelineDurationMs;
SetScrollOffset(&pending_tree, scroller_id, gfx::ScrollOffset(0, halfwayY));
scoped_refptr<ScrollTimeline> main_timeline = ScrollTimeline::Create(
scroller_id, ScrollTimeline::ScrollDown, scroll_offsets, 100);
scroller_id, ScrollTimeline::ScrollDown, scroll_offsets);
// Now create an impl version of the ScrollTimeline. Initially this should
// only have a pending scroller id, as the active tree may not yet have the
@ -309,7 +291,8 @@ TEST_F(ScrollTimelineTest, ActiveTimeIsSetOnlyAfterPromotion) {
EXPECT_TRUE(std::isnan(
ToDouble(impl_timeline->CurrentTime(active_tree.scroll_tree, true))));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
50, impl_timeline->CurrentTime(pending_tree.scroll_tree, false));
expectedTime,
impl_timeline->CurrentTime(pending_tree.scroll_tree, false));
// Now fake a tree activation; this should cause the ScrollTimeline to update
// its active scroller id. Note that we deliberately pass in the pending_tree
@ -317,18 +300,19 @@ TEST_F(ScrollTimelineTest, ActiveTimeIsSetOnlyAfterPromotion) {
// implement tree swapping just for the test.
impl_timeline->ActivateTimeline();
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
50, impl_timeline->CurrentTime(pending_tree.scroll_tree, true));
expectedTime, impl_timeline->CurrentTime(pending_tree.scroll_tree, true));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
50, impl_timeline->CurrentTime(pending_tree.scroll_tree, false));
expectedTime,
impl_timeline->CurrentTime(pending_tree.scroll_tree, false));
}
TEST_F(ScrollTimelineTest, CurrentTimeIsAdjustedForPixelSnapping) {
double time_range = content_size().height() - container_size().height();
double scroll_size = content_size().height() - container_size().height();
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0);
scroll_offsets.push_back(time_range);
scroll_offsets.push_back(scroll_size);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 50));
@ -338,18 +322,21 @@ TEST_F(ScrollTimelineTest, CurrentTimeIsAdjustedForPixelSnapping) {
property_trees().transform_tree.FindNodeFromElementId(scroller_id());
transform_node->snap_amount = gfx::Vector2dF(0, 0.5);
EXPECT_SCROLL_TIMELINE_TIME_NEAR(49.5,
// Scale necessary to convert absolute unit times to progress based values
double scale = ScrollTimeline::kScrollTimelineDurationMs / scroll_size;
EXPECT_SCROLL_TIMELINE_TIME_NEAR(49.5 * scale,
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, CurrentTimeHandlesStartScrollOffset) {
double time_range = content_size().height() - container_size().height();
double scroll_size = content_size().height() - container_size().height();
const double start_scroll_offset = 20;
std::vector<double> scroll_offsets;
scroll_offsets.push_back(start_scroll_offset);
scroll_offsets.push_back(time_range);
scroll_offsets.push_back(scroll_size);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
// Unscrolled, the timeline should read a current time of 0 since the current
// offset (0) will be less than the startScrollOffset.
@ -367,96 +354,94 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesStartScrollOffset) {
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 50));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
CalculateCurrentTime(50, start_scroll_offset, time_range, time_range),
CalculateCurrentTime(50, start_scroll_offset, scroll_size),
timeline->CurrentTime(scroll_tree(), false));
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 200));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
CalculateCurrentTime(200, start_scroll_offset, time_range, time_range),
CalculateCurrentTime(200, start_scroll_offset, scroll_size),
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, CurrentTimeHandlesEndScrollOffset) {
double time_range = content_size().height() - container_size().height();
const double end_scroll_offset = time_range - 20;
double scroll_size = content_size().height() - container_size().height();
const double end_scroll_offset = scroll_size - 20;
std::vector<double> scroll_offsets;
scroll_offsets.push_back(0); // should be absl::nullopt
scroll_offsets.push_back(end_scroll_offset);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, time_range));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(time_range,
gfx::ScrollOffset(0, scroll_size));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs,
timeline->CurrentTime(scroll_tree(), false));
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, time_range - 20));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(time_range,
gfx::ScrollOffset(0, scroll_size - 20));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs,
timeline->CurrentTime(scroll_tree(), false));
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, time_range - 50));
gfx::ScrollOffset(0, scroll_size - 50));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
CalculateCurrentTime(time_range - 50, 0, end_scroll_offset, time_range),
CalculateCurrentTime(scroll_size - 50, 0, end_scroll_offset),
timeline->CurrentTime(scroll_tree(), false));
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, time_range - 200));
gfx::ScrollOffset(0, scroll_size - 200));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
CalculateCurrentTime(time_range - 200, 0, end_scroll_offset, time_range),
CalculateCurrentTime(scroll_size - 200, 0, end_scroll_offset),
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, CurrentTimeHandlesCombinedStartAndEndScrollOffset) {
double time_range = content_size().height() - container_size().height();
double scroll_size = content_size().height() - container_size().height();
double start_scroll_offset = 20;
double end_scroll_offset = time_range - 50;
double end_scroll_offset = scroll_size - 50;
std::vector<double> scroll_offsets;
scroll_offsets.push_back(start_scroll_offset);
scroll_offsets.push_back(end_scroll_offset);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, time_range - 150));
gfx::ScrollOffset(0, scroll_size - 150));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(
CalculateCurrentTime(time_range - 150, start_scroll_offset,
end_scroll_offset, time_range),
CalculateCurrentTime(scroll_size - 150, start_scroll_offset,
end_scroll_offset),
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, CurrentTimeHandlesEqualStartAndEndScrollOffset) {
double time_range = content_size().height() - container_size().height();
std::vector<double> scroll_offsets;
scroll_offsets.push_back(20);
scroll_offsets.push_back(20);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 150));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(time_range,
EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs,
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest,
CurrentTimeHandlesStartOffsetLargerThanEndScrollOffset) {
double time_range = content_size().height() - container_size().height();
std::vector<double> scroll_offsets;
scroll_offsets.push_back(50);
scroll_offsets.push_back(10);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 40));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(0,
timeline->CurrentTime(scroll_tree(), false));
SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 150));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(time_range,
EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs,
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, CurrentTimeHandlesScrollOffsets) {
const double time_range = 100;
const double start_scroll_offset = 20;
const double scroller_height =
content_size().height() - container_size().height();
@ -466,7 +451,7 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesScrollOffsets) {
scroll_offsets.push_back(end_scroll_offset);
scoped_refptr<ScrollTimeline> timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, time_range);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
// Before the start_scroll_offset the current time should be 0
SetScrollOffset(&property_trees(), scroller_id(),
@ -474,27 +459,27 @@ TEST_F(ScrollTimelineTest, CurrentTimeHandlesScrollOffsets) {
EXPECT_SCROLL_TIMELINE_TIME_NEAR(0,
timeline->CurrentTime(scroll_tree(), false));
// At the end_scroll_offset the current time should be time-range
// At the end_scroll_offset the current time should be 100%
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, end_scroll_offset));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(time_range,
EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs,
timeline->CurrentTime(scroll_tree(), false));
// After the end_scroll_offset the current time should be time-range
// After the end_scroll_offset the current time should be 100%
SetScrollOffset(&property_trees(), scroller_id(),
gfx::ScrollOffset(0, end_scroll_offset + 10));
EXPECT_SCROLL_TIMELINE_TIME_NEAR(time_range,
EXPECT_SCROLL_TIMELINE_TIME_NEAR(ScrollTimeline::kScrollTimelineDurationMs,
timeline->CurrentTime(scroll_tree(), false));
}
TEST_F(ScrollTimelineTest, Activeness) {
// ScrollTimeline with zero scroller id is inactive.
std::vector<double> scroll_offsets;
double time_range = content_size().height() - container_size().height();
double scroll_size = content_size().height() - container_size().height();
scroll_offsets.push_back(0);
scroll_offsets.push_back(time_range);
scroll_offsets.push_back(scroll_size);
scoped_refptr<ScrollTimeline> inactive_timeline1 = ScrollTimeline::Create(
absl::nullopt, ScrollTimeline::ScrollDown, scroll_offsets, 100);
absl::nullopt, ScrollTimeline::ScrollDown, scroll_offsets);
EXPECT_FALSE(
inactive_timeline1->IsActive(scroll_tree(), false /*is_active_tree*/));
EXPECT_FALSE(
@ -503,7 +488,7 @@ TEST_F(ScrollTimelineTest, Activeness) {
// ScrollTimeline with a scroller that is not in the scroll tree is
// inactive.
scoped_refptr<ScrollTimeline> inactive_timeline2 = ScrollTimeline::Create(
ElementId(2), ScrollTimeline::ScrollDown, scroll_offsets, 100);
ElementId(2), ScrollTimeline::ScrollDown, scroll_offsets);
EXPECT_FALSE(
inactive_timeline2->IsActive(scroll_tree(), false /*is_active_tree*/));
// Activate the scroll tree.
@ -514,7 +499,7 @@ TEST_F(ScrollTimelineTest, Activeness) {
// ScrollTimeline with empty scroll offsets is inactive.
std::vector<double> empty_scroll_offsets;
scoped_refptr<ScrollTimeline> inactive_timeline3 = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, empty_scroll_offsets, 100);
scroller_id(), ScrollTimeline::ScrollDown, empty_scroll_offsets);
EXPECT_FALSE(
inactive_timeline3->IsActive(scroll_tree(), false /*is_active_tree*/));
EXPECT_FALSE(
@ -528,7 +513,7 @@ TEST_F(ScrollTimelineTest, Activeness) {
inactive_timeline3->IsActive(scroll_tree(), true /*is_active_tree*/));
scoped_refptr<ScrollTimeline> active_timeline = ScrollTimeline::Create(
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets, 100);
scroller_id(), ScrollTimeline::ScrollDown, scroll_offsets);
EXPECT_TRUE(
active_timeline->IsActive(scroll_tree(), false /*is_active_tree*/));
EXPECT_FALSE(

@ -60,7 +60,6 @@ class MockScrollTimeline : public ScrollTimeline {
: ScrollTimeline(ElementId(),
ScrollTimeline::ScrollDown,
std::vector<double>(),
0,
AnimationIdProvider::NextTimelineId()) {}
MOCK_CONST_METHOD2(CurrentTime,
absl::optional<base::TimeTicks>(const ScrollTree&, bool));

@ -238,6 +238,7 @@ CompositorAnimations::CompositorElementNamespaceForProperty(
CompositorAnimations::FailureReasons
CompositorAnimations::CheckCanStartEffectOnCompositor(
const Timing& timing,
const Timing::NormalizedTiming& normalized_timing,
const Element& target_element,
const Animation* animation_to_add,
const EffectModel& effect,
@ -441,7 +442,7 @@ CompositorAnimations::CheckCanStartEffectOnCompositor(
base::TimeDelta time_offset =
animation_to_add ? animation_to_add->ComputeCompositorTimeOffset()
: base::TimeDelta();
if (!ConvertTimingForCompositor(timing, time_offset, out,
if (!ConvertTimingForCompositor(timing, normalized_timing, time_offset, out,
animation_playback_rate)) {
reasons |= kEffectHasUnsupportedTimingParameters;
}
@ -551,6 +552,7 @@ CompositorAnimations::CheckCanStartElementOnCompositor(
CompositorAnimations::FailureReasons
CompositorAnimations::CheckCanStartAnimationOnCompositor(
const Timing& timing,
const Timing::NormalizedTiming& normalized_timing,
const Element& target_element,
const Animation* animation_to_add,
const EffectModel& effect,
@ -558,7 +560,7 @@ CompositorAnimations::CheckCanStartAnimationOnCompositor(
double animation_playback_rate,
PropertyHandleSet* unsupported_properties) {
FailureReasons reasons = CheckCanStartEffectOnCompositor(
timing, target_element, animation_to_add, effect,
timing, normalized_timing, target_element, animation_to_add, effect,
paint_artifact_compositor, animation_playback_rate,
unsupported_properties);
return reasons | CheckCanStartElementOnCompositor(target_element, effect);
@ -609,6 +611,7 @@ void CompositorAnimations::StartAnimationOnCompositor(
absl::optional<double> start_time,
base::TimeDelta time_offset,
const Timing& timing,
const Timing::NormalizedTiming& normalized_timing,
const Animation* animation,
CompositorAnimation& compositor_animation,
const EffectModel& effect,
@ -617,17 +620,17 @@ void CompositorAnimations::StartAnimationOnCompositor(
DCHECK(started_keyframe_model_ids.IsEmpty());
// TODO(petermayo): Pass the PaintArtifactCompositor before
// BlinkGenPropertyTrees is always on.
DCHECK_EQ(
CheckCanStartAnimationOnCompositor(timing, element, animation, effect,
nullptr, animation_playback_rate),
kNoFailure);
DCHECK_EQ(CheckCanStartAnimationOnCompositor(
timing, normalized_timing, element, animation, effect, nullptr,
animation_playback_rate),
kNoFailure);
const auto& keyframe_effect = To<KeyframeEffectModelBase>(effect);
Vector<std::unique_ptr<CompositorKeyframeModel>> keyframe_models;
GetAnimationOnCompositor(element, timing, group, start_time, time_offset,
keyframe_effect, keyframe_models,
animation_playback_rate);
GetAnimationOnCompositor(element, timing, normalized_timing, group,
start_time, time_offset, keyframe_effect,
keyframe_models, animation_playback_rate);
DCHECK(!keyframe_models.IsEmpty());
for (auto& compositor_keyframe_model : keyframe_models) {
int id = compositor_keyframe_model->Id();
@ -687,6 +690,7 @@ void CompositorAnimations::AttachCompositedLayers(
bool CompositorAnimations::ConvertTimingForCompositor(
const Timing& timing,
const Timing::NormalizedTiming& normalized_timing,
base::TimeDelta time_offset,
CompositorTiming& out,
double animation_playback_rate) {
@ -696,18 +700,19 @@ bool CompositorAnimations::ConvertTimingForCompositor(
return false;
// FIXME: Compositor does not know anything about endDelay.
if (!timing.end_delay.is_zero())
if (!normalized_timing.end_delay.is_zero())
return false;
if (!timing.iteration_duration || !timing.iteration_count ||
timing.iteration_duration->is_zero() ||
timing.iteration_duration->is_max())
if (!timing.iteration_count ||
normalized_timing.iteration_duration.is_zero() ||
normalized_timing.iteration_duration.is_max())
return false;
// Compositor's time offset is positive for seeking into the animation.
DCHECK(animation_playback_rate);
double delay =
animation_playback_rate > 0 ? timing.start_delay.InSecondsF() : 0;
double delay = animation_playback_rate > 0
? normalized_timing.start_delay.InSecondsF()
: 0;
base::TimeDelta scaled_delay =
base::TimeDelta::FromSecondsD(delay / animation_playback_rate);
@ -729,7 +734,7 @@ bool CompositorAnimations::ConvertTimingForCompositor(
out.adjusted_iteration_count = std::isfinite(timing.iteration_count)
? timing.iteration_count
: std::numeric_limits<double>::infinity();
out.scaled_duration = timing.iteration_duration.value();
out.scaled_duration = normalized_timing.iteration_duration;
out.direction = timing.direction;
out.playback_rate = animation_playback_rate;
@ -823,6 +828,7 @@ void AddKeyframesToCurve(PlatformAnimationCurveType& curve,
void CompositorAnimations::GetAnimationOnCompositor(
const Element& target_element,
const Timing& timing,
const Timing::NormalizedTiming& normalized_timing,
int group,
absl::optional<double> start_time,
base::TimeDelta time_offset,
@ -831,8 +837,9 @@ void CompositorAnimations::GetAnimationOnCompositor(
double animation_playback_rate) {
DCHECK(keyframe_models.IsEmpty());
CompositorTiming compositor_timing;
bool timing_valid = ConvertTimingForCompositor(
timing, time_offset, compositor_timing, animation_playback_rate);
bool timing_valid =
ConvertTimingForCompositor(timing, normalized_timing, time_offset,
compositor_timing, animation_playback_rate);
ALLOW_UNUSED_LOCAL(timing_valid);
PropertyHandleSet properties = effect.Properties();

@ -112,6 +112,7 @@ class CORE_EXPORT CompositorAnimations {
static FailureReasons CheckCanStartAnimationOnCompositor(
const Timing&,
const Timing::NormalizedTiming&,
const Element&,
const Animation*,
const EffectModel&,
@ -131,6 +132,7 @@ class CORE_EXPORT CompositorAnimations {
absl::optional<double> start_time,
base::TimeDelta time_offset,
const Timing&,
const Timing::NormalizedTiming&,
const Animation*,
CompositorAnimation&,
const EffectModel&,
@ -159,6 +161,7 @@ class CORE_EXPORT CompositorAnimations {
};
static bool ConvertTimingForCompositor(const Timing&,
const Timing::NormalizedTiming&,
base::TimeDelta time_offset,
CompositorTiming& out,
double animation_playback_rate);
@ -166,6 +169,7 @@ class CORE_EXPORT CompositorAnimations {
static void GetAnimationOnCompositor(
const Element&,
const Timing&,
const Timing::NormalizedTiming&,
int group,
absl::optional<double> start_time,
base::TimeDelta time_offset,
@ -183,6 +187,7 @@ class CORE_EXPORT CompositorAnimations {
private:
static FailureReasons CheckCanStartEffectOnCompositor(
const Timing&,
const Timing::NormalizedTiming&,
const Element&,
const Animation*,
const EffectModel&,

@ -181,7 +181,7 @@ class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
CompositorAnimations::CompositorTiming& out,
double playback_rate = 1) {
return CompositorAnimations::ConvertTimingForCompositor(
t, base::TimeDelta(), out, playback_rate);
t, NormalizedTiming(t), base::TimeDelta(), out, playback_rate);
}
CompositorAnimations::FailureReasons CanStartEffectOnCompositor(
@ -204,8 +204,8 @@ class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
const PaintArtifactCompositor* paint_artifact_compositor =
GetDocument().View()->GetPaintArtifactCompositor();
return CompositorAnimations::CheckCanStartEffectOnCompositor(
timing, element, animation, effect_model, paint_artifact_compositor, 1,
unsupported_properties);
timing, NormalizedTiming(timing), element, animation, effect_model,
paint_artifact_compositor, 1, unsupported_properties);
}
CompositorAnimations::FailureReasons CheckCanStartElementOnCompositor(
@ -221,8 +221,8 @@ class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
Vector<std::unique_ptr<CompositorKeyframeModel>>& keyframe_models,
double animation_playback_rate) {
CompositorAnimations::GetAnimationOnCompositor(
*element_, timing, 0, absl::nullopt, base::TimeDelta(), effect,
keyframe_models, animation_playback_rate);
*element_, timing, NormalizedTiming(timing), 0, absl::nullopt,
base::TimeDelta(), effect, keyframe_models, animation_playback_rate);
}
CompositorAnimations::FailureReasons
@ -251,6 +251,32 @@ class AnimationCompositorAnimationsTest : public PaintTestConfigurations,
return timing;
}
// Simplified version of what happens in AnimationEffect::NormalizedTiming()
Timing::NormalizedTiming NormalizedTiming(Timing timing) {
Timing::NormalizedTiming normalized_timing;
normalized_timing.start_delay = timing.start_delay;
normalized_timing.end_delay = timing.end_delay;
// Currently, compositor animation tests are using document timelines
// exclusively. In order to support scroll timelines, the algorithm would
// need to correct for the intrinsic iteration duration of the timeline.
EXPECT_TRUE(timeline_->IsDocumentTimeline());
normalized_timing.iteration_duration =
timing.iteration_duration.value_or(AnimationTimeDelta());
normalized_timing.active_duration =
normalized_timing.iteration_duration * timing.iteration_count;
normalized_timing.end_time = std::max(
normalized_timing.start_delay + normalized_timing.active_duration +
normalized_timing.end_delay,
AnimationTimeDelta());
return normalized_timing;
}
StringKeyframe* CreateReplaceOpKeyframe(CSSPropertyID id,
const String& value,
double offset = 0) {

@ -341,8 +341,8 @@ KeyframeEffect::CheckCanStartAnimationOnCompositor(
reasons |= CompositorAnimations::kTargetHasMultipleTransformProperties;
reasons |= CompositorAnimations::CheckCanStartAnimationOnCompositor(
SpecifiedTiming(), *effect_target_, GetAnimation(), *Model(),
paint_artifact_compositor, animation_playback_rate,
SpecifiedTiming(), NormalizedTiming(), *effect_target_, GetAnimation(),
*Model(), paint_artifact_compositor, animation_playback_rate,
unsupported_properties);
}
@ -368,7 +368,7 @@ void KeyframeEffect::StartAnimationOnCompositor(
CompositorAnimations::StartAnimationOnCompositor(
*effect_target_, group, start_time, time_offset, SpecifiedTiming(),
GetAnimation(), *compositor_animation, *Model(),
NormalizedTiming(), GetAnimation(), *compositor_animation, *Model(),
compositor_keyframe_model_ids_, animation_playback_rate);
DCHECK(!compositor_keyframe_model_ids_.IsEmpty());
}

@ -32,8 +32,7 @@ scoped_refptr<CompositorScrollTimeline> ToCompositorScrollTimeline(
scroll_timeline->GetOrientation(), box ? box->Style() : nullptr);
return CompositorScrollTimeline::Create(
element_id, orientation, scroll_timeline->GetResolvedScrollOffsets(),
scroll_timeline->GetTimeRange());
element_id, orientation, scroll_timeline->GetResolvedScrollOffsets());
}
absl::optional<CompositorElementId> GetCompositorScrollElementId(

@ -62,10 +62,6 @@ TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimeline) {
ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
options->setScrollSource(scroller);
const double time_range = 100;
options->setTimeRange(
MakeGarbageCollected<V8UnionDoubleOrScrollTimelineAutoKeyword>(
time_range));
options->setOrientation("block");
options->setScrollOffsets({OffsetFromString(GetDocument(), "50px"),
OffsetFromString(GetDocument(), "auto")});
@ -76,7 +72,6 @@ TEST_F(ScrollTimelineUtilTest, ToCompositorScrollTimeline) {
ToCompositorScrollTimeline(timeline);
EXPECT_EQ(compositor_timeline->GetActiveIdForTest(), absl::nullopt);
EXPECT_EQ(compositor_timeline->GetPendingIdForTest(), element_id);
EXPECT_EQ(compositor_timeline->GetTimeRangeForTest(), time_range);
EXPECT_EQ(compositor_timeline->GetDirectionForTest(),
CompositorScrollTimeline::ScrollDown);
EXPECT_EQ(compositor_timeline->GetStartScrollOffsetForTest(), 50);

@ -7672,9 +7672,6 @@ crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/workle
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-local-time-before-start.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-set-timing.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-overflow-hidden.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-cancel.https.html [ Failure Pass ]
crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread.https.html [ Failure Pass ]
crbug.com/1233781 http/tests/serviceworker/window-close-during-registration.html [ Failure Pass ]
@ -7682,6 +7679,13 @@ crbug.com/1233792 virtual/synchronous_html_parser/http/tests/inspector-protocol/
crbug.com/1234057 [ Mac ] external/wpt/css/css-paint-api/no-op-animation.https.html [ Failure Pass ]
crbug.com/1234302 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/paint2d-image.https.html [ Failure Pass ]
# Temporarily disabling progress based worklet animation tests.
crbug.com/1238130 virtual/threaded/external/wpt/animation-worklet/inactive-timeline.https.html [ Timeout ]
crbug.com/1238130 virtual/threaded/external/wpt/animation-worklet/scroll-timeline-writing-modes.https.html [ Failure ]
crbug.com/1238130 virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Timeout ]
crbug.com/1238130 virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Failure ]
crbug.com/1238130 virtual/threaded-no-composited-antialiasing/animations/animationworklet/playback-rate-scroll-timeline-accelerated-property.html [ Timeout ]
# Sheriff 2021-07-29
crbug.com/626703 http/tests/security/cross-frame-access-put.html [ Failure Pass ]
crbug.com/626703 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/overdraw.https.html [ Failure Pass ]

@ -56,7 +56,8 @@
const scroller = document.getElementById('scroller');
scroller.classList.add('removed');
const timeline = new ScrollTimeline({ scrollSource: scroller, timeRange: 1000, orientation: 'block' });
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const animation = new Animation(effect, timeline);
animation.play();

@ -43,7 +43,8 @@
);
const scroller = document.scrollingElement;
const timeline = new ScrollTimeline({ scrollSource: scroller, timeRange: 1000, orientation: 'block' });
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const animation = new Animation(effect, timeline);
animation.play();

@ -51,7 +51,8 @@
);
const scroller = document.getElementById('scroller');
const timeline = new ScrollTimeline({ scrollSource: scroller, timeRange: 1000, orientation: 'block' });
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const animation = new Animation(effect, timeline);
animation.play();
@ -61,7 +62,7 @@
scroller.scrollTop = 0.5 * maxScroll;
waitForAnimationFrames(2).then(_ => {
takeScreenshot();
takeScreenshot();
});
});
</script>

@ -64,7 +64,6 @@ layout changes on percentage-based scroll offset">
const scroller = document.getElementById('scroller');
const timeline = new ScrollTimeline({
scrollSource: scroller,
timeRange: 1000,
scrollOffsets: [CSS.percent(20), CSS.percent(80)]
});
const animation = new Animation(effect, timeline);

@ -0,0 +1,45 @@
<!DOCTYPE html>
<title>Reference for Web Animation with scroll timeline and effect delay tests</title>
<style>
#box {
width: 100px;
height: 100px;
background-color: green;
transform: translate(0, 100px);
opacity: 0.5;
will-change: transform; /* force compositing */
}
#covered {
width: 100px;
height: 100px;
background-color: red;
}
#scroller {
overflow: auto;
height: 100px;
width: 100px;
will-change: transform; /* force compositing */
}
#contents {
height: 1000px;
width: 100%;
}
</style>
<div id="box"></div>
<div id="covered"></div>
<div id="scroller">
<div id="contents"></div>
</div>
<script>
window.addEventListener('load', function() {
// Move the scroller to halfway.
const scroller = document.getElementById("scroller");
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
scroller.scrollTop = 0.75 * maxScroll;
});
</script>

@ -0,0 +1,69 @@
<html class="reftest-wait">
<title>Animation effect delays should be accounted for when using a progress based timeline</title>
<link rel="help" href="https://drafts.csswg.org/scroll-animations/">
<meta name="assert" content="Effect delay should be accounted for by progress based animations">
<link rel="match" href="progress-based-effect-delay-ref.html">
<script src="/web-animations/testcommon.js"></script>
<script src="/common/reftest-wait.js"></script>
<style>
#box {
width: 100px;
height: 100px;
background-color: green;
}
#covered {
width: 100px;
height: 100px;
background-color: red;
}
#scroller {
overflow: auto;
height: 100px;
width: 100px;
will-change: transform; /* force compositing */
}
#contents {
height: 1000px;
width: 100%;
}
</style>
<div id="box"></div>
<div id="covered"></div>
<div id="scroller">
<div id="contents"><p>Scrolling Contents</p></div>
</div>
<script>
const box = document.getElementById('box');
const effect = new KeyframeEffect(box,
[
{ transform: 'translateY(0)', opacity: 1},
{ transform: 'translateY(200px)', opacity: 0}
], {
delay: 1000,
duration: 1000
}
);
const scroller = document.getElementById('scroller');
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const animation = new Animation(effect, timeline);
animation.play();
animation.ready.then(() => {
// Move the scroller to the halfway point.
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
scroller.scrollTop = 0.75 * maxScroll;
waitForAnimationFrames(2).then(_ => {
takeScreenshot();
});
});
</script>

@ -51,9 +51,10 @@
);
const scroller = document.getElementById('scroller');
const timeline = new ScrollTimeline({ scrollSource: scroller, timeRange: 1000, orientation: 'block' });
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const animation = new Animation(effect, timeline);
animation.currentTime = 0;
animation.currentTime = CSS.percent(0);
animation.play();
animation.ready.then(() => {
@ -62,7 +63,7 @@
scroller.scrollTop = 0.5 * maxScroll;
waitForAnimationFrames(2).then(_ => {
takeScreenshot();
takeScreenshot();
});
});
</script>

@ -60,7 +60,8 @@
);
const scroller = document.getElementById('scroller');
const timeline = new ScrollTimeline({ scrollSource: scroller, timeRange: 1000, orientation: 'block' });
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const animation = new Animation(effect, timeline);
const temporary_animation = new Animation(temporary_effect, timeline);
animation.play();
@ -75,7 +76,7 @@
scroller.scrollTop = 0.5 * maxScroll;
waitForAnimationFrames(2).then(_ => {
takeScreenshot();
takeScreenshot();
});
});
});

@ -60,7 +60,8 @@ drive two animations">
);
const scroller = document.getElementById('scroller');
const timeline = new ScrollTimeline({ scrollSource: scroller, timeRange: 1000, orientation: 'block' });
const timeline = new ScrollTimeline(
{ scrollSource: scroller, orientation: 'block' });
const transform_animation = new Animation(transform_effect, timeline);
transform_animation.play();
const opacity_animation = new Animation(opacity_effect, timeline);
@ -72,7 +73,7 @@ drive two animations">
scroller.scrollTop = 0.5 * maxScroll;
waitForAnimationFrames(2).then(_ => {
takeScreenshot();
takeScreenshot();
});
});
</script>