Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 4329f90

Browse files
iskakaushiknaudzghebre
authored andcommitted
VSyncWaiter on Fuchsia will defer firing until frame start time (#29287)
* VSyncWaiter on Fuchsia will defer firing until frame start time The common vsync waiter implementation expects this invariant to be held. * Add a test for vsync_waiter
1 parent 6f7b8f9 commit 4329f90

5 files changed

Lines changed: 84 additions & 8 deletions

File tree

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/thread.h
14491449
FILE: ../../../flutter/shell/platform/fuchsia/flutter/unique_fdio_ns.h
14501450
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter.cc
14511451
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter.h
1452+
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter_unittest.cc
14521453
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface.cc
14531454
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface.h
14541455
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vulkan_surface_pool.cc

shell/platform/fuchsia/flutter/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ executable("flutter_runner_unittests") {
449449
"tests/engine_unittests.cc",
450450
"tests/flutter_runner_product_configuration_unittests.cc",
451451
"tests/gfx_session_connection_unittests.cc",
452+
"vsync_waiter_unittest.cc",
452453
]
453454

454455
# This is needed for //third_party/googletest for linking zircon symbols.

shell/platform/fuchsia/flutter/vsync_waiter.cc

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,27 @@ VsyncWaiter::VsyncWaiter(AwaitVsyncCallback await_vsync_callback,
3030
weak_factory_(this) {
3131
fire_callback_callback_ = [this](fml::TimePoint frame_start,
3232
fml::TimePoint frame_end) {
33-
// Note: It is VERY important to set |pause_secondary_tasks| to false, else
34-
// Animator will almost immediately crash on Fuchsia.
35-
// FML_LOG(INFO) << "CRASH:: VsyncWaiter about to FireCallback";
36-
FireCallback(frame_start, frame_end, /*pause_secondary_tasks=*/false);
33+
task_runners_.GetUITaskRunner()->PostTaskForTime(
34+
[frame_start, frame_end, weak_this = weak_ui_]() {
35+
if (weak_this) {
36+
// Note: It is VERY important to set |pause_secondary_tasks| to
37+
// false, else Animator will almost immediately crash on Fuchsia.
38+
// FML_LOG(INFO) << "CRASH:: VsyncWaiter about to FireCallback";
39+
weak_this->FireCallback(frame_start, frame_end,
40+
/*pause_secondary_tasks*/ false);
41+
}
42+
},
43+
frame_start);
3744
};
3845

3946
// Generate a WeakPtrFactory for use with the UI thread. This does not need
4047
// to wait on a latch because we only ever use the WeakPtrFactory on the UI
4148
// thread so we have ordering guarantees (see ::AwaitVSync())
4249
fml::TaskRunner::RunNowOrPostTask(
4350
task_runners_.GetUITaskRunner(), fml::MakeCopyable([this]() mutable {
44-
this->weak_factory_ui_ =
51+
weak_factory_ui_ =
4552
std::make_unique<fml::WeakPtrFactory<VsyncWaiter>>(this);
53+
weak_ui_ = weak_factory_ui_->GetWeakPtr();
4654
}));
4755
}
4856

shell/platform/fuchsia/flutter/vsync_waiter.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_VSYNC_WAITER_H_
6-
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_VSYNC_WAITER_H_
5+
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_VSYNC_WAITER_H_
6+
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_VSYNC_WAITER_H_
77

88
#include <lib/async/cpp/wait.h>
99

@@ -46,6 +46,7 @@ class VsyncWaiter final : public flutter::VsyncWaiter {
4646
AwaitVsyncForSecondaryCallbackCallback
4747
await_vsync_for_secondary_callback_callback_;
4848

49+
fml::WeakPtr<VsyncWaiter> weak_ui_;
4950
std::unique_ptr<fml::WeakPtrFactory<VsyncWaiter>> weak_factory_ui_;
5051
fml::WeakPtrFactory<VsyncWaiter> weak_factory_;
5152

@@ -54,4 +55,4 @@ class VsyncWaiter final : public flutter::VsyncWaiter {
5455

5556
} // namespace flutter_runner
5657

57-
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_VSYNC_WAITER_H_
58+
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_VSYNC_WAITER_H_
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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+
#define FML_USED_ON_EMBEDDER
6+
7+
#include <gtest/gtest.h>
8+
9+
#include <string>
10+
11+
#include "flutter/fml/task_runner.h"
12+
#include "flutter/shell/common/thread_host.h"
13+
#include "fml/make_copyable.h"
14+
#include "fml/message_loop.h"
15+
#include "fml/synchronization/waitable_event.h"
16+
#include "fml/time/time_delta.h"
17+
#include "fml/time/time_point.h"
18+
#include "vsync_waiter.h"
19+
20+
namespace flutter_runner {
21+
22+
TEST(VSyncWaiterFuchsia, FrameScheduledForStartTime) {
23+
using flutter::ThreadHost;
24+
std::string prefix = "vsync_waiter_test";
25+
26+
fml::MessageLoop::EnsureInitializedForCurrentThread();
27+
auto platform_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
28+
29+
ThreadHost thread_host =
30+
ThreadHost(prefix, flutter::ThreadHost::Type::RASTER |
31+
flutter::ThreadHost::Type::UI |
32+
flutter::ThreadHost::Type::IO);
33+
const flutter::TaskRunners task_runners(
34+
prefix, // Dart thread labels
35+
platform_task_runner, // platform
36+
thread_host.raster_thread->GetTaskRunner(), // raster
37+
thread_host.ui_thread->GetTaskRunner(), // ui
38+
thread_host.io_thread->GetTaskRunner() // io
39+
);
40+
41+
// await vsync will invoke the callback right away, but vsync waiter will post
42+
// the task for frame_start time.
43+
VsyncWaiter vsync_waiter(
44+
[](FireCallbackCallback callback) {
45+
const auto now = fml::TimePoint::Now();
46+
const auto frame_start = now + fml::TimeDelta::FromMilliseconds(20);
47+
const auto frame_end = now + fml::TimeDelta::FromMilliseconds(36);
48+
callback(frame_start, frame_end);
49+
},
50+
/*secondary callback*/ nullptr, task_runners);
51+
52+
fml::AutoResetWaitableEvent latch;
53+
task_runners.GetUITaskRunner()->PostTask([&]() {
54+
vsync_waiter.AsyncWaitForVsync(
55+
[&](std::unique_ptr<flutter::FrameTimingsRecorder> recorder) {
56+
const auto now = fml::TimePoint::Now();
57+
EXPECT_GT(now, recorder->GetVsyncStartTime());
58+
latch.Signal();
59+
});
60+
});
61+
62+
latch.Wait();
63+
}
64+
65+
} // namespace flutter_runner

0 commit comments

Comments
 (0)