Flutter Engine
vsync_waiter_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 <gtest/gtest.h>
6 #include <lib/async-loop/default.h>
7 #include <lib/zx/event.h>
8 #include <zircon/syscalls.h>
9 
10 #include <array>
11 
12 #include "flutter/fml/synchronization/waitable_event.h"
13 #include "flutter/fml/time/time_delta.h"
14 #include "flutter/fml/time/time_point.h"
15 #include "flutter/shell/common/thread_host.h"
16 #include "flutter/shell/common/vsync_waiter.h"
17 #include "flutter/shell/platform/fuchsia/flutter/flutter_runner_product_configuration.h"
18 #include "flutter/shell/platform/fuchsia/flutter/task_runner_adapter.h"
19 #include "flutter/shell/platform/fuchsia/flutter/thread.h"
20 #include "flutter/shell/platform/fuchsia/flutter/vsync_waiter.h"
21 
22 namespace flutter_runner_test {
23 
24 class VsyncWaiterTest : public testing::Test {
25  public:
27 
28  ~VsyncWaiterTest() = default;
29 
30  std::unique_ptr<flutter::VsyncWaiter> CreateVsyncWaiter(
31  flutter::TaskRunners task_runners) {
32  return std::make_unique<flutter_runner::VsyncWaiter>(
33  "VsyncWaiterTest", vsync_event_.get(), task_runners,
35  }
36 
38  auto status =
39  zx_object_signal(vsync_event_.get(), 0,
41  EXPECT_EQ(status, ZX_OK);
42  }
43 
44  protected:
45  void SetUp() override {
46  auto status = zx::event::create(0, &vsync_event_);
47  EXPECT_EQ(status, ZX_OK);
48  }
49 
50  private:
51  zx::event vsync_event_;
52 };
53 
54 TEST_F(VsyncWaiterTest, AwaitVsync) {
55  std::array<std::unique_ptr<flutter_runner::Thread>, 3> threads;
56 
57  for (auto& thread : threads) {
58  thread.reset(new flutter_runner::Thread());
59  }
60 
61  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
62 
63  const flutter::TaskRunners task_runners(
64  "VsyncWaiterTests", // Dart thread labels
66  async_get_default_dispatcher()), // platform
67  flutter_runner::CreateFMLTaskRunner(threads[0]->dispatcher()), // raster
68  flutter_runner::CreateFMLTaskRunner(threads[1]->dispatcher()), // ui
69  flutter_runner::CreateFMLTaskRunner(threads[2]->dispatcher()) // io
70  );
71 
72  auto vsync_waiter = CreateVsyncWaiter(std::move(task_runners));
73 
75  vsync_waiter->AsyncWaitForVsync(
76  [&latch](fml::TimePoint frame_start_time,
77  fml::TimePoint frame_target_time) { latch.Signal(); });
79 
80  bool did_timeout =
82 
83  // False indicates we were signalled rather than timed out
84  EXPECT_FALSE(did_timeout);
85 
86  vsync_waiter.reset();
87  for (const auto& thread : threads) {
88  thread->Quit();
89  }
90 }
91 
92 TEST_F(VsyncWaiterTest, SnapToNextPhaseOverlapsWithNow) {
93  const auto now = fml::TimePoint::Now();
94  const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(10);
95  const auto delta = fml::TimeDelta::FromNanoseconds(10);
96  const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
97  now, last_presentation_time, delta);
98 
99  EXPECT_EQ(now + delta, next_vsync);
100 }
101 
102 TEST_F(VsyncWaiterTest, SnapToNextPhaseAfterNow) {
103  const auto now = fml::TimePoint::Now();
104  const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(9);
105  const auto delta = fml::TimeDelta::FromNanoseconds(10);
106  const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
107  now, last_presentation_time, delta);
108 
109  // math here: 10 - 9 = 1
110  EXPECT_EQ(now + fml::TimeDelta::FromNanoseconds(1), next_vsync);
111 }
112 
113 TEST_F(VsyncWaiterTest, SnapToNextPhaseAfterNowMultiJump) {
114  const auto now = fml::TimePoint::Now();
115  const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(34);
116  const auto delta = fml::TimeDelta::FromNanoseconds(10);
117  const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
118  now, last_presentation_time, delta);
119 
120  // zeroes: -34, -24, -14, -4, 6, ...
121  EXPECT_EQ(now + fml::TimeDelta::FromNanoseconds(6), next_vsync);
122 }
123 
124 TEST_F(VsyncWaiterTest, SnapToNextPhaseAfterNowMultiJumpAccountForCeils) {
125  const auto now = fml::TimePoint::Now();
126  const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(20);
127  const auto delta = fml::TimeDelta::FromNanoseconds(16);
128  const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
129  now, last_presentation_time, delta);
130 
131  // zeroes: -20, -4, 12, 28, ...
132  EXPECT_EQ(now + fml::TimeDelta::FromNanoseconds(12), next_vsync);
133 }
134 
135 } // namespace flutter_runner_test
fml::RefPtr< fml::TaskRunner > CreateFMLTaskRunner(async_dispatcher_t *dispatcher)
static constexpr TimeDelta FromNanoseconds(int64_t nanos)
Definition: time_delta.h:40
static constexpr TimeDelta Zero()
Definition: time_delta.h:33
TEST_F(AccessibilityBridgeTest, RegistersViewRef)
bool WaitWithTimeout(TimeDelta timeout)
static fml::TimePoint SnapToNextPhase(const fml::TimePoint now, const fml::TimePoint last_frame_presentation_time, const fml::TimeDelta presentation_interval)
std::unique_ptr< flutter::VsyncWaiter > CreateVsyncWaiter(flutter::TaskRunners task_runners)
GdkEventButton * event
Definition: fl_view.cc:62
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition: time_delta.h:46
static constexpr zx_signals_t SessionPresentSignal
Definition: vsync_waiter.h:21
static TimePoint Now()
Definition: time_point.cc:26