上文中我們講到了VSYNC的注冊峡捡,注冊之后會(huì)等待vsync信號(hào)回調(diào)doframe,然后回調(diào)到了
FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
,因?yàn)镴NILoad的時(shí)候?qū)?code>FlutterJNI#nativeOnVsync跟VsyncWaiterAndroid#OnNativeVsync
做了綁定嗡载,此時(shí)會(huì)被回調(diào)到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+屏幕刷新時(shí)間(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<std::weak_ptr<VsyncWaiter>*>(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) {
//判斷之前設(shè)置的callback是否被設(shè)置為null了,若設(shè)置為null了也就沒必要回調(diào)了
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的信號(hào)回調(diào)
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);
//執(zhí)行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);
}
}
這里的回調(diào)信號(hào)會(huì)post到UI線程中執(zhí)行,同時(shí)UI線程會(huì)在
MessageLoop::RunExpiredTasks
將消息取出來執(zhí)行。
- 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<fml::closure> invocations;
//取出task中的消息
task_queue_->GetTasksToRunNow(queue_id_, type, invocations);
//執(zhí)行取出的消息
for (const auto& invocation : invocations) {
invocation();
std::vector<fml::closure> observers =
task_queue_->GetObserversToNotify(queue_id_);
for (const auto& observer : observers) {
observer();
}
}
}
從task_queue 中取出對應(yīng)的消息,并執(zhí)行invocation炼邀,此方法將真正執(zhí)行對應(yīng)的callback(
AsyncWaitForVsync
中的callback)
- 6.message_loop_tast_queues.cc
MessageLoopTaskQueues::GetTasksToRunNow
void MessageLoopTaskQueues::GetTasksToRunNow(
TaskQueueId queue_id,
FlushType type,
std::vector<fml::closure>& invocations) {
std::lock_guard guard(queue_mutex_);
//是否有掛起的task
if (!HasPendingTasksUnlocked(queue_id)) {
return;
}
const auto now = fml::TimePoint::Now();
//判斷是否有掛起的任務(wù),有取出來并判斷時(shí)間是否到了吃沪,到了立馬執(zhí)行
while (HasPendingTasksUnlocked(queue_id)) {
TaskQueueId top_queue = _kUnmerged;
const auto& top = PeekNextTaskUnlocked(queue_id, top_queue);
//判斷隊(duì)列的頭時(shí)間是否可以執(zhí)行汤善,不可以執(zhí)行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睡眠當(dāng)前l(fā)oop,直到下一次message的到來
WakeUpUnlocked(queue_id, fml::TimePoint::Max());
} else {
//若有掛起的task票彪,執(zhí)行并設(shè)置下次喚醒的時(shí)間
WakeUpUnlocked(queue_id, GetNextWakeTimeUnlocked(queue_id));
}
}
//為當(dāng)前隊(duì)列設(shè)置wakeup的喚醒時(shí)間
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);
}
}
此方法會(huì)從消息隊(duì)列中循環(huán)取出隊(duì)列的消息
1.若沒有掛起的task消息红淡,那么將當(dāng)前的loop進(jìn)行睡眠直到新的消息到來喚醒(time = fml::TimePoint::Max())
2.若有掛起的task消息,但是時(shí)間沒有到top.GetTargetTime() > now
,那么將當(dāng)前的loop進(jìn)行睡眠到message執(zhí)行的時(shí)間
3.若有掛起的task且時(shí)間是top.GetTargetTime() <= now
,那么將執(zhí)行此消息降铸。然后將loop睡眠到下個(gè)message執(zhí)行的時(shí)間
- 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
///復(fù)用上一次的圖層庫
void Animator::DrawLastLayerTree() {
//釋放信號(hào)量在旱,vsync信號(hào)可再次注冊
pending_frame_semaphore_.Signal();
delegate_.OnAnimatorDrawLastLayerTree();
}
注意:delgate此處表示的是shell.cc:shell同時(shí)繼承了PlatformView::Delegate,Animator::Delegate推掸,Engine::Delegate桶蝎,所以在Engine驻仅,Animator,PlatformView中的成員變量delegate_都是指Shell對象登渣。
- shell.cc#OnAnimatorDrawLastLayerTree
void Shell::OnAnimatorDrawLastLayerTree() {
FML_DCHECK(is_setup_);
//將任務(wù)交給Raster線程(draw過程并為GPU下發(fā)指令的線程)處理
task_runners_.GetRasterTaskRunner()->PostTask(
[rasterizer = rasterizer_->GetWeakPtr()]() {
if (rasterizer) {
rasterizer->DrawLastLayerTree();
}
});
}
這里的Raster線程是對LayerTree進(jìn)行draw操作并將要draw內(nèi)容下發(fā)給GPU進(jìn)行渲染噪服。Raster的處理過程后邊文章介紹,本篇不進(jìn)行介紹胜茧。
- 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;
//非負(fù)信號(hào)量粘优,容量1,每次獲取會(huì)減1呻顽,釋放加1雹顺。控制vysnc的注冊`pending_frame_semaphore_(1),`
//此處+1
pending_frame_semaphore_.Signal();
if (!producer_continuation_) {
//若之前的layertree并沒有執(zhí)行Animation :: Render廊遍,此次直接啟用便可
//layer_tree_pipeline_(fml::MakeRefCounted<LayerTreePipeline>(2)) 這里的管道是最大深度是2嬉愧,即最大的執(zhí)行l(wèi)aytree為2,每次UI線程執(zhí)行poduce會(huì)減一喉前,Raster線程執(zhí)行Comsume之后會(huì)執(zhí)行一次加一操作没酣。
producer_continuation_ = layer_tree_pipeline_->Produce();
if (!producer_continuation_) {
//pipeline已滿,說明GPU線程繁忙被饿,則結(jié)束本次UI繪制四康,重新注冊Vsync
RequestFrame();
return;
}
}
FML_DCHECK(producer_continuation_);
//從pipeline中獲取有效的continuation,并準(zhǔn)備為可能的frame服務(wù)
last_frame_begin_time_ = frame_start_time;
//獲取當(dāng)前幀繪制截止時(shí)間狭握,用于告知可GC的空閑時(shí)長
last_frame_target_time_ = frame_target_time;
dart_frame_deadline_ = FxlToDartOrEarlier(frame_target_time);
{
TRACE_EVENT2("flutter", "Framework Workload", "mode", "basic", "frame",
FrameParity());
//執(zhí)行繪制
delegate_.OnAnimatorBeginFrame(frame_target_time);
}
if (!frame_scheduled_) {
//執(zhí)行完繪制之后需要通知UI,閑置
task_runners_.GetUITaskRunner()->PostDelayedTask(
[self = weak_factory_.GetWeakPtr(),
notify_idle_task_id = notify_idle_task_id_]() {
if (!self.get()) {
return;
}
//如果我們(此任務(wù)的)任務(wù)ID與當(dāng)前任務(wù)ID相同(表示發(fā)布此任務(wù)的| BeginFrame |調(diào)用沒有后續(xù)框架)并且當(dāng)前沒有可處理的frame疯溺,通知引擎當(dāng)前處于空閑狀態(tài) 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幀的時(shí)間+1ms,之所以這樣設(shè)計(jì)是由于在某些工作負(fù)載下(比如父視圖調(diào)整大小囱嫩,通過viewport metrics事件傳達(dá)給子視圖)實(shí)際上還沒有schedule幀恃疯,盡管在下一個(gè)vsync會(huì)生成一幀(將在收到viewport事件后schedule),因此推遲調(diào)用OnAnimatorNotifyIdle一點(diǎn)點(diǎn)墨闲,從而避免可能垃圾回收在不希望的時(shí)間觸發(fā)今妄。
- 11.shell.cc
Shell::OnAnimatorNotifyIdle
以下都是一系列調(diào)用過程
// |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<tonic::DartState> 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是對應(yīng)的。
BeginFrame 方法此時(shí)執(zhí)行了
1._beginFrame 執(zhí)行到了window.dart的onBeginFrame
2.FlushMicrotasksNow 這里便是我們平常使用的scheduleMicrotask異步事件鸳碧,這里進(jìn)行了執(zhí)行盾鳞,所以我們的Microtask本身耗時(shí)的話會(huì)阻塞我們的UI線程
3._drawFrame 執(zhí)行到了window.dart的onDrawFrame
從hooks.dart 中可以知道
@pragma('vm:entry-point')
// ignore: unused_element
void _beginFrame(int microseconds) {
_invoke1<Duration>(window.onBeginFrame, window._onBeginFrameZone, Duration(microseconds: microseconds));
}
@pragma('vm:entry-point')
// ignore: unused_element
void _drawFrame() {
_invoke(window.onDrawFrame, window._onDrawFrameZone);
}