上文中我们讲到了VSYNC的注册,注册之后会等待vsync信号回调doframe,然后回调到了
FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
,因为JNILoad的时候将FlutterJNI#nativeOnVsync
跟VsyncWaiterAndroid#OnNativeVsync
做了绑定,此时会被回调到OnNativeVsync中
- 1.vsnyc_waiter_android.cc
VsyncWaiterAndroid::OnNativeVsync
/// static
void VsyncWaiterAndroid::OnNativeVsync(JNIEnv* env,
jclass jcaller,
jlong frameTimeNanos,
jlong frameTargetTimeNanos,
jlong java_baton) {
TRACE_EVENT0("flutter", "VSYNC");
auto frame_time = fml::TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds(frameTimeNanos));
auto target_time = fml::TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds(frameTargetTimeNanos));
ConsumePendingCallback(java_baton, frame_time, target_time);
}
这里的target_time = frame_time+屏幕刷新时间(fps)
float fps = windowManager.getDefaultDisplay().getRefreshRate();
long refreshPeriodNanos = (long) (1000000000.0 / fps);
一般的屏幕刷新率每秒60次,fps =16.7
- 2.vsnyc_waiter_android.cc
VsyncWaiterAndroid:: ConsumePendingCallback
// static
void VsyncWaiterAndroid::ConsumePendingCallback(
jlong java_baton,
fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
auto* weak_this = reinterpret_cast*>(java_baton);
auto shared_this = weak_this->lock();
delete weak_this;
if (shared_this) {
shared_this->FireCallback(frame_start_time, frame_target_time);
}
}
- 3.vsync_waiter.cc
VsyncWaiter:: FireCallback
void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
Callback callback;
fml::closure secondary_callback;
{
std::scoped_lock lock(callback_mutex_);
callback = std::move(callback_);
secondary_callback = std::move(secondary_callback_);
}
if (!callback && !secondary_callback) {
//判断之前设置的callback是否被设置为null了,若设置为null了也就没必要回调了
TRACE_EVENT_INSTANT0("flutter", "MismatchedFrameCallback");
return;
}
if (callback) {
auto flow_identifier = fml::tracing::TraceNonce();
TRACE_EVENT0("flutter", "VsyncFireCallback");
TRACE_FLOW_BEGIN("flutter", kVsyncFlowName, flow_identifier);
//向UI线程中post VSYNC的信号回调
task_runners_.GetUITaskRunner()->PostTaskForTime(
[callback, flow_identifier, frame_start_time, frame_target_time]() {
FML_TRACE_EVENT("flutter", kVsyncTraceName, "StartTime",
frame_start_time, "TargetTime", frame_target_time);
fml::tracing::TraceEventAsyncComplete(
"flutter", "VsyncSchedulingOverhead", fml::TimePoint::Now(),
frame_start_time);
//执行callback
callback(frame_start_time, frame_target_time);
TRACE_FLOW_END("flutter", kVsyncFlowName, flow_identifier);
},
frame_start_time);
}
if (secondary_callback) {
task_runners_.GetUITaskRunner()->PostTaskForTime(
std::move(secondary_callback), frame_start_time);
}
}
这里的回调信号会post到UI线程中执行,同时UI线程会在
MessageLoop::RunExpiredTasks
将消息取出来执行。
- 4.message_loop.cc
MessageLoop::RunExpiredTasksNow
void MessageLoop::RunExpiredTasksNow() {
loop_->RunExpiredTasksNow();
}
- 5.message_loop_impl.cc
void MessageLoopImpl::RunExpiredTasksNow() {
FlushTasks(FlushType::kAll);
}
void MessageLoopImpl::FlushTasks(FlushType type) {
TRACE_EVENT0("fml", "MessageLoop::FlushTasks");
std::vector invocations;
//取出task中的消息
task_queue_->GetTasksToRunNow(queue_id_, type, invocations);
//执行取出的消息
for (const auto& invocation : invocations) {
invocation();
std::vector observers =
task_queue_->GetObserversToNotify(queue_id_);
for (const auto& observer : observers) {
observer();
}
}
}
从task_queue 中取出对应的消息,并执行invocation,此方法将真正执行对应的callback(
AsyncWaitForVsync
中的callback)
- 6.message_loop_tast_queues.cc
MessageLoopTaskQueues::GetTasksToRunNow
void MessageLoopTaskQueues::GetTasksToRunNow(
TaskQueueId queue_id,
FlushType type,
std::vector& invocations) {
std::lock_guard guard(queue_mutex_);
//是否有挂起的task
if (!HasPendingTasksUnlocked(queue_id)) {
return;
}
const auto now = fml::TimePoint::Now();
//判断是否有挂起的任务,有取出来并判断时间是否到了,到了立马执行
while (HasPendingTasksUnlocked(queue_id)) {
TaskQueueId top_queue = _kUnmerged;
const auto& top = PeekNextTaskUnlocked(queue_id, top_queue);
//判断队列的头时间是否可以执行,不可以执行break
if (top.GetTargetTime() > now) {
break;
}
//将挂起的放到列表里面
invocations.emplace_back(top.GetTask());
queue_entries_.at(top_queue)->delayed_tasks.pop();
if (type == FlushType::kSingle) {
break;
}
}
if (!HasPendingTasksUnlocked(queue_id)) {
//若没有挂起的task睡眠当前loop,直到下一次message的到来
WakeUpUnlocked(queue_id, fml::TimePoint::Max());
} else {
//若有挂起的task,执行并设置下次唤醒的时间
WakeUpUnlocked(queue_id, GetNextWakeTimeUnlocked(queue_id));
}
}
//为当前队列设置wakeup的唤醒时间
void MessageLoopTaskQueues::WakeUpUnlocked(TaskQueueId queue_id,
fml::TimePoint time) const {
if (queue_entries_.at(queue_id)->wakeable) {
queue_entries_.at(queue_id)->wakeable->WakeUp(time);
}
}
此方法会从消息队列中循环取出队列的消息
1.若没有挂起的task消息,那么将当前的loop进行睡眠直到新的消息到来唤醒(time = fml::TimePoint::Max())
2.若有挂起的task消息,但是时间没有到top.GetTargetTime() > now
,那么将当前的loop进行睡眠到message执行的时间
3.若有挂起的task且时间是top.GetTargetTime() <= now
,那么将执行此消息。然后将loop睡眠到下个message执行的时间
- 7.animator.cc
Animator::AwaitVSync
callback的位置
void Animator::AwaitVSync() {
waiter_->AsyncWaitForVsync(
[self = weak_factory_.GetWeakPtr()](fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
if (self) {
if (self->CanReuseLastLayerTree()) {
self->DrawLastLayerTree();
} else {
self->BeginFrame(frame_start_time, frame_target_time);
}
}
});
delegate_.OnAnimatorNotifyIdle(dart_frame_deadline_);
}
- 8.animator.cc#DrawLastLayerTree
///复用上一次的图层库
void Animator::DrawLastLayerTree() {
//释放信号量,vsync信号可再次注册
pending_frame_semaphore_.Signal();
delegate_.OnAnimatorDrawLastLayerTree();
}
注意:delgate此处表示的是shell.cc:shell同时继承了PlatformView::Delegate,Animator::Delegate,Engine::Delegate,所以在Engine,Animator,PlatformView中的成员变量delegate_都是指Shell对象。
-
- shell.cc#OnAnimatorDrawLastLayerTree
void Shell::OnAnimatorDrawLastLayerTree() {
FML_DCHECK(is_setup_);
//将任务交给Raster线程(draw过程并为GPU下发指令的线程)处理
task_runners_.GetRasterTaskRunner()->PostTask(
[rasterizer = rasterizer_->GetWeakPtr()]() {
if (rasterizer) {
rasterizer->DrawLastLayerTree();
}
});
}
这里的Raster线程是对LayerTree进行draw操作并将要draw内容下发给GPU进行渲染。Raster的处理过程后边文章介绍,本篇不进行介绍。
- 10.animator.cc
Animator::BeginFrame
void Animator::BeginFrame(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
TRACE_EVENT_ASYNC_END0("flutter", "Frame Request Pending", frame_number_++);
TRACE_EVENT0("flutter", "Animator::BeginFrame");
while (!trace_flow_ids_.empty()) {
uint64_t trace_flow_id = trace_flow_ids_.front();
TRACE_FLOW_END("flutter", "PointerEvent", trace_flow_id);
trace_flow_ids_.pop_front();
}
frame_scheduled_ = false;
notify_idle_task_id_++;
regenerate_layer_tree_ = false;
//非负信号量,容量1,每次获取会减1,释放加1。控制vysnc的注册`pending_frame_semaphore_(1),`
//此处+1
pending_frame_semaphore_.Signal();
if (!producer_continuation_) {
//若之前的layertree并没有执行Animation :: Render,此次直接启用便可
//layer_tree_pipeline_(fml::MakeRefCounted(2)) 这里的管道是最大深度是2,即最大的执行laytree为2,每次UI线程执行poduce会减一,Raster线程执行Comsume之后会执行一次加一操作。
producer_continuation_ = layer_tree_pipeline_->Produce();
if (!producer_continuation_) {
//pipeline已满,说明GPU线程繁忙,则结束本次UI绘制,重新注册Vsync
RequestFrame();
return;
}
}
FML_DCHECK(producer_continuation_);
//从pipeline中获取有效的continuation,并准备为可能的frame服务
last_frame_begin_time_ = frame_start_time;
//获取当前帧绘制截止时间,用于告知可GC的空闲时长
last_frame_target_time_ = frame_target_time;
dart_frame_deadline_ = FxlToDartOrEarlier(frame_target_time);
{
TRACE_EVENT2("flutter", "Framework Workload", "mode", "basic", "frame",
FrameParity());
//执行绘制
delegate_.OnAnimatorBeginFrame(frame_target_time);
}
if (!frame_scheduled_) {
//执行完绘制之后需要通知UI,闲置
task_runners_.GetUITaskRunner()->PostDelayedTask(
[self = weak_factory_.GetWeakPtr(),
notify_idle_task_id = notify_idle_task_id_]() {
if (!self.get()) {
return;
}
//如果我们(此任务的)任务ID与当前任务ID相同(表示发布此任务的| BeginFrame |调用没有后续框架)并且当前没有可处理的frame,通知引擎当前处于空闲状态 100ms
if (notify_idle_task_id == self->notify_idle_task_id_ &&
!self->frame_scheduled_) {
TRACE_EVENT0("flutter", "BeginFrame idle callback");
self->delegate_.OnAnimatorNotifyIdle(Dart_TimelineGetMicros() +
100000);
}
},
//等待51毫秒(比60hz的3帧多1毫秒)
kNotifyIdleTaskWaitTime);
}
}
此处kNotifyIdleTaskWaitTime等于51ms,等于3帧的时间+1ms,之所以这样设计是由于在某些工作负载下(比如父视图调整大小,通过viewport metrics事件传达给子视图)实际上还没有schedule帧,尽管在下一个vsync会生成一帧(将在收到viewport事件后schedule),因此推迟调用OnAnimatorNotifyIdle一点点,从而避免可能垃圾回收在不希望的时间触发。
- 11.shell.cc
Shell::OnAnimatorNotifyIdle
以下都是一系列调用过程
// |Animator::Delegate|
void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_target_time) {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
// record the target time for use by rasterizer.
{
std::scoped_lock time_recorder_lock(time_recorder_mutex_);
latest_frame_target_time_.emplace(frame_target_time);
}
if (engine_) {
engine_->BeginFrame(frame_target_time);
}
}
- 12.engine.cc
Engine::BeginFrame
void Engine::BeginFrame(fml::TimePoint frame_time) {
TRACE_EVENT0("flutter", "Engine::BeginFrame");
runtime_controller_->BeginFrame(frame_time);
}
- 13.runtim_controller.cc
RuntimeController::BeginFrame
bool RuntimeController::BeginFrame(fml::TimePoint frame_time) {
if (auto* window = GetWindowIfAvailable()) {
window->BeginFrame(frame_time);
return true;
}
return false;
}
- 14.window.cc
Window::BeginFrame
void Window::BeginFrame(fml::TimePoint frameTime) {
std::shared_ptr dart_state = library_.dart_state().lock();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_beginFrame",
{
Dart_NewInteger(microseconds),
}));
UIDartState::Current()->FlushMicrotasksNow();
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_drawFrame", {}));
}
之前交代过window.cc 中的方法跟window.dart是对应的。
BeginFrame 方法此时执行了
1._beginFrame 执行到了window.dart的onBeginFrame
2.FlushMicrotasksNow 这里便是我们平常使用的scheduleMicrotask异步事件,这里进行了执行,所以我们的Microtask本身耗时的话会阻塞我们的UI线程
3._drawFrame 执行到了window.dart的onDrawFrame
从hooks.dart 中可以知道
@pragma('vm:entry-point')
// ignore: unused_element
void _beginFrame(int microseconds) {
_invoke1(window.onBeginFrame, window._onBeginFrameZone, Duration(microseconds: microseconds));
}
@pragma('vm:entry-point')
// ignore: unused_element
void _drawFrame() {
_invoke(window.onDrawFrame, window._onDrawFrameZone);
}