环境: flutter sdk v1.7.8+hotfix.3@stable
对应 flutter engine: 54ad777f
这里关注的是 C ++ 层面的绘制流程,平台怎样驱动和响应绘制与渲染的过程,并不是 Dart 部分的渲染。
结合之前的分析,在虚拟机实例的构造函数中调用了一个重要方法DartUI::InitForGlobal()
, 调用流程再罗列一下:
DartVMRef::Create
DartVMRef::DartVMRef
DartVM::Create
DartVMData::Create
DartVM::DartVM
DartUI::InitForGlobal()
实现体很明了,注册了各种类对象的方法,也就是说,这些在 dart 语言继承 NativeFieldWrapperClass2
的类都有一份在 C ++ 层的实现,也说明了 DartSDK 是如何提供接口绑定与 C ++ 层的实现,相当于 java 语言中的 jni。
另外还有针对 Isolate
的初始化,不过只是设置了一个可以 import 的路径,并不重要:
DartIsolate::CreateRootIsolate
DartIsolate::CreateDartVMAndEmbedderObjectPair
DartIsolate::LoadLibraries
DartUI::InitForIsolate
Dart_SetNativeResolver
视口设置
我们知道 RuntimeController 持有一个 Window 实例,看 Window 实例被创建之后做了哪些制作:
RuntimeController::RuntimeController
Window::Window
DartIsolate::CreateRootIsolate
DartIsolate::DartIsolate
DartIsolate::SetWindow => UIDartState::SetWindow
WindowClient::UpdateIsolateDescription => RuntimeController::UpdateIsolateDescription
RuntimeDelegate::UpdateIsolateDescription => Shell::UpdateIsolateDescription
ServiceProtocol::SetHandlerDescription
Window::DidCreateIsolate
library_.Set("dart:ui")
RuntimeController::FlushRuntimeStateToIsolate
RuntimeController::SetViewportMetrics
Window::UpdateWindowMetrics
library_, _updateWindowMetrics
操作从最里层的 Window
一直传递到了Shell
, 最重要的一个作用是初始化了 ViewPort(视口:用作画布的大小,分辨率等尺寸信息),再跟一下 ViewPort 被初始化后又如何被设置的:
FlutterView.onSizeChanged
FlutterView.updateViewportMetrics
FlutterJNI.setViewportMetrics
FlutterJNI.nativeSetViewportMetrics
::SetViewportMetrics
AndroidShellHolder::SetViewportMetrics
[async:ui]Engine::SetViewportMetrics
RuntimeController::SetViewportMetrics
Window::UpdateWindowMetrics
Engine::ScheduleFrame
这里从 Java 调用到 C ++,FlutterView.onSizeChanged
这个操作是在 FlutterView
实例创建之后被系统调用的(而 FlutterView 的创建发生在 Activity.onCreate
时机),显然是响应平台层的通知,这符合我们的认知预期,因为画布的大小可能因为用户操作发生变化,dart 层需要被动响应。
需要注意的是响应 onSizeChanged
在 Platform 线程,调用 Engine::SetViewportMetrics
切到了 UI 线程,铭记 Engine
的所有的操作都是在 UI 线程。
启动画帧
Engine
在通过 RuntimeController
设置了窗口的尺寸之后,调用了另一个重要方法ScheduleFrame
, 于是看它的实现:
Engine::ScheduleFrame
Animator::RequestFrame
[async:ui]Animator::AwaitVSync
VsyncWaiter::AsyncWaitForVsync
callback_= {Animator::BeginFrame}
VsyncWaiter::AwaitVSync => VsyncWaiterAndroid::AwaitVSync
[async:platform]FlutterJNI.asyncWaitForVsync
AsyncWaitForVsyncDelegate.asyncWaitForVsync => VsyncWaiter.asyncWaitForVsyncDelegate
Choreographer.getInstance().postFrameCallback
Delegate::OnAnimatorNotifyIdle => Shell::OnAnimatorNotifyIdle
Engine::NotifyIdle
通知 VSync
这里操作有些凌乱,首先切到 UI 线程,又切到 Platform 线程,其实就是为了调用平台接口,搞清这个最终目的。
终于涉及到了绘制图像所需要的关键类 Animator
和VSyncWaiter
:
- 在 UI 线程等待
VSync
信号,表示信号到达后执行Animator::BeginFrame
方法; - 如何设置
VSync
信号?通过调用平台接口,平台操作必须都在 Platform 线程,于是从 UI 线程切到 Platform 线程,目的是去调用 android 的Choreographer.postFrameCallback
,这样又执行了一串从 C ++ 调到 java 的过程。
响应 VSync
因为是在 java 层调用的 VSync
回调,只能先在 Java 层响应于是有:
FrameCallback.doFrame <= VsyncWaiter.asyncWaitForVsyncDelegate
FlutterJNI.nativeOnVsync
VsyncWaiterAndroid::OnNativeVsync
VsyncWaiterAndroid::ConsumePendingCallback
VsyncWaiter::FireCallback
[async:ui]callback() => Animator::BeginFrame
在 VSync 信号到达之后,最终在 UI 线程响应了Animator::BeginFrame
,且看其实现:
Animator::BeginFrame
Animator::Delegate::OnAnimatorBeginFrame => Shell::
Engine::BeginFrame
Window::BeginFrame
library_."_beginFrame" => hooks.dart:_beginFrame
UIDartState::FlushMicrotasksNow
tonic::DartMicrotaskQueue::RunMicrotasks
library_."_drawFrame" => hooks.dart:_drawFrame
最终的最终回到了 dart 层,并调用了其两个重要方法:_beginFrame
和_drawFrame
,完成了帧的绘制。
VSync 创建
另外罗列一下 VSyncWaiter
创建时机:
Shell::CreateShellOnPlatformThread
PlatformView::CreateVSyncWaiter => PlatformViewAndroid::CreateVSyncWaiter
VsyncWaiterAndroid()
Animator::Animator
Engine::Engine
它是与创建 Shell 同样的时机,也就是说在 Platform 线程由 PlatformView::CreateVSyncWaiter
创建的,并被 Animator
持有,而 Animator
又是被 Engine
持有。VSyncWaiter
与 Engine
一样,所有的操作都必须在 UI 线程中执行
窗口渲染
窗口的渲染是由 Dart 层的 Window 完成的,其实调用了 C ++ 层的实现:
("Window_render", Render)
Render() (window.cc:30)
Scene=
WindowClient::Render
Scene::takeLayerTree
RuntimeDelegate::Render => Engine::Render
ProducerContinuation::Complete(layer_tree)
Animator::Delegate::OnAnimatorDraw => Shell::OnAnimatorDraw(layer_tree_pipeline_)
[async:gpu]Rasterizer::Draw => android_shell_holder.cc:76
Rasterizer::DoDraw
Rasterizer::DrawToSurface
Surface::AcquireFrame
ExternalViewEmbedder::BeginFrame
CompositorContext::AcquireFrame
ScopedFrame::Raster
SurfaceFrame::Submit
ExternalViewEmbedder::SubmitFrame
FireNextFrameCallbackIfPresent
Rasterizer::Delegate::OnFrameRasterized
"Window_scheduleFrame", ScheduleFrame
这里涉及的对象更多了,而且紧密的与 Dart 层的绘制与渲染机制关联。值得注意的是具体的绘制操作(光栅化)是在 GPU 线程进行。
另外 Dart 层的 Window 也需要主动的调度帧,因此也绑定了 ScheduleFrame
方法。