blob: 60b5b4477c0ac89994e9656b7cbc4b5f71b61eff [file] [log] [blame]
Khushalfdacdc92017-09-22 22:40:521// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/trees/image_animation_controller.h"
6
Gyuyoung Kime83664012017-12-02 00:12:497#include <memory>
8
Sebastien Marchand6d0558fd2019-01-25 16:49:379#include "base/bind.h"
Khushalfdacdc92017-09-22 22:40:5210#include "base/run_loop.h"
11#include "base/test/gtest_util.h"
12#include "base/threading/thread_task_runner_handle.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace cc {
16
17class FakeAnimationDriver : public ImageAnimationController::AnimationDriver {
18 public:
Chris Watkinsf6353292017-12-04 02:36:0519 FakeAnimationDriver() = default;
20 ~FakeAnimationDriver() override = default;
Khushalfdacdc92017-09-22 22:40:5221
22 void set_should_animate(bool should_animate) {
23 should_animate_ = should_animate;
24 }
25
26 // ImageAnimationController::AnimationDriver implementation.
27 bool ShouldAnimate(PaintImage::Id paint_image_id) const override {
28 return should_animate_;
29 }
30
31 private:
32 bool should_animate_ = true;
33};
34
35class DelayTrackingTaskRunner : public base::SingleThreadTaskRunner {
36 public:
37 explicit DelayTrackingTaskRunner(base::SingleThreadTaskRunner* task_runner)
38 : task_runner_(task_runner) {}
39
40 bool PostDelayedTask(const base::Location& from_here,
41 base::OnceClosure task,
42 base::TimeDelta delay) override {
43 last_delay_.emplace(delay);
44 return task_runner_->PostTask(from_here, std::move(task));
45 }
46
47 bool RunsTasksInCurrentSequence() const override {
48 return task_runner_->RunsTasksInCurrentSequence();
49 }
50
51 bool PostNonNestableDelayedTask(const base::Location& from_here,
52 base::OnceClosure task,
53 base::TimeDelta delay) override {
54 last_delay_.emplace(delay);
55 return task_runner_->PostTask(from_here, std::move(task));
56 }
57
58 void VerifyDelay(base::TimeDelta expected) {
59 DCHECK(last_delay_.has_value());
60 EXPECT_EQ(last_delay_.value(), expected);
61 last_delay_.reset();
62 }
63
64 bool has_delay() const { return last_delay_.has_value(); }
65
66 private:
67 ~DelayTrackingTaskRunner() override = default;
68
69 base::Optional<base::TimeDelta> last_delay_;
70 base::SingleThreadTaskRunner* task_runner_;
71};
72
Khushala60ea1a2019-02-23 03:51:3073class ImageAnimationControllerTest : public testing::Test,
74 public ImageAnimationController::Client {
Khushalfdacdc92017-09-22 22:40:5275 public:
76 void SetUp() override {
77 task_runner_ =
78 new DelayTrackingTaskRunner(base::ThreadTaskRunnerHandle::Get().get());
Gyuyoung Kime83664012017-12-02 00:12:4979 controller_ = std::make_unique<ImageAnimationController>(
Khushala60ea1a2019-02-23 03:51:3080 task_runner_.get(), this, GetEnableImageAnimationResync());
81 controller_->set_now_callback_for_testing(base::BindRepeating(
82 &ImageAnimationControllerTest::Now, base::Unretained(this)));
Khushalfdacdc92017-09-22 22:40:5283 now_ += base::TimeDelta::FromSeconds(10);
84 }
85
86 void TearDown() override { controller_.reset(); }
87
88 void LoopOnceNoDelay(PaintImage::Id paint_image_id,
89 const std::vector<FrameMetadata>& frames,
90 size_t num_of_frames_to_loop,
Khushal3e58f9b72017-09-26 05:28:5591 int repetitions_completed,
Khushala60ea1a2019-02-23 03:51:3092 std::vector<base::TimeDelta> expected_delays = {},
Khushal3e58f9b72017-09-26 05:28:5593 bool restarting = false) {
Khushalfdacdc92017-09-22 22:40:5294 DCHECK_LE(num_of_frames_to_loop, frames.size());
95
Khushala60ea1a2019-02-23 03:51:3096 if (expected_delays.empty()) {
97 expected_delays.resize(frames.size());
98 for (size_t i = 0; i < frames.size(); ++i)
99 expected_delays[i] = frames[i].duration;
100 }
101
Khushalfdacdc92017-09-22 22:40:52102 invalidation_count_ = 0;
103 for (size_t i = 0; i < num_of_frames_to_loop; ++i) {
104 SCOPED_TRACE(i);
105
106 // Run the pending invalidation.
Khushala60ea1a2019-02-23 03:51:30107 RunFrameRequestAndInvalidation();
Khushalfdacdc92017-09-22 22:40:52108
109 // Animate the image on the sync tree.
Khushala60ea1a2019-02-23 03:51:30110 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushal488580692017-10-03 01:02:49111
112 // No frames should have been skipped since we add no delay in advancing
113 // the animation.
114 EXPECT_EQ(
115 controller_->GetLastNumOfFramesSkippedForTesting(paint_image_id), 0u);
116
Khushalfdacdc92017-09-22 22:40:52117 EXPECT_EQ(controller_->GetFrameIndexForImage(paint_image_id,
118 WhichTree::PENDING_TREE),
119 i);
Khushal3e58f9b72017-09-26 05:28:55120 if (i == 0u && !restarting) {
Khushalfdacdc92017-09-22 22:40:52121 // If we are displaying the first frame on the pending tree, then the
122 // active tree has the first frame as well if this is the first loop,
123 // otherwise it should be the last frame since we are starting a new
124 // loop.
Khushal3e58f9b72017-09-26 05:28:55125 size_t active_index = 0u;
126 if (repetitions_completed != 0)
Khushalfdacdc92017-09-22 22:40:52127 active_index = frames.size() - 1;
Khushal3e58f9b72017-09-26 05:28:55128 EXPECT_EQ(controller_->GetFrameIndexForImage(paint_image_id,
129 WhichTree::ACTIVE_TREE),
130 active_index);
131 } else if (i != 0u) {
132 EXPECT_EQ(controller_->GetFrameIndexForImage(paint_image_id,
133 WhichTree::ACTIVE_TREE),
134 i - 1);
Khushalfdacdc92017-09-22 22:40:52135 }
136
Khushal3e58f9b72017-09-26 05:28:55137 if (i == 0u && repetitions_completed == 0 && !restarting) {
Khushalfdacdc92017-09-22 22:40:52138 // Starting the animation does not perform any invalidation.
139 EXPECT_EQ(animated_images.size(), 0u);
140 } else {
141 EXPECT_EQ(animated_images.size(), 1u);
142 EXPECT_EQ(animated_images.count(paint_image_id), 1u);
143 }
144
145 // Animating should schedule an invalidation for the next frame, until we
146 // reach the last frame.
147 if (i != num_of_frames_to_loop - 1)
Khushala60ea1a2019-02-23 03:51:30148 task_runner_->VerifyDelay(expected_delays.at(i));
Khushalfdacdc92017-09-22 22:40:52149
150 // Activate and advance time to the next frame.
151 controller_->DidActivate();
Khushala60ea1a2019-02-23 03:51:30152 AdvanceNow(expected_delays.at(i));
Khushalfdacdc92017-09-22 22:40:52153 }
154 }
155
156 protected:
Khushala60ea1a2019-02-23 03:51:30157 // ImageAnimationController::Client implementation.
158 void RequestBeginFrameForAnimatedImages() override { begin_frame_count_++; }
159 void RequestInvalidationForAnimatedImages() override {
160 invalidation_count_++;
161 }
162
163 base::TimeTicks Now() { return now_; }
Khushalfdacdc92017-09-22 22:40:52164
165 void AdvanceNow(base::TimeDelta delta) { now_ += delta; }
Khushala60ea1a2019-02-23 03:51:30166 viz::BeginFrameArgs BeginFrameArgs(base::TimeTicks now = base::TimeTicks()) {
167 if (now == base::TimeTicks())
168 now = now_;
169
170 return viz::BeginFrameArgs::Create(
171 BEGINFRAME_FROM_HERE, 1 /* source_id */, 1 /* sequence_number */,
172 now /* frame_time */, now + interval_ /* deadline */,
173 interval_ /* interval */,
174 viz::BeginFrameArgs::BeginFrameArgsType::NORMAL);
175 }
176
177 void RunFrameRequestAndInvalidation() {
178 // Frame request.
179 base::RunLoop().RunUntilIdle();
180 EXPECT_EQ(begin_frame_count_, 1);
181 EXPECT_EQ(invalidation_count_, 0);
182 begin_frame_count_ = 0;
183
184 // Invalidation request.
185 controller_->WillBeginImplFrame(BeginFrameArgs());
186 EXPECT_EQ(begin_frame_count_, 0);
187 EXPECT_EQ(invalidation_count_, 1);
188 invalidation_count_ = 0;
189 }
Khushalfdacdc92017-09-22 22:40:52190
Eric Seckler628770942018-03-02 23:20:21191 virtual bool GetEnableImageAnimationResync() const { return true; }
192
Khushalfdacdc92017-09-22 22:40:52193 base::TimeTicks now_;
194 int invalidation_count_ = 0;
Khushala60ea1a2019-02-23 03:51:30195 int begin_frame_count_ = 0;
Khushalfdacdc92017-09-22 22:40:52196 std::unique_ptr<ImageAnimationController> controller_;
197 scoped_refptr<DelayTrackingTaskRunner> task_runner_;
Khushala60ea1a2019-02-23 03:51:30198
199 base::TimeDelta interval_ = base::TimeDelta::FromMilliseconds(1);
Khushalfdacdc92017-09-22 22:40:52200};
201
202TEST_F(ImageAnimationControllerTest, AnimationWithDelays) {
203 std::vector<FrameMetadata> frames = {
204 FrameMetadata(true, base::TimeDelta::FromMilliseconds(5)),
205 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
Khushal488580692017-10-03 01:02:49206 FrameMetadata(true, base::TimeDelta::FromMilliseconds(4)),
207 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
Khushalfdacdc92017-09-22 22:40:52208
209 DiscardableImageMap::AnimatedImageMetadata data(
210 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames,
Khushal3e58f9b72017-09-26 05:28:55211 kAnimationLoopInfinite, 0);
Khushalfdacdc92017-09-22 22:40:52212 controller_->UpdateAnimatedImage(data);
213 FakeAnimationDriver driver;
214 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30215 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52216
217 // Display 2 loops in the animation.
218 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 0);
219 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 1);
220
221 // now_ is set to the time at which the first frame should be displayed for
222 // the third iteration. Add a delay that causes us to skip the first frame.
223 base::TimeDelta additional_delay = base::TimeDelta::FromMilliseconds(1);
224 AdvanceNow(data.frames[0].duration + additional_delay);
Khushala60ea1a2019-02-23 03:51:30225 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52226 EXPECT_EQ(animated_images.size(), 1u);
227 EXPECT_EQ(animated_images.count(data.paint_image_id), 1u);
Khushal488580692017-10-03 01:02:49228 EXPECT_EQ(
229 controller_->GetLastNumOfFramesSkippedForTesting(data.paint_image_id),
230 1u);
Khushalfdacdc92017-09-22 22:40:52231
232 // The pending tree displays the second frame while the active tree has the
Khushal488580692017-10-03 01:02:49233 // last frame.
Khushalfdacdc92017-09-22 22:40:52234 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
235 WhichTree::PENDING_TREE),
236 1u);
237 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
238 WhichTree::ACTIVE_TREE),
Khushal488580692017-10-03 01:02:49239 3u);
Khushalfdacdc92017-09-22 22:40:52240
241 // Invalidation delay is based on the duration of the second frame and the
242 // delay in creating this sync tree.
243 task_runner_->VerifyDelay(frames[1].duration - additional_delay);
Khushalfdacdc92017-09-22 22:40:52244
Khushal488580692017-10-03 01:02:49245 // Activate and animate with a delay that causes us to skip another 2 frames.
Khushalfdacdc92017-09-22 22:40:52246 controller_->DidActivate();
247 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
248 WhichTree::ACTIVE_TREE),
249 1u);
Khushal488580692017-10-03 01:02:49250 AdvanceNow(data.frames[1].duration + data.frames[2].duration +
251 data.frames[3].duration);
Khushala60ea1a2019-02-23 03:51:30252 RunFrameRequestAndInvalidation();
253 animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52254 EXPECT_EQ(animated_images.size(), 1u);
255 EXPECT_EQ(animated_images.count(data.paint_image_id), 1u);
Khushal488580692017-10-03 01:02:49256 EXPECT_EQ(
257 controller_->GetLastNumOfFramesSkippedForTesting(data.paint_image_id),
258 2u);
Khushalfdacdc92017-09-22 22:40:52259
260 // The pending tree displays the first frame, while the active tree has the
261 // second frame.
262 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
263 WhichTree::PENDING_TREE),
264 0u);
265 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
266 WhichTree::ACTIVE_TREE),
267 1u);
268
269 // Invalidation delay is based on the duration of the first frame and the
270 // initial additionaly delay.
271 task_runner_->VerifyDelay(frames[0].duration - additional_delay);
Khushalfdacdc92017-09-22 22:40:52272
273 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
274}
275
276TEST_F(ImageAnimationControllerTest, DriversControlAnimationTicking) {
277 std::vector<FrameMetadata> first_image_frames = {
278 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
279 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
280 DiscardableImageMap::AnimatedImageMetadata first_data(
281 PaintImage::GetNextId(), PaintImage::CompletionState::DONE,
Khushal3e58f9b72017-09-26 05:28:55282 first_image_frames, kAnimationLoopOnce, 0);
Khushalfdacdc92017-09-22 22:40:52283 controller_->UpdateAnimatedImage(first_data);
284 FakeAnimationDriver first_driver;
285 controller_->RegisterAnimationDriver(first_data.paint_image_id,
286 &first_driver);
287
288 std::vector<FrameMetadata> second_image_frames = {
289 FrameMetadata(true, base::TimeDelta::FromMilliseconds(5)),
290 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
291 DiscardableImageMap::AnimatedImageMetadata second_data(
292 PaintImage::GetNextId(), PaintImage::CompletionState::DONE,
Khushal3e58f9b72017-09-26 05:28:55293 second_image_frames, kAnimationLoopOnce, 0);
Khushalfdacdc92017-09-22 22:40:52294 controller_->UpdateAnimatedImage(second_data);
295 FakeAnimationDriver second_driver;
296 controller_->RegisterAnimationDriver(second_data.paint_image_id,
297 &second_driver);
298
299 // Disable animating from all drivers, no invalidation request should be made.
300 first_driver.set_should_animate(false);
301 second_driver.set_should_animate(false);
Khushala60ea1a2019-02-23 03:51:30302 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52303 base::RunLoop().RunUntilIdle();
Khushala60ea1a2019-02-23 03:51:30304 EXPECT_EQ(begin_frame_count_, 0);
Khushalfdacdc92017-09-22 22:40:52305
306 // Enable animating from the first driver, which should schedule an
307 // invalidation to advance this animation.
308 first_driver.set_should_animate(true);
Khushala60ea1a2019-02-23 03:51:30309 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52310 task_runner_->VerifyDelay(base::TimeDelta());
Khushalfdacdc92017-09-22 22:40:52311
312 // Start animating the first image.
Khushala60ea1a2019-02-23 03:51:30313 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52314 EXPECT_EQ(animated_images.size(), 0u);
315
316 // Invalidation should be scheduled for this image.
317 task_runner_->VerifyDelay(first_image_frames[0].duration);
318
319 // Now enable animating the second image instead.
320 second_driver.set_should_animate(true);
Khushala60ea1a2019-02-23 03:51:30321 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52322
323 // Invalidation is triggered to start with no delay since the second image has
324 // not started animating yet.
325 task_runner_->VerifyDelay(base::TimeDelta());
326
327 // Disable animating all images.
328 first_driver.set_should_animate(false);
329 second_driver.set_should_animate(false);
Khushala60ea1a2019-02-23 03:51:30330 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52331
332 // Any scheduled invalidation should be cancelled.
333 base::RunLoop().RunUntilIdle();
Khushala60ea1a2019-02-23 03:51:30334 EXPECT_EQ(begin_frame_count_, 0);
Khushalfdacdc92017-09-22 22:40:52335
336 controller_->UnregisterAnimationDriver(first_data.paint_image_id,
337 &first_driver);
338 controller_->UnregisterAnimationDriver(second_data.paint_image_id,
339 &second_driver);
340}
341
342TEST_F(ImageAnimationControllerTest, RepetitionsRequested) {
343 std::vector<FrameMetadata> frames = {
344 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
345 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
346 FrameMetadata(true, base::TimeDelta::FromMilliseconds(4))};
347
348 DiscardableImageMap::AnimatedImageMetadata data(
349 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames,
Khushal3e58f9b72017-09-26 05:28:55350 kAnimationLoopOnce, 0);
Khushalfdacdc92017-09-22 22:40:52351 controller_->UpdateAnimatedImage(data);
352 FakeAnimationDriver driver;
353 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30354 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52355
356 // Finish a single loop in the animation.
357 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 0);
358
359 // No invalidation should be scheduled now, since the requested number of
360 // loops have been completed.
361 invalidation_count_ = 0;
362 base::RunLoop().RunUntilIdle();
363 EXPECT_EQ(invalidation_count_, 0);
364 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
365
366 // Now with a repetition count of 5.
367 data.paint_image_id = PaintImage::GetNextId();
368 data.repetition_count = 5;
369 controller_->UpdateAnimatedImage(data);
370 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30371 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52372 for (int i = 0; i < data.repetition_count; ++i) {
373 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), i);
374
375 // Since we will be looping back to the first frame, the invalidation should
376 // have the delay of the last frame. Until we reach the end of requested
377 // iterations.
378 if (i < data.repetition_count - 1)
379 task_runner_->VerifyDelay(frames.back().duration);
380 invalidation_count_ = 0;
381 }
382
383 // No invalidation should be scheduled now, since the requested number of
384 // loops have been completed.
385 invalidation_count_ = 0;
386 base::RunLoop().RunUntilIdle();
387 EXPECT_EQ(invalidation_count_, 0);
388 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
389
390 // Now with kAnimationLoopInfinite.
391 data.paint_image_id = PaintImage::GetNextId();
392 data.repetition_count = kAnimationLoopInfinite;
393 controller_->UpdateAnimatedImage(data);
394 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30395 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52396 for (int i = 0; i < 7; ++i) {
397 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), i);
398
399 // Since we will be looping back to the first frame, the invalidation should
400 // have the delay of the last frame. Until we reach the end of requested
401 // iterations.
402 if (i < data.repetition_count - 1)
403 task_runner_->VerifyDelay(frames.back().duration);
404 invalidation_count_ = 0;
405 }
406
407 // We still have an invalidation scheduled since the image will keep looping
408 // till the drivers keep the animation active.
Khushala60ea1a2019-02-23 03:51:30409 begin_frame_count_ = 0;
Khushalfdacdc92017-09-22 22:40:52410 base::RunLoop().RunUntilIdle();
Khushala60ea1a2019-02-23 03:51:30411 EXPECT_EQ(begin_frame_count_, 1);
Khushalfdacdc92017-09-22 22:40:52412 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
413
414 // Now try with a kAnimationNone image, which should result in a DCHECK
415 // failure.
416 data.paint_image_id = PaintImage::GetNextId();
417 data.repetition_count = kAnimationNone;
418 EXPECT_DCHECK_DEATH(controller_->UpdateAnimatedImage(data));
419}
420
421TEST_F(ImageAnimationControllerTest, DisplayCompleteFrameOnly) {
422 std::vector<FrameMetadata> frames = {
423 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
424 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
425 FrameMetadata(false, base::TimeDelta::FromMilliseconds(4))};
426
427 DiscardableImageMap::AnimatedImageMetadata data(
428 PaintImage::GetNextId(), PaintImage::CompletionState::PARTIALLY_DONE,
Khushal3e58f9b72017-09-26 05:28:55429 frames, kAnimationLoopInfinite, 0);
Khushalfdacdc92017-09-22 22:40:52430 controller_->UpdateAnimatedImage(data);
431 FakeAnimationDriver driver;
432 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30433 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52434
435 // Advance until the second frame.
436 LoopOnceNoDelay(data.paint_image_id, frames, 2, 0);
437
438 // We have no invalidation scheduled since its not possible to animate the
439 // image further until the second frame is completed.
440 invalidation_count_ = 0;
441 base::RunLoop().RunUntilIdle();
442 EXPECT_EQ(invalidation_count_, 0);
443
Khushal8ece8f982017-10-10 23:46:37444 // Completely load the image but the frame is still incomplete. It should not
445 // be advanced.
Khushalfdacdc92017-09-22 22:40:52446 data.completion_state = PaintImage::CompletionState::DONE;
447 controller_->UpdateAnimatedImage(data);
Khushala60ea1a2019-02-23 03:51:30448 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52449
Khushal8ece8f982017-10-10 23:46:37450 // No invalidation is scheduled since the last frame is still incomplete.
Khushalfdacdc92017-09-22 22:40:52451 base::RunLoop().RunUntilIdle();
Khushal8ece8f982017-10-10 23:46:37452 EXPECT_EQ(invalidation_count_, 0);
Khushalfdacdc92017-09-22 22:40:52453
454 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
455}
456
457TEST_F(ImageAnimationControllerTest, DontLoopPartiallyLoadedImages) {
458 std::vector<FrameMetadata> frames = {
459 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
460 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
461
462 DiscardableImageMap::AnimatedImageMetadata data(
463 PaintImage::GetNextId(), PaintImage::CompletionState::PARTIALLY_DONE,
Khushal3e58f9b72017-09-26 05:28:55464 frames, 2, 0);
Khushalfdacdc92017-09-22 22:40:52465 controller_->UpdateAnimatedImage(data);
466 FakeAnimationDriver driver;
467 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30468 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52469
470 // Finish the first loop.
471 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 0);
472
473 // We shouldn't be looping back to the first frame until the image is known to
474 // be completely loaded.
475 invalidation_count_ = 0;
476 base::RunLoop().RunUntilIdle();
477 EXPECT_EQ(invalidation_count_, 0);
478
479 // Now add another frame and mark the image complete. The animation should
480 // advance and we should see another repetition. This verifies that we don't
481 // mark loops complete on reaching the last frame until the image is
482 // completely loaded and the frame count is known to be accurate.
483 frames.push_back(FrameMetadata(true, base::TimeDelta::FromMilliseconds(4)));
484 data.completion_state = PaintImage::CompletionState::DONE;
485 data.frames = frames;
486 controller_->UpdateAnimatedImage(data);
Khushala60ea1a2019-02-23 03:51:30487 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52488
489 // The animation advances to the last frame. We don't have a delay since we
490 // already advanced to the desired time in the loop above.
491 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:30492 RunFrameRequestAndInvalidation();
493 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52494 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
495 WhichTree::PENDING_TREE),
496 2u);
497 EXPECT_EQ(animated_images.size(), 1u);
498 EXPECT_EQ(animated_images.count(data.paint_image_id), 1u);
499 controller_->DidActivate();
500
501 // Advancing the animation scheduled an invalidation for the next iteration.
502 task_runner_->VerifyDelay(frames.back().duration);
503
504 // Perform another loop in the animation.
505 AdvanceNow(frames.back().duration);
506 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 1);
507
508 // No invalidation should have been requested at the end of the second loop.
Khushala60ea1a2019-02-23 03:51:30509 begin_frame_count_ = 0;
Khushalfdacdc92017-09-22 22:40:52510 base::RunLoop().RunUntilIdle();
Khushala60ea1a2019-02-23 03:51:30511 EXPECT_EQ(begin_frame_count_, 0);
Khushalfdacdc92017-09-22 22:40:52512
513 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
514}
515
516TEST_F(ImageAnimationControllerTest, DontAdvanceUntilDesiredTime) {
517 std::vector<FrameMetadata> frames = {
518 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
519 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
520
521 DiscardableImageMap::AnimatedImageMetadata data(
522 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames,
Khushal3e58f9b72017-09-26 05:28:55523 kAnimationLoopOnce, 0);
Khushalfdacdc92017-09-22 22:40:52524 controller_->UpdateAnimatedImage(data);
525 FakeAnimationDriver driver;
526 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30527 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52528
529 // Advance the first frame.
530 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:30531 RunFrameRequestAndInvalidation();
532 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52533 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
534 WhichTree::PENDING_TREE),
535 0u);
536 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
537 WhichTree::ACTIVE_TREE),
538 0u);
539 EXPECT_EQ(animated_images.size(), 0u);
540 controller_->DidActivate();
541
542 // We have an invalidation request for the second frame.
543 task_runner_->VerifyDelay(frames[0].duration);
544
545 // While there is still time for the second frame, we get a new sync tree. The
546 // animation is not advanced.
547 base::TimeDelta time_remaining = base::TimeDelta::FromMilliseconds(1);
548 AdvanceNow(frames[0].duration - time_remaining);
Khushala60ea1a2019-02-23 03:51:30549 animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52550 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
551 WhichTree::PENDING_TREE),
552 0u);
553 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
554 WhichTree::ACTIVE_TREE),
555 0u);
556 EXPECT_EQ(animated_images.size(), 0u);
557 controller_->DidActivate();
558
559 // We did not get another invalidation request because there is no change in
560 // the desired time and the previous request is still pending.
561 EXPECT_FALSE(task_runner_->has_delay());
562
563 // We have a sync tree before the invalidation task could run.
564 AdvanceNow(time_remaining);
Khushala60ea1a2019-02-23 03:51:30565 animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52566 EXPECT_EQ(animated_images.size(), 1u);
567 EXPECT_EQ(animated_images.count(data.paint_image_id), 1u);
568 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
569 WhichTree::PENDING_TREE),
570 1u);
571 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
572 WhichTree::ACTIVE_TREE),
573 0u);
574 controller_->DidActivate();
575
576 // We shouldn't have an invalidation because the animation was already
577 // advanced to the last frame and the previous one should have been cancelled.
578 invalidation_count_ = 0;
579 base::RunLoop().RunUntilIdle();
580 EXPECT_EQ(invalidation_count_, 0);
581
582 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
583}
584
585TEST_F(ImageAnimationControllerTest, RestartAfterSyncCutoff) {
586 std::vector<FrameMetadata> frames = {
587 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
588 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
589
590 DiscardableImageMap::AnimatedImageMetadata data(
591 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames,
Khushal3e58f9b72017-09-26 05:28:55592 kAnimationLoopOnce, 0);
Khushalfdacdc92017-09-22 22:40:52593 controller_->UpdateAnimatedImage(data);
594 FakeAnimationDriver driver;
595 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30596 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52597
598 // Advance the first frame.
599 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:30600 RunFrameRequestAndInvalidation();
601 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52602 EXPECT_EQ(animated_images.size(), 0u);
603 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
604 WhichTree::PENDING_TREE),
605 0u);
606 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
607 WhichTree::ACTIVE_TREE),
608 0u);
609 controller_->DidActivate();
610
611 // Invalidation request for the second frame.
612 task_runner_->VerifyDelay(frames[0].duration);
613
614 // Advance the time by 10 min.
615 AdvanceNow(base::TimeDelta::FromMinutes(10));
616
Khushala60ea1a2019-02-23 03:51:30617 // Animate again, it starts from the first frame. We don't see a
618 // frame update, because that's the frame we are already displaying.
619 controller_->WillBeginImplFrame(BeginFrameArgs());
620 animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52621 EXPECT_EQ(animated_images.size(), 0u);
622 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
623 WhichTree::PENDING_TREE),
624 0u);
625 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
626 WhichTree::ACTIVE_TREE),
627 0u);
628 controller_->DidActivate();
629
630 // New invalidation request since the desired invalidation time changed.
631 task_runner_->VerifyDelay(frames[0].duration);
Khushalfdacdc92017-09-22 22:40:52632
633 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
634}
635
636TEST_F(ImageAnimationControllerTest, DontSkipLoopsToCatchUpAfterLoad) {
637 std::vector<FrameMetadata> frames = {
638 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
639 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
640 FrameMetadata(true, base::TimeDelta::FromMilliseconds(4)),
641 FrameMetadata(true, base::TimeDelta::FromMilliseconds(5))};
642
643 DiscardableImageMap::AnimatedImageMetadata data(
644 PaintImage::GetNextId(), PaintImage::CompletionState::PARTIALLY_DONE,
Khushal3e58f9b72017-09-26 05:28:55645 frames, kAnimationLoopInfinite, 0);
Khushalfdacdc92017-09-22 22:40:52646 controller_->UpdateAnimatedImage(data);
647 FakeAnimationDriver driver;
648 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30649 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52650
651 // Perform the first loop while the image is partially loaded, until the third
652 // frame.
653 LoopOnceNoDelay(data.paint_image_id, frames, 3u, 0);
654
655 // The invalidation has been scheduled with a delay for the third frame's
656 // duration.
657 task_runner_->VerifyDelay(frames[2].duration);
658
659 // |now_| is set to the desired time for the fourth frame. Advance further so
660 // we would reach the time for the second frame.
661 AdvanceNow(frames[3].duration + frames[0].duration);
662
663 // Finish the image load.
664 data.completion_state = PaintImage::CompletionState::DONE;
665 controller_->UpdateAnimatedImage(data);
Khushala60ea1a2019-02-23 03:51:30666 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52667
668 // Invalidation is scheduled immediately because we are way past the desired
669 // time. We should start from the first frame after the image is loaded
670 // instead of skipping frames.
671 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:30672 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52673 EXPECT_EQ(animated_images.size(), 1u);
674 EXPECT_EQ(animated_images.count(data.paint_image_id), 1u);
675 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
676 WhichTree::PENDING_TREE),
677 0u);
678 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
679 WhichTree::ACTIVE_TREE),
680 2u);
681 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
682}
683
684TEST_F(ImageAnimationControllerTest, FinishRepetitionsDuringCatchUp) {
685 std::vector<FrameMetadata> frames = {
686 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
687 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
688 FrameMetadata(true, base::TimeDelta::FromMilliseconds(4))};
689
690 // The animation wants 3 loops.
691 DiscardableImageMap::AnimatedImageMetadata data(
Khushal3e58f9b72017-09-26 05:28:55692 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames, 3, 0);
Khushalfdacdc92017-09-22 22:40:52693 controller_->UpdateAnimatedImage(data);
694 FakeAnimationDriver driver;
695 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30696 controller_->UpdateStateFromDrivers();
Khushalfdacdc92017-09-22 22:40:52697
698 // Finish 2 loops.
699 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 0);
700 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 1);
701
702 // now_ is set to the desired time for the first frame. Advance it so we would
703 // reach way beyond the third repeition.
704 AdvanceNow(base::TimeDelta::FromMinutes(1));
705
706 // Advance the animation, we should see the last frame since the desired
707 // repetition count will be reached during catch up.
Khushala60ea1a2019-02-23 03:51:30708 RunFrameRequestAndInvalidation();
709 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Khushalfdacdc92017-09-22 22:40:52710 // No invalidation since the active tree is already at the last frame.
711 EXPECT_EQ(animated_images.size(), 0u);
712 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
713 WhichTree::PENDING_TREE),
714 frames.size() - 1);
715 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
716 WhichTree::ACTIVE_TREE),
717 frames.size() - 1);
718
719 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
720}
721
Khushal3e58f9b72017-09-26 05:28:55722TEST_F(ImageAnimationControllerTest, ResetAnimations) {
723 std::vector<FrameMetadata> frames = {
724 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
725 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
726 FrameMetadata(true, base::TimeDelta::FromMilliseconds(4))};
727 DiscardableImageMap::AnimatedImageMetadata data(
728 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames, 3,
729 0u);
730 controller_->UpdateAnimatedImage(data);
731 FakeAnimationDriver driver;
732 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30733 controller_->UpdateStateFromDrivers();
Khushal3e58f9b72017-09-26 05:28:55734
735 // Go uptill the second frame during the second iteration.
736 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 0);
737 LoopOnceNoDelay(data.paint_image_id, frames, 2u, 1);
738
739 // Reset the animation.
740 data.reset_animation_sequence_id++;
741 controller_->UpdateAnimatedImage(data);
Khushala60ea1a2019-02-23 03:51:30742 controller_->UpdateStateFromDrivers();
Khushal3e58f9b72017-09-26 05:28:55743
744 // It should start again from the first frame and do 3 loops.
745 for (int i = 0; i < 3; ++i) {
746 bool restarting = i == 0;
Khushala60ea1a2019-02-23 03:51:30747 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), i, {},
748 restarting);
Khushal3e58f9b72017-09-26 05:28:55749 }
750
751 // No invalidation should be pending.
752 invalidation_count_ = 0;
753 base::RunLoop().RunUntilIdle();
754 EXPECT_EQ(invalidation_count_, 0);
755
756 // Same image used again in a recording. There shouldn't be an invalidation
757 // since the reset sequence has already been synchronized.
758 controller_->UpdateAnimatedImage(data);
Khushala60ea1a2019-02-23 03:51:30759 controller_->UpdateStateFromDrivers();
Khushal3e58f9b72017-09-26 05:28:55760 base::RunLoop().RunUntilIdle();
761 EXPECT_EQ(invalidation_count_, 0);
762
763 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
764}
765
sohan1d625d92018-03-12 21:57:08766TEST_F(ImageAnimationControllerTest, ResetAnimationStateMapOnNavigation) {
767 std::vector<FrameMetadata> first_image_frames = {
768 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
769 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
770 DiscardableImageMap::AnimatedImageMetadata first_data(
771 PaintImage::GetNextId(), PaintImage::CompletionState::DONE,
772 first_image_frames, kAnimationLoopOnce, 0);
773 controller_->UpdateAnimatedImage(first_data);
774 FakeAnimationDriver first_driver;
775 controller_->RegisterAnimationDriver(first_data.paint_image_id,
776 &first_driver);
777
778 std::vector<FrameMetadata> second_image_frames = {
779 FrameMetadata(true, base::TimeDelta::FromMilliseconds(5)),
780 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
781 DiscardableImageMap::AnimatedImageMetadata second_data(
782 PaintImage::GetNextId(), PaintImage::CompletionState::DONE,
783 second_image_frames, kAnimationLoopOnce, 0);
784 controller_->UpdateAnimatedImage(second_data);
785 FakeAnimationDriver second_driver;
786 controller_->RegisterAnimationDriver(second_data.paint_image_id,
787 &second_driver);
788
Khushala60ea1a2019-02-23 03:51:30789 controller_->AnimateForSyncTree(BeginFrameArgs());
sohan1d625d92018-03-12 21:57:08790
791 controller_->UnregisterAnimationDriver(first_data.paint_image_id,
792 &first_driver);
793 EXPECT_EQ(controller_->animation_state_map_size_for_testing(), 2u);
794
795 // Fake navigation and activation.
796 controller_->set_did_navigate();
797 controller_->DidActivate();
798
799 // Animation state map entries without drivers will be purged on navigation.
800 EXPECT_EQ(controller_->animation_state_map_size_for_testing(), 1u);
801
802 controller_->UnregisterAnimationDriver(second_data.paint_image_id,
803 &second_driver);
804
805 EXPECT_EQ(controller_->animation_state_map_size_for_testing(), 1u);
806}
807
Khushala60ea1a2019-02-23 03:51:30808TEST_F(ImageAnimationControllerTest, ImageWithNonVsyncAlignedDurations) {
809 interval_ = base::TimeDelta::FromMilliseconds(1);
810 std::vector<FrameMetadata> frames = {
811 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(2.5)),
812 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(3.76)),
813 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(4.27))};
814 DiscardableImageMap::AnimatedImageMetadata data(
815 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames, 3,
816 0u);
817 controller_->UpdateAnimatedImage(data);
818 FakeAnimationDriver driver;
819 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
820 controller_->UpdateStateFromDrivers();
821
822 std::vector<base::TimeDelta> expected_delays = {
823 base::TimeDelta::FromMilliseconds(2),
Khushalb43b61c2019-03-01 23:20:18824 base::TimeDelta::FromMilliseconds(4),
Khushala60ea1a2019-02-23 03:51:30825 base::TimeDelta::FromMilliseconds(4)};
826 LoopOnceNoDelay(data.paint_image_id, frames, frames.size(), 0,
827 expected_delays);
828
829 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
830}
831
832TEST_F(ImageAnimationControllerTest, ImageWithLessThanIntervalDurations) {
833 interval_ = base::TimeDelta::FromMilliseconds(1);
834 std::vector<FrameMetadata> frames = {
835 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(0.5)),
836 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(0.43)),
837 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(0.76)),
838 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(0.74)),
839 };
840 frames.push_back(FrameMetadata(true, interval_ - frames.back().duration));
841 DiscardableImageMap::AnimatedImageMetadata data(
842 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames,
843 kAnimationLoopOnce, 0u);
844 controller_->UpdateAnimatedImage(data);
845 FakeAnimationDriver driver;
846 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
847 controller_->UpdateStateFromDrivers();
848
Khushalb43b61c2019-03-01 23:20:18849 // Animation starts at 10s, we jump directly to the third frame.
Khushala60ea1a2019-02-23 03:51:30850 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:30851 auto invalidated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
852 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
853 WhichTree::PENDING_TREE),
Khushala60ea1a2019-02-23 03:51:30854 2u);
855 controller_->DidActivate();
856
857 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
858}
859
860TEST_F(ImageAnimationControllerTest, ImplFramesWhileInvalidationPending) {
861 std::vector<FrameMetadata> frames = {
862 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(2.5)),
863 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(3.76)),
864 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(4.27))};
865 DiscardableImageMap::AnimatedImageMetadata data(
866 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames, 3,
867 0u);
868 controller_->UpdateAnimatedImage(data);
869 FakeAnimationDriver driver;
870 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
871 controller_->UpdateStateFromDrivers();
872
873 // Send the impl frame for invalidating the current image such that an
874 // invalidation request is pending.
875 task_runner_->VerifyDelay(base::TimeDelta());
876 RunFrameRequestAndInvalidation();
877
878 // No new task since an invalidation is expected.
879 controller_->WillBeginImplFrame(BeginFrameArgs());
880 EXPECT_FALSE(task_runner_->has_delay());
881
882 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
883}
884
885TEST_F(ImageAnimationControllerTest, MissedBeginFrameAfterRequest) {
886 std::vector<FrameMetadata> frames = {
887 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(2.5)),
888 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(3.76)),
889 FrameMetadata(true, base::TimeDelta::FromMillisecondsD(4.27))};
890 DiscardableImageMap::AnimatedImageMetadata data(
891 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames, 3,
892 0u);
893 controller_->UpdateAnimatedImage(data);
894 FakeAnimationDriver driver;
895 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
896 controller_->UpdateStateFromDrivers();
897
898 // There should be a frame request with no delay to start the animation.
899 task_runner_->VerifyDelay(base::TimeDelta());
900
901 // Run the pending frame request.
902 begin_frame_count_ = 0;
903 base::RunLoop().RunUntilIdle();
904 EXPECT_EQ(begin_frame_count_, 1);
905
906 // Pretend that we got an impl frame for the previous vsync.
907 controller_->WillBeginImplFrame(BeginFrameArgs(now_ - interval_));
908
909 // We should get another request for an impl frame.
910 EXPECT_EQ(begin_frame_count_, 2);
911
912 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
913}
914
Eric Seckler628770942018-03-02 23:20:21915class ImageAnimationControllerNoResyncTest
916 : public ImageAnimationControllerTest {
917 protected:
918 bool GetEnableImageAnimationResync() const override { return false; }
919};
920
921TEST_F(ImageAnimationControllerNoResyncTest, NoSyncCutoffAfterIdle) {
922 std::vector<FrameMetadata> frames = {
923 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
924 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3))};
925
926 DiscardableImageMap::AnimatedImageMetadata data(
927 PaintImage::GetNextId(), PaintImage::CompletionState::DONE, frames,
928 kAnimationLoopInfinite, 0);
929 controller_->UpdateAnimatedImage(data);
930 FakeAnimationDriver driver;
931 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30932 controller_->UpdateStateFromDrivers();
Eric Seckler628770942018-03-02 23:20:21933
934 // Advance the first frame.
935 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:30936 RunFrameRequestAndInvalidation();
937 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Eric Seckler628770942018-03-02 23:20:21938 EXPECT_EQ(animated_images.size(), 0u);
939 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
940 WhichTree::PENDING_TREE),
941 0u);
942 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
943 WhichTree::ACTIVE_TREE),
944 0u);
945 controller_->DidActivate();
946
947 // Invalidation request for the second frame.
948 task_runner_->VerifyDelay(frames[0].duration);
949
950 // Advance the time by 10 min (divisible by animation duration) and first
951 // frame duration.
952 AdvanceNow(base::TimeDelta::FromMinutes(10) + frames[0].duration);
953
954 // Animate again, it should not restart from the start. Should display second
955 // animation frame.
Khushala60ea1a2019-02-23 03:51:30956 controller_->WillBeginImplFrame(BeginFrameArgs());
957 animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Eric Seckler628770942018-03-02 23:20:21958 EXPECT_EQ(animated_images.size(), 1u);
959 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
960 WhichTree::PENDING_TREE),
961 1u);
962 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
963 WhichTree::ACTIVE_TREE),
964 0u);
965 controller_->DidActivate();
966
967 // New invalidation request since the desired invalidation time changed.
968 task_runner_->VerifyDelay(frames[1].duration);
Eric Seckler628770942018-03-02 23:20:21969
970 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
971}
972
973TEST_F(ImageAnimationControllerNoResyncTest, SkipsLoopsAfterFirstIteration) {
974 std::vector<FrameMetadata> frames = {
975 FrameMetadata(true, base::TimeDelta::FromMilliseconds(2)),
976 FrameMetadata(true, base::TimeDelta::FromMilliseconds(3)),
977 FrameMetadata(true, base::TimeDelta::FromMilliseconds(4)),
978 FrameMetadata(true, base::TimeDelta::FromMilliseconds(5))};
979
980 DiscardableImageMap::AnimatedImageMetadata data(
981 PaintImage::GetNextId(), PaintImage::CompletionState::PARTIALLY_DONE,
982 frames, kAnimationLoopInfinite, 0);
983 controller_->UpdateAnimatedImage(data);
984 FakeAnimationDriver driver;
985 controller_->RegisterAnimationDriver(data.paint_image_id, &driver);
Khushala60ea1a2019-02-23 03:51:30986 controller_->UpdateStateFromDrivers();
Eric Seckler628770942018-03-02 23:20:21987
988 // Perform the first loop while the image is partially loaded, until the third
989 // frame.
990 LoopOnceNoDelay(data.paint_image_id, frames, 3u, 0);
991
992 // The invalidation has been scheduled with a delay for the third frame's
993 // duration.
994 task_runner_->VerifyDelay(frames[2].duration);
995
996 // |now_| is set to the desired time for the fourth frame. Advance further so
997 // we reach the time for the second frame.
998 AdvanceNow(frames[3].duration + frames[0].duration);
999
1000 // Finish the image load.
1001 data.completion_state = PaintImage::CompletionState::DONE;
1002 controller_->UpdateAnimatedImage(data);
Khushala60ea1a2019-02-23 03:51:301003 controller_->UpdateStateFromDrivers();
Eric Seckler628770942018-03-02 23:20:211004
1005 // Invalidation is scheduled immediately because we are way past the desired
1006 // time. We skip frames even after the image is loaded.
1007 task_runner_->VerifyDelay(base::TimeDelta());
Khushala60ea1a2019-02-23 03:51:301008 auto animated_images = controller_->AnimateForSyncTree(BeginFrameArgs());
Eric Seckler628770942018-03-02 23:20:211009 EXPECT_EQ(animated_images.size(), 1u);
1010 EXPECT_EQ(animated_images.count(data.paint_image_id), 1u);
1011 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
1012 WhichTree::PENDING_TREE),
1013 1u);
1014 EXPECT_EQ(controller_->GetFrameIndexForImage(data.paint_image_id,
1015 WhichTree::ACTIVE_TREE),
1016 2u);
1017 controller_->UnregisterAnimationDriver(data.paint_image_id, &driver);
1018}
1019
Khushalfdacdc92017-09-22 22:40:521020} // namespace cc