±à¼ÍƼö: |
±¾ÎÄÖ÷ÒªÏêϸ½éÉÜÁËUIÏß³ÌäÖȾ¡¢UIÏß³ÌäÖȾÁ÷³Ìͼ¡¢VSYNC×¢²áÁ÷³Ì£¬Framework²ã»æÖÆ£¬Ï£Íû¶ÔÄúÄÜÓÐËù°ïÖú¡£
±¾ÎÄÀ´×ÔÓÚgityuan,ÓÉ»ðÁú¹ûÈí¼þDelores±à¼ÍƼö¡£ |
|
Ò»¡¢UIÏß³ÌäÖȾ
FlutterÊǹȸ迪ԴµÄÒÆ¶¯UI¿ò¼Ü£¬¿ÉÒÔ¿ìËÙÔÚAndroidºÍiOSÉϹ¹½¨³ö¸ßÖÊÁ¿µÄÔÉúÓû§½çÃæ£¬Ä¿Ç°È«ÊÀ½çÔ½À´Ô½¶àµÄ¿ª·¢Õß¼ÓÈëµ½FlutterµÄ¶ÓÎé¡£ FlutterÏà±ÈRNÐÔÄܸüºÃ£¬ÓÉÓÚFlutter×Ô¼ºÊµÏÖÁËÒ»Ì×UI¿ò¼Ü£¬¶ªÆúÁËÔÉúµÄUI¿ò¼Ü£¬·Ç³£½Ó½üÔÉúµÄÌåÑé¡£
ΪÁ˽ÒÃØFlutter¸ßÐÔÄÜ£¬±¾ÎÄ´ÓÔ´Âë½Ç¶ÈÀ´¿´¿´FlutterµÄäÖȾ»æÖÆ»úÖÆ£¬¸úäÖȾֱ½ÓÏà¹ØµÄÁ½¸öÏß³ÌÊÇUIÏ̺߳ÍGPUỊ̈߳º
UIỊ̈߳ºÔËÐÐ×ÅUI Task Runner£¬ÊÇFlutter EngineÓÃÓÚÖ´ÐÐDart root isolate´úÂ룬½«Æäת»»Îªlayer treeÊÓͼ½á¹¹£»
GPUỊ̈߳º¸ÃÏß³ÌÒÀÈ»ÊÇÔÚCPUÉÏÖ´ÐУ¬ÔËÐÐ×ÅGPU Task Runner£¬´¦Àílayer tree£¬½«Æäת»»³ÉΪGPUÃüÁî²¢·¢Ë͵½GPU¡£
ͨ¹ýVSYNCÐźÅʹUIÏ̺߳ÍGPUÏß³ÌÓÐÌõ²»ÎɵÄÖÜÆÚÐÔµÄäÖȾ½çÃæ£¬±¾ÎĽéÉÜVSYNCµÄ²úÉú¹ý³Ì¡¢UIÏß³ÌÔÚÒýÇæºÍ¿ò¼ÜµÄ»æÖƹ¤×÷£¬ÏÂһƪÎÄÕ»á½éÉÜGPUÏ̵߳ĻæÖƹ¤×÷¡£
1.1 UIäÖȾÔÀí
1.1.1 UIäÖȾ¸ÅÀÀ
ͨ¹ýVSYNCÐźÅʹUIÏ̺߳ÍGPUÏß³ÌÓÐÌõ²»ÎɵÄÖÜÆÚÐÔµÄäÖȾ½çÃæ£¬ÈçÏÂͼËùʾ£º

µ±ÐèÒªäÖȾÔò»áµ÷Óõ½EngineµÄScheduleFrame()À´×¢²áVSYNCÐźŻص÷£¬Ò»µ©´¥·¢»Øµ÷doFrame()Ö´ÐÐÍê³Éºó£¬±ã»áÒÆ³ý»Øµ÷·½·¨£¬Ò²¾ÍÊÇ˵һ´Î×¢²áÒ»´Î»Øµ÷£»
µ±ÐèÒªÔٴλæÖÆÔòÐèÒªÖØÐµ÷Óõ½ScheduleFrame()·½·¨£¬¸Ã·½·¨µÄÎ¨Ò»ÖØÒª²ÎÊýregenerate_layer_tree¾ö¶¨ÔÚÖ¡»æÖƹý³ÌÊÇ·ñÐèÒªÖØÐÂÉú³Élayer tree£¬»¹ÊÇÖ±½Ó¸´ÓÃÉÏÒ»´ÎµÄlayer tree£»
UIÏ̵߳ĻæÖƹý³Ì£¬×îºËÐĵÄÊÇÖ´ÐÐWidgetsBindingµÄdrawFrame()·½·¨£¬È»ºó»á´´½¨layer treeÊÓͼÊ÷
ÔÙ½»ÓÉGPU Task Runner½«layer treeÌṩµÄÐÅϢת»¯ÎªÆ½Ì¨¿ÉÖ´ÐеÄGPUÖ¸Áî¡£
1.1.2 UI»æÖƺËÐŤ×÷
1£©Vsyncµ¥×¢²áģʽ£º±£Ö¤ÔÚÒ»Ö¡µÄʱ¼ä´°¿ÚÀïUIÏß³ÌÖ»»áÉú³ÉÒ»¸ölayer tree·¢Ë͸øGPUỊ̈߳¬ÔÀíÈçÏ£º
AnimatorÖеÄÐźÅÁ¿pending_frame_semaphore_ÓÃÓÚ¿ØÖƲ»ÄÜÁ¬ÐøÆµ·±µØµ÷ÓÃVsyncÇëÇó£¬Ò»´ÎÖ»ÄÜ´æÔÚVsync×¢²á¡£ pending_frame_semaphore_³õʼֵΪ1£¬ÔÚAnimator::RequestFrame()Ïû·ÑÐźŻá¼õ1£¬µ±¶øºóÔٴε÷ÓÃÔò»áʧ°ÜÖ±½Ó·µ»Ø£» AnimatorµÄBeginFrame()»òÕßDrawLastLayerTree()·½·¨»áÖ´ÐÐÐźżÓ1²Ù×÷¡£
2£©UI»æÖÆ×îºËÐĵķ½·¨ÊÇdrawFrame()£¬°üº¬ÒÔϼ¸¸ö¹ý³Ì£º
Animate: ±éÀú_transientCallbacks£¬Ö´Ðж¯»»Øµ÷·½·¨£»
Build: ¶ÔÓÚdirtyµÄÔªËØ»áÖ´ÐÐbuild¹¹Ô죬ûÓÐdirtyÔªËØÔò²»»áÖ´ÐУ¬¶ÔÓ¦ÓÚbuildScope()
Layout: ¼ÆËãäÖȾ¶ÔÏóµÄ´óСºÍλÖ㬶ÔÓ¦ÓÚflushLayout()£¬Õâ¸ö¹ý³Ì¿ÉÄÜ»áǶÌ×ÔÙµ÷ÓÃbuild²Ù×÷£»
Compositing bits: ¸üоßÓÐÔàºÏ³ÉλµÄÈκÎäÖȾ¶ÔÏó£¬ ¶ÔÓ¦ÓÚflushCompositingBits()£»
Paint: ½«»æÖÆÃüÁî¼Ç¼µ½Layer£¬ ¶ÔÓ¦ÓÚflushPaint()£»
Compositing: ½«Compositing bits·¢Ë͸øGPU£¬ ¶ÔÓ¦ÓÚcompositeFrame()£»
Semantics: ±àÒëäÖȾ¶ÔÏóµÄÓïÒ壬²¢½«ÓïÒå·¢Ë͸ø²Ù×÷ϵͳ£¬ ¶ÔÓ¦ÓÚflushSemantics()¡£
UIÏ̵߳ĺÄʱ´ÓdoFrame(frameTimeNanos)ÖеÄframeTimeNanosΪÆðµã£¬ÒÔС½Ú[4.10.6]Animator::Render()·½·¨½áÊøÎªÖյ㣬 ²¢½«½á¹û±£´æµ½LayerTreeµÄ³ÉÔ±±äÁ¿construction_time_£¬Õâ±ãÊÇUIÏ̵߳ĺÄʱʱ³¤¡£
1.1.3 Timeline˵Ã÷
3£©ÒÔÉϼ¸¸ö¹ý³ÌÔÚTimelineÖÐuiÏß³ÌÖж¼ÓÐÌåÏÖ£¬ÈçÏÂͼËùʾ£º

ÁíÍâTimelineÖл¹ÓÐÁ½¸ö±È½Ï³£¼ûµÄ±êÇ©Ïî
¡°Frame Request Pending¡±£º´ÓAnimator::RequestFrame µ½Animator::BeginFrame()½áÊø£»
¡±PipelineProduce¡°£º ´ÓAnimator::BeginFrame()µ½Animator::Render()½áÊø¡£
1.2 UIÏß³ÌäÖȾÁ÷³Ìͼ
1.2.1 VSYNC×¢²áÁ÷³Ì
VSYNC×¢²áÁ÷³Ìͼ

µ±µ÷Óõ½ÒýÇæEngineµÄScheduleFrame()·½·¨¹ý³ÌÔò»á×¢²áVSYNCÐźŻص÷£¬Ò»µ©VsyncÐźŴﵽ£¬Ôò»áµ÷Óõ½doFrame()·½·¨¡£ ¶ÔÓÚµ÷ÓÃScheduleFrame()µÄ³¡¾°ÓжàÖÖ£¬±ÈÈ綯»µÄÖ´ÐÐAnimationController.forward()£¬ÔÙ±ÈÈç±ÈÈçsurface´´½¨µÄʱºòshell::SurfaceCreated()¡£
1.2.2 Engine²ã»æÖÆ
Engine²ã´¦ÀíÁ÷³Ìͼ

doFrame()¾¹ý¶à²ãµ÷Óúóͨ¹ýPostTask½«ÈÎÎñÒì²½postµ½UI TaskRunnerÏß³ÌÀ´Ö´ÐУ¬×îºóµ÷Óõ½WindowµÄBeginFrame()·½·¨¡£
1.2.3 Framework²ã»æÖÆ
Framework²ã´¦ÀíÁ÷³Ìͼ

ÆäÖÐwindow.ccÖеÄÒ»¸öBeginFrame()·½·¨£¬»áµ÷Óõ½window.dartÖеÄonBeginFrame()ºÍonDrawFrame()Á½¸ö·½·¨¡£
1.3 ºËÐÄÀàͼ
Àà¹ØÏµÍ¼

ΪÁËÈôó¼Ò¸üÈÝÒ×Àí½âÔ´Â룬ÏÈ¿´Ò»ÕŹØÓÚShell¡¢Engine¡¢AnimatorµÈFlutterµÈFlutterÒýÇæÖкËÐÄÀàµÄÀàͼ¡£
WindowÀࣺÊÇÁ¬½ÓFlutter¿ò¼Ü²ã(Dart)ÓëÒýÇæ²ã(C++)µÄ¹Ø¼üÀ࣬ÔÚ¿ò¼Ü²ãÖÐwindow.dartÎļþÀïµÄһЩ·½·¨ÔÚÒýÇæ²ãµÄwindow.ccÎļþÓÐÏà¶ÔÓ¦µÄ·½·¨£¬±ÈÈçscheduleFrame()·½·¨¡£ ÔÚwindow.ccÀïÃæÍ¨¹ýWindow::RegisterNatives()×¢²áÁËһЩ¿ò¼Ü²ãÓëÒýÇæ²ãµÄ·½·¨¶ÔÓ¦¹ØÏµ£»
RuntimeControllerÀࣺ¿Éͨ¹ýÆä³ÉÔ±root_isolate_ÕÒµ½WindowÀࣻ
ShellÀࣺͬʱ¼Ì³ÐÁËPlatformView::Delegate£¬Animator::Delegate£¬Engine::Delegate£¬ËùÒÔÔÚEngine£¬Animator£¬PlatformViewÖеijÉÔ±±äÁ¿delegate_¶¼ÊÇÖ¸Shell¶ÔÏó£¬ ´ÓͼÖÐÒ²ÄÜ¿´³öÆäÖÐÐĵØÎ»£¬´úÀí¶àÏîÒµÎñ£¬¸ÃÀàÊÇÓÉAndroidShellHolder¹ý³ÌÖгõʼ»¯´´½¨µÄ£»ÁíÍâShellÀ໹¼Ì³ÐÁËServiceProtocol::Handler£¬Í¼ÖÐÊ¡ÂÔ¶øÒÑ¡£
PlatformViewAndroidÀࣺÔÚAndroidƽ̨ÉÏPlatformViewµÄʵÀý²ÉÓõıãÊÇPlatformViewAndroidÀà¡£
Dart²ãÓëC²ãÖ®¼ä¿ÉÒÔÏ໥µ÷Ó㬴ÓWindowһ·Äܵ÷Óõ½ShellÀ࣬ҲÄÜ´ÓShellÀàһ·µ÷ÓûØWindow¡£
½ÓÏÂÀ´´ø×Å´ó¼Ò´ÓÔ´Âë½Ç¶ÈÀ´ÒÀ´Î½²½âVsync×¢²áÒÔ¼°UIÏ̵߳ĻæÖÆ´¦ÀíÁ÷³Ì£¬ÏÂһƪÎÄÕ»á½éÉÜGPUÏ̵߳ĻæÖƹ¤×÷¡£
¶þ¡¢ VSYNC×¢²áÁ÷³Ì
2.1 Engine::ScheduleFrame
[-> flutter/shell/common/engine.cc]
void Engine::ScheduleFrame (bool
regenerate_layer_tree) {
//[¼ûС½Ú2.2]
animator_->RequestFrame (regenerate_layer_tree);
} |
¸Ã·½·¨ËµÃ÷£º
animator_µÄ¸³Öµ¹ý³ÌÊÇÔÚEngine¶ÔÏó³õʼ»¯¹ý³ÌÍê³É£¬¶øEngine³õʼ»¯¹ý³ÌÔÚShell´´½¨¹ý³Ì£¬´Ë´¦animator_±ãÊÇAnimator¶ÔÏó£»
ScheduleFrameµÄ²ÎÊýregenerate_layer_tree¾ö¶¨ÊÇ·ñÐèÒªÖØÐÂÉú³Élayer tree£¬»¹ÊÇÖ±½Ó¸´ÓÃÉÏÒ»´ÎÉú³ÉµÄlayer tree£»
¾ø´ó¶àÊýÇé¿öÏ£¬µ÷ÓÃRequestFrame()ʱ½«regenerate_layer_tree_ÉèÖÃΪtrue»òÕßÓÃĬÈÏÖµtrue£¬Ö´ÐÐÍêAnimator::BeginFrame()ÔòÉèÖøñäÁ¿Îªfalse£»
µ±ÎÞ²ÎÊýµ÷Óø÷½·¨Ê±£¬regenerate_layer_treeΪĬÈÏֵΪtrue¡£
ÌØ±ðµÄÀý×Ó¾ÍÊÇShell::OnPlatformViewMarkTextureFrameAvailable()¹ý³Ì£¬ÉèÖòÎÊýΪfalse£¬ÄÇô¼Æ»®»æÖÆÒ»Ö¡µÄʱºò¾Í²»ÐèÒªÖØ»ælayer tree£»
2.2 Animator::RequestFrame
[-> flutter/shell/common/animator.cc]
void Animator::RequestFrame
(bool
regenerate_layer_tree) {
if (regenerate_layer_tree) {
// regenerate_layer_tree_¾ö¶¨ VsyncÐźŵ½À´Ê±£¬ÊÇ·ñÖ´ÐÐBeginFrame
regenerate_layer_tree_ = true;
}
//µ±µ÷ÓÃAnimator::Stop() Ôò»áÍ£Ö¹¶¯»»æÖÆ
if (paused_ && !dimension_change_pending_)
{
return;
}
//µ÷ÓÃsem_trywaitÀ´±£Ö¤²»»áͬʱ Óжà¸övsyncÇëÇó
if (!pending_frame_semaphore_. TryWait()) {
return;
}
task_runners_.GetUITaskRunner() ->PostTask([self
= weak_factory_. GetWeakPtr(),
frame_number = frame_number_]() {
if (!self.get()) {
return;
}
TRACE_EVENT_ASYNC_BEGIN0("flutter",
"Frame Request Pending", frame_number);
self->AwaitVSync(); // [¼ûС½Ú2.3]
});
frame_scheduled_ = true; //±ê×¢ÒѾschedule»æ»Ö¡
} |
¹ý³Ì˵Ã÷£º
pending_frame_semaphore_£º·Ç¸ºÐźÅÁ¿£¬³õʼֵΪ1£¬µÚÒ»´Îµ÷ÓÃTryWait¼õ1£¬¶øºóÔٴε÷ÓÃÔò»áʧ°ÜÖ±½Ó·µ»Ø¡£µ±Ïû·ÑÁËÕâ´Îvsync»Øµ÷£¬Ò²¾ÍÊǵ÷ÓÃÁËAnimatorµÄBeginFrame()»òÕßDrawLastLayerTree()·½·¨ºó£¬¸ÄÐźÅÁ¿»á¼Ó1[¼ûС½Ú3.6]£¬¿ÉÒÔÔÙ´ÎÖ´ÐÐvysncµÄ×¢²á£»
ͨ¹ýAnimatorµÄStart()»òÕßBeginFrameµ÷Óõ½µÄRequestFrame·½·¨£¬Ôò¿Ï¶¨ÐèÒªÖØÐÂÉú³Élayer tree£»Í¨¹ýEngineµÄScheduleFrame·½·¨ÊÇ·ñÖØ½¨layer tree¿´Ð¡½Ú2.1£»
´Ë´¦Í¨¹ýpost°ÑAnimator::AwaitVSyncÈÎÎñ·ÅÈëµ½UI Task RunnerÀ´Ö´ÐС£
2.3 Animator::AwaitVSync
[-> flutter/shell/common/animator.cc]
void Animator::AwaitVSync()
{
// [¼ûС½Ú2.4]
waiter_->AsyncWaitForVsync(
[self = weak_factory_.GetWeakPtr()] (fml::TimePoint
frame_start_time,
fml::TimePoint frame_target_time) {
if (self) {
//ÊÇ·ñÄܸ´ÓÃÉÏ´ÎlayerÊ÷£¬ È¡¾öÓÚregenerate_layer_tree_
if (self->CanReuseLastLayerTree()) {
//¸´ÓÃÉÏ´ÎlayerÊ÷£¬Ö±½Ó°ÑÈÎÎñpostµ½ gpuÏß³Ì×öÕ¤¸ñ»¯²Ù×÷
self->DrawLastLayerTree();
} else {
self->BeginFrame(frame_start_time, frame_target_time);
}
}
});
delegate_.OnAnimatorNotifyIdle (dart_frame_deadline_);
} |
waiter_µÄ¸³ÖµÊÇÔÚAnimator³õʼ»¯¹ý³Ì£¬È¡ÖµÎªVsyncWaiterAndroid¶ÔÏ󣬵±µ÷ÓÃÁËRequestFrame()£¬Ä¬ÈϲÎÊýregenerate_layer_tree_Ϊtrue£¬Òâζ×ÅÐèÒªÖØÐÂÉú³ÉlayerÊ÷£¬¹Ê²»ÄÜÖØ¸´Ê¹ÓÃÉÏÒ»´ÎµÄlayerÊ÷£¬½Ó×ÅÀ´¿´Ò»ÏÂAsyncWaitForVsync()·½·¨µÄʵÏÖ¡£
2.4 VsyncWaiter::AsyncWaitForVsync
[-> flutter/shell/common/vsync_waiter.cc]
void VsyncWaiter::AsyncWaitForVsync (Callback
callback) {
{
std::lock_guard<std::mutex> lock(callback_mutex_);
//¸³Öµcallback_
callback_ = std::move(callback);
}
TRACE_EVENT0("flutter", "AsyncWaitForVsync");
AwaitVSync(); // [¼ûС½Ú2.5]
} |
´Ë´ÎµÄcallback_±ãÊÇ[С½Ú2.3]·½·¨ÖеIJÎÊý£¬¸Ã·½·¨¸ù¾Ýregenerate_layer_tree_À´¾ö¶¨Ö´ÐÐÁ÷¡£
µ±regenerate_layer_tree_=false£¬ÔòÖ´ÐÐDrawLastLayerTree();
µ±regenerate_layer_tree_=false£¬ÔòÖ´ÐÐBeginFrame();
2.5 VsyncWaiterAndroid::AwaitVSync
[-> flutter/shell/platform/android/vsync_waiter_android.cc]
void VsyncWaiterAndroid:: AwaitVSync()
{
std::weak_ptr<VsyncWaiter>* weak_this =
new std::weak_ptr<VsyncWaiter> (shared_from_this());
//»ñÈ¡VsyncWaiterµÄÈõÒýÓÃ
jlong java_baton = reinterpret _cast<jlong>(weak_this);
JNIEnv* env = fml::jni:: AttachCurrentThread();
// ´Ë´Îµ÷Óõ½Java²ãµÄ asyncWaitForVsync·½·¨£¬java_baton Ö¸ÏòVsyncWaiter
env->CallStaticVoidMethod (g_vsync_waiter_class->obj(),
//
g_async_wait_for_vsync_method_, //
java_baton //
);
} |
´Ë´¦g_vsync_waiter_class£¬g_async_wait_for_vsync_method_µÄ¸³Öµ¹ý³ÌÊÇÓÉJNI_OnLoadÍê³É£¬ÈçÏÂËùʾ¡£
2.5.1 JNI_OnLoad
[-> flutter/shell/platform/android/library_loader.cc]
JNIEXPORT jint
JNI_OnLoad (JavaVM* vm, void* reserved) {
// ³õʼ»¯JavaÐéÄâ»ú
fml::jni::InitJavaVM(vm);
JNIEnv* env = fml::jni:: AttachCurrentThread();
bool result = false;
// ×¢²áFlutterMain.
result = shell::FlutterMain:: Register(env);
// ×¢²áPlatformView [¼ûС½Ú2.5.2]
result = shell::PlatformViewAndroid ::Register(env);
// ×¢²áVSyncWaiter [¼ûС½Ú2.5.3]
result = shell::VsyncWaiterAndroid ::Register(env);
return JNI_VERSION_1_4;
} |
Ê״μÓÔØ¹²Ïí¿âʱÐéÄâ»ú»áµ÷Óô˷½·¨¡£
2.5.2 Register
[-> flutter/shell/platform/android/platform_view_android_jni.cc]
bool PlatformViewAndroid::
Register(JNIEnv*
env) {
//¼Ç¼FlutterCallbackInformation ÀàµÄÈ«¾ÖÒýÓÃ
g_flutter_callback_info_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/view /FlutterCallbackInformation"));
//¼Ç¼FlutterCallbackInformation¹¹Ô캯Êý
g_flutter_callback_info_constructor = env->GetMethodID(
g_flutter_callback_info_class->obj(), "<init>",
"(Ljava/lang/String;Ljava/lang/String; Ljava/lang/String;)V");
//¼Ç¼FlutterJNIÀàµÄÈ«¾ÖÒýÓÃ
g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/embedding /engine/FlutterJNI"));
//¼Ç¼SurfaceTextureÀàµÄÈ«¾ÖÒýÓÃ
g_surface_texture_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass ("android/graphics/SurfaceTexture"));
static const JNINativeMethod callback_info_methods[]
= {
{
.name = "nativeLookupCallbackInformation",
.signature = "(J)Lio/flutter/view /FlutterCallbackInformation;",
.fnPtr = reinterpret_cast<void*> (&shell::LookupCallbackInformation),
},
};
//×¢²áFlutterCallbackInformationµÄnativeLookupCallbackInformation()·½·¨
env->RegisterNatives (g_flutter_callback_info_class->obj(),
callback_info_methods,
arraysize(callback_info_methods)) != 0);
g_is_released_method =
env->GetMethodID (g_surface_texture_class->obj(),
"isReleased", "()Z");
fml::jni::ClearException(env);
g_attach_to_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "attachToGLContext",
"(I)V");
g_update_tex_image_method =
env->GetMethodID (g_surface_texture_class->obj(),
"updateTexImage", "()V");
g_get_transform_matrix_method = env->GetMethodID(
g_surface_texture_class->obj(), "getTransformMatrix",
"([F)V");
g_detach_from_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "detachFromGLContext",
"()V");
return RegisterApi(env);
} |
¸Ã·½·¨µÄÖ÷Òª¹¤×÷£º
¼Ç¼ºÍ×¢²áÀàFlutterCallbackInformation¡¢FlutterJNIÒÔ¼°SurfaceTextureÀàµÄÏà¹Ø·½·¨£¬ÓÃÓÚJavaºÍC++²ã·½·¨µÄÏ໥µ÷Óá£
2.5.3 Register
[-> flutter/shell/platform/android/vsync_waiter_android.cc]
bool VsyncWaiterAndroid::Register
(JNIEnv*
env) {
static const JNINativeMethod methods[] = ;
jclass clazz = env->FindClass ("io/flutter/view/VsyncWaiter");
g_vsync_waiter_class = new fml::jni ::ScopedJavaGlobalRef <jclass>(env,
clazz);
g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
g_vsync_waiter_class->obj(), "asyncWaitForVsync",
"(J)V");
return env->RegisterNatives (clazz, methods,
arraysize(methods)) == 0;
} |
¸Ã×¢²á¹ý³ÌÖ÷Òª¹¤×÷£º
½«Java²ãµÄVsyncWaiterÀàµÄnativeOnVsync()·½·¨£¬Ó³Éäµ½C++²ãµÄOnNativeVsync()·½·¨£¬ÓÃÓڸ÷½·¨µÄJavaµ÷ÓÃC++µÄ¹ý³Ì£»
½«Java²ãµÄVsyncWaiterÀàµÄasyncWaitForVsync()·½·¨£¬±£´æµ½C++²ãµÄg_async_wait_for_vsync_method_±äÁ¿£¬ÓÃÓڸ÷½·¨C++µ÷ÓÃJavaµÄ¹ý³Ì¡£
¿É¼û£¬½«µ÷ÓÃVsyncWaiterÀàµÄasyncWaitForVsync()·½·¨
2.6 asyncWaitForVsync[Java]
[-> flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java]
public class
VsyncWaiter {
// FlutterViewµÄË¢ÐÂʱ¼äÖÜÆÚ£¨16.7ms£©
public static long refreshPeriodNanos = 1000000000
/ 60;
private static HandlerThread handlerThread;
private static Handler handler;
static {
handlerThread = new HandlerThread ("FlutterVsyncThread");
handlerThread.start();
}
public static void asyncWaitForVsync (final
long cookie) {
if (handler == null) {
handler = new Handler (handlerThread.getLooper());
}
handler.post(new Runnable() {
@Override
public void run() {
//×¢²áÖ¡»Øµ÷·½·¨£¬¼ûС½Ú[2.6.1]/[2.6.2]
Choreographer.getInstance(). postFrameCallback (new
Choreographer.FrameCallback() {
@Override
public void doFrame (long frameTimeNanos) {
//frameTimeNanosÊÇVYSNC´¥·¢µÄʱ¼äµã£¬ Ò²¾ÍÊǼƻ®»æÖƵÄʱ¼äµã
nativeOnVsync(frameTimeNanos, frameTimeNanos
+ refreshPeriodNanos, cookie);
}
});
}
});
}
} |
ͨ¹ýHandler½«¹¤×÷postµ½FlutterVsyncThreadỊ̈߳¬¾ßÌåµÄ¹¤×÷ÊÇͨ¹ýChoreographerÀ´×¢²á»Øµ÷·½·¨doFrame()ÒÔ¼àÌýϵͳVSYNCÐźš£
2.6.1 Choreographer.getInstance
[-> Choreographer.java]
public static
Choreographer getInstance() {
return sThreadInstance.get(); //µ¥Àýģʽ
}
private static final ThreadLocal <Choreographer>
sThreadInstance =
new ThreadLocal<Choreographer>() {
protected Choreographer initialValue(){
//»ñÈ¡µ±Ç°Ïß³ÌFlutterVsyncThreadµÄLooper
Looper looper = Looper.myLooper();
// ³õʼ»¯Choreographer¶ÔÏó
return new Choreographer(looper);
}
};
private Choreographer(Looper looper) {
mLooper = looper;
//´´½¨Handler¶ÔÏó
mHandler = new FrameHandler(looper);
//´´½¨ÓÃÓÚ½ÓÊÕVSyncÐźŵĶÔÏó
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper)
: null;
mLastFrameTimeNanos = Long.MIN_VALUE; //ÉÏÒ»´ÎÖ¡»æÖÆÊ±¼äµã
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
mCallbackQueues = new CallbackQueue [CALLBACK_LAST
+ 1];
for (int i = 0; i <= CALLBACK_LAST; i++){
mCallbackQueues[i] = new CallbackQueue();
}
} |
´Ë´¦ChoreographerµÄmLooperºÍmHandler¶¼ÔËÐÐÔÚFlutterVsyncThreadÏ̡߳£
2.6.2 postFrameCallback
[-> Choreographer.java]
public void
postFrameCallback (FrameCallback callback) {
postFrameCallbackDelayed(callback, 0);
}
public void postFrameCallback Delayed(FrameCallback
callback, long delayMillis) {
postCallbackDelayedInternal (CALLBACK_ANIMATION,
callback, FRAME_CALLBACK_TOKEN, delayMillis);
}
private void postCallbackDelayedInternal (int
callbackType, Object action, Object token, long
delayMillis) {
synchronized (mLock) {
final long now = SystemClock. uptimeMillis();
final long dueTime = now + delayMillis;
//Ìí¼Óµ½mCallbackQueues¶ÓÁÐ
mCallbackQueues[callbackType]. addCallbackLocked (dueTime,
action, token);
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
...
}
}
} |
½«FrameCallback·½·¨¼ÓÈëµ½mCallbackQueues[CALLBACK_ANIMATION]»Øµ÷¶ÓÁÐÖС£
Èý¡¢Engine²ã»æÖÆ
3.1 doFrame
[-> Choreographer.java]
public void
doFrame (long frameTimeNanos) {
//Android FWÿ´Îµ±vsyncÐźŴ¥·¢£¬ Ôò»áµ÷Óø÷½·¨ [¼ûÏ·½]
nativeOnVsync(frameTimeNanos, frameTimeNanos +
refreshPeriodNanos, cookie);
} |
Vsync×¢²á¹ý³Ì¼û[С½Ú2.6] Choreographer.FrameCallback()¡£×¢²áÁËVysncÐźźó£¬Ò»µ©µ×²ãVsyncÐźŴ¥·¢£¬¾¹ý²ã²ãµ÷Óûص½FrameDisplayEventReceiverµÄ¹ý³Ì£¬È»ºó»áÓÐÒ»¸öͨ¹ýhandlerµÄ·½Ê½postµ½Ï̡߳±FlutterVsyncThread¡±À´Ö´ÐвÙ×÷£¬ ¾ßÌåÁ÷³Ì¼ûChoreographerÔÀí¡£½ô½Ó×ÅÔÙ´¦ÀíËùÓÐ×¢²áµÄdoCallbacks·½·¨£¬Ôò»áÖ´ÐÐChoreographer.FrameCallbackÖеÄdoFrame()·½·¨£¬ÈçÏÂËùʾ¡£
new Choreographer.FrameCallback(){
@Override
public void doFrame (long frameTimeNanos) {
//frameTimeNanosÊÇVYSNC´¥·¢µÄʱ¼äµã£¬ Ò²¾ÍÊǼƻ®»æÖƵÄʱ¼äµã [¼ûС½Ú3.2]
nativeOnVsync(frameTimeNanos, frameTimeNanos +
refreshPeriodNanos, cookie);
}
} |
3.2 OnNativeVsync
[-> flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java]
public class
VsyncWaiter {
...
// [¼ûС½Ú3.2.1]
private static native void nativeOnVsync(long
frameTimeNanos,
long frameTargetTimeNanos,
long cookie);
...
} |
ÓÉ[С½Ú2.5.3]¿ÉÖª£¬VsyncWaiter.javaÖÐµÄ nativeOnVsync¶ÔÓ¦ÓÚvsync_waiter_android.cc µÄOnNativeVsync()£¬¾ßÌå¹ý³ÌÔÚjni¼ÓÔØ¹ý³Ì³õʼ»¯£¬ÈçÏÂËùʾ¡£
3.2.1 OnNativeVsync[C++]
[-> flutter/shell/platform/android/vsync_waiter_android.cc]
static void
OnNativeVsync (JNIEnv* env, jclass jcaller,
jlong frameTimeNanos,
jlong frameTargetTimeNanos,
jlong java_baton) {
auto frame_time = fml:: TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds (frameTimeNanos));
auto target_time = fml::TimePoint ::FromEpochDelta(
fml::TimeDelta::FromNanoseconds (frameTargetTimeNanos));
//Ïû·Ñpending»Øµ÷[¼ûС½Ú3.3]
ConsumePendingCallback (java_baton, frame_time,
target_time);
} |
3.3 ConsumePendingCallback
[-> flutter/shell/platform/android/vsync_waiter_android.cc]
static void
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Ö¸ÏòVsyncWaiterµÄÈõÒýÓà [¼ûС½Ú3.4]
shared_this->FireCallback (frame_start_time,
frame_target_time);
}
} |
3.4 VsyncWaiter::FireCallback
[-> flutter/shell/common/vsync_waiter.cc]
void VsyncWaiter::FireCallback (fml::TimePoint
frame_start_time,
fml::TimePoint frame_target_time) {
Callback callback;
{
std::lock_guard<std::mutex> lock (callback_mutex_);
callback = std::move(callback_);
}
if (!callback) {
TRACE_EVENT_INSTANT0("flutter", "MismatchedFrameCallback");
return;
}
TRACE_EVENT0("flutter", "VsyncFireCallback");
//½«ÈÎÎñ·ÅÈëtask¶ÓÁÐ[¼ûС½Ú3.4.1]
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);
//¿ªÊ¼Ö´ÐÐvync [¼ûС½Ú3.5]
callback(frame_start_time, frame_target_time);
TRACE_FLOW_END("flutter", kVsyncFlowName,
flow_identifier);
},
frame_start_time);
} |
½«ÈÎÎñ±Õ°ü·ÅÈëtask¶ÓÁУ¬ÏûÏ¢LoopÒ»µ©½ÓÊܵ½ÏûÏ¢Ôò»á¶ÁÈ¡³öÀ´¡£
3.4.1 MessageLoopImpl::RunExpiredTasks
[-> flutter/fml/message_loop_impl.cc]
void MessageLoopImpl::
RunExpiredTasks()
{
TRACE_EVENT0("fml", "MessageLoop ::RunExpiredTasks");
std::vector<fml::closure> invocations;
{
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
//µ±Ã»Óдý´¦ÀíµÄtaskÔòÖ±½Ó·µ»Ø
if (delayed_tasks_.empty()) {
return;
}
auto now = fml::TimePoint::Now();
while (!delayed_tasks_.empty()) {
const auto& top = delayed_tasks_.top();
if (top.target_time > now) {
break;
}
invocations.emplace_back (std::move(top.task));
delayed_tasks_.pop();
}
WakeUp(delayed_tasks_.empty() ? fml::TimePoint::Max()
: delayed_tasks_.top().target_time);
}
for (const auto& invocation : invocations)
{
invocation(); // [¼ûС½Ú3.5]
for (const auto& observer : task_observers_)
{
observer.second();
}
}
} |
¶ÔÓÚuiÏ̴߳¦ÓÚÏûÏ¢loop״̬£¬Ò»µ©ÓÐʱ¼äµ½´ïµÄÈÎÎñÔò¿ªÊ¼Ö´ÐУ¬·ñÔò´¦ÓÚ¿ÕÏеȵÈ״̬¡£Ç°Ãæ[С½Ú3.4] VsyncWaiter::FireCallback¹ý³ÌÒѾÏò¸ÃuiÏß³ÌpostTask¡£ ¶ÔÓÚ²»¿É¸´ÓÃlayer treeµÄÇé¿öÔòµ÷ÓÃAnimator::BeginFrame()·½·¨¡£
3.5 callback
[-> flutter/shell/common/animator.cc]
[self = weak_factory_.GetWeakPtr()] (fml::TimePoint
frame_start_time,
fml::TimePoint frame_target_time) {
if (self) {
if (self->CanReuseLastLayerTree()) {
self->DrawLastLayerTree();
} else {
//¸ù¾ÝĬÈϲÎÊýregenerate_layer_tree_ Ϊtrue£¬ÔòÖ´Ðи÷ÖÖ§ [¼ûС½Ú3.6]
self->BeginFrame(frame_start_time, frame_target_time);
}
}
} |
´Ë´ÎµÄcallback¸³Öµ¹ý³ÌλÓÚ[С½Ú2.3]Animator::AwaitVSync()·½·¨µÄ±Õ°ü²ÎÊý£¬Ïà¹ØËµÃ÷£º
frame_start_time£º¼Æ»®¿ªÊ¼»æÖÆÊ±¼äµã£¬À´Ô´ÓÚdoFrame()·½·¨ÖеIJÎÊý£»
frame_target_time£º´Óframe_start_time¼ÓÉÏһ֡ʱ¼ä(16.7ms)µÄʱ¼ä£¬×÷Ϊ±¾´Î»æÖƵÄdeadline¡£
3.6 Animator::BeginFrame
[-> flutter/shell/common/animator.cc]
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");
frame_scheduled_ = false;
notify_idle_task_id_++;
regenerate_layer_tree_ = false;
//ÐźÅÁ¿¼Ó1£¬¿ÉÒÔ×¢²áеÄvsyncÐźţ¬ Ò²¾ÍÊÇÄÜÖ´ÐÐAnimator::RequestFrame()
pending_frame_semaphore_.Signal();
if (!producer_continuation_) {
//[С½Ú3.6.1]/[С½Ú3.6.2]
producer_continuation_ = layer_tree_pipeline_->Produce();
//pipelineÒÑÂú£¬ËµÃ÷GPUÏ̷߳±Ã¦£¬ Ôò½áÊø±¾´ÎUI»æÖÆ£¬ÖØÐÂ×¢²áVsync
if (!producer_continuation_) {
RequestFrame();
return;
}
}
//´ÓpipelineÖлñÈ¡ÓÐЧµÄcontinuation£¬ ²¢×¼±¸Îª¿ÉÄܵÄframe·þÎñ
last_begin_frame_time_ = frame_start_time;
//»ñÈ¡µ±Ç°Ö¡»æÖƽØÖ¹Ê±¼ä£¬ ÓÃÓÚ¸æÖª¿ÉGCµÄ¿ÕÏÐʱ³¤
dart_frame_deadline_ = FxlToDartOrEarlier (frame_target_time);
{
TRACE_EVENT2("flutter", "Framework
Workload", "mode", "basic",
"frame",
FrameParity());
//´Ë´¦delegate_ΪShell [С½Ú3.7]
delegate_.OnAnimatorBeginFrame (last_begin_frame_time_);
}
if (!frame_scheduled_) {
task_runners_.GetUITaskRunner() ->PostDelayedTask(
[self = weak_factory_.GetWeakPtr(),
notify_idle_task_id = notify_idle_task_id_]()
{
if (!self.get()) {
return;
}
// ¸ÃÈÎÎñidºÍµ±Ç°ÈÎÎñidÒ»Ö£¬ Ôò²»ÔÙÐèÒªÉó²éframe£¬ ¿ÉÒÔ֪ͨÒýÇæµ±Ç°´¦ÓÚ¿ÕÏÐ״̬£¬100ms
if (notify_idle_task_id == self->notify_idle_task_id_)
{
self->delegate_.OnAnimatorNotifyIdle (Dart_TimelineGetMicros()
+
100000);
}
},
kNotifyIdleTaskWaitTime); //ÑÓ³Ù51msÔÙ֪ͨÒýÇæ¿ÕÏÐ״̬
}
} |
¸Ã·½·¨Ö÷Òª¹¦ÄÜ˵Ã÷£º
layer_tree_pipeline_ÊÇÔÚAnimator¶ÔÏó³õʼ»¯µÄ¹ý³ÌÖд´½¨µÄLayerTreePipeline£¬ÆäÀàÐÍΪPipeline
´Ë´¦kNotifyIdleTaskWaitTimeµÈÓÚ51ms£¬µÈÓÚ3Ö¡µÄʱ¼ä+1ms£¬Ö®ËùÒÔÕâÑùÉè¼ÆÊÇÓÉÓÚÔÚijЩ¹¤×÷¸ºÔØÏ£¨±ÈÈ縸ÊÓͼµ÷Õû´óС£¬Í¨¹ýviewport metricsʼþ´«´ï¸ø×ÓÊÓͼ£©Êµ¼ÊÉÏ»¹Ã»ÓÐscheduleÖ¡£¬¾¡¹ÜÔÚÏÂÒ»¸övsync»áÉú³ÉÒ»Ö¡(½«ÔÚÊÕµ½viewportʼþºóschedule)£¬Òò´ËÍÆ³Ùµ÷ÓÃOnAnimatorNotifyIdleÒ»µãµã£¬´Ó¶ø±ÜÃâ¿ÉÄÜÀ¬»ø»ØÊÕÔÚ²»Ï£ÍûµÄʱ¼ä´¥·¢¡£
3.6.1 LayerTreePipeline³õʼ»¯
[-> flutter/shell/common/animator.cc]
Animator::Animator(Delegate&
delegate,
TaskRunners task_runners,
std::unique_ptr<VsyncWaiter> waiter)
: delegate_(delegate),
task_runners_(std::move(task_runners)),
waiter_(std::move(waiter)),
last_begin_frame_time_(),
dart_frame_deadline_(0),
layer_tree_pipeline_(fml ::MakeRefCounted<LayerTreePipeline>(2)),
... {} |
´Ë´¦LayerTreePipelineµÄ³õʼ»¯¹ý³ÌÈçÏ£º
using LayerTreePipeline
= Pipeline<flutter::LayerTree>; |
ÔÚpipeline.hµÄ¹ý³Ì»á³õʼ»¯Pipeline£¬¿É¼û³õʼֵempty_ = 2£¬available_ = 0£»
Pipeline(uint32_t
depth) : empty_(depth), available_(0) {} |
3.6.2 Pipeline::Produce
[-> flutter/synchronization/pipeline.h]
ProducerContinuation
Produce() {
//µ±¹ÜµÀ²»Îª¿Õ£¬ Ôò²»ÔÊÐíÔÙ´ÎÏò¹ÜµÀ¼ÓÈëÊý¾Ý
if (!empty_.TryWait()) {
return {};
}
//[¼ûС½Ú3.6.3]
return ProducerContinuation{
std::bind(&Pipeline::ProducerCommit,this,
std::placeholders::_1,
std::placeholders::_2), // continuation
GetNextPipelineTraceID()};
} |
ͨ¹ýÐźÅÁ¿empty_µÄ³õʼֵΪdepth(ĬÈϵÈÓÚ2)£¬À´±£Ö¤Í¬Ò»¸ö¹ÜµÀµÄÈÎÎñ×î¶à²»³¬¹ýdepth¸ö£¬Ã¿´ÎUIÏß³ÌÖ´ÐÐProduce()»á¼õ1£¬µ±GPUÏß³ÌÖ´ÐÐÍê³ÉConsume()·½·¨ºó²Å»áÖ´ÐмÓ1²Ù×÷¡£
3.6.3 ProducerContinuation³õʼ»¯
[-> flutter/synchronization/pipeline.h]
ProducerContinuation (Continuation
continuation, size_t trace_id)
: continuation_(continuation), trace_id_(trace_id)
{
TRACE_FLOW_BEGIN("flutter", "PipelineItem",
trace_id_);
TRACE_EVENT_ASYNC_BEGIN0 ("flutter",
"PipelineProduce", trace_id_);
} |
3.6.3 Pipeline.ProducerCommit
[-> flutter/synchronization/pipeline.h]
void ProducerCommit
(ResourcePtr
resource, size_t trace_id) {
{
std::lock_guard<std::mutex> lock(queue_mutex_);
queue_.emplace(std::move (resource), trace_id);
}
available_.Signal();
} |
3.7 Shell::OnAnimatorBeginFrame
[-> flutter/shell/common/shell.cc]
void Shell::OnAnimatorBeginFrame (fml::TimePoint
frame_time) {
if (engine_) {
engine_->BeginFrame(frame_time); // [С½Ú3.8]
}
} |
3.8 Engine::BeginFrame
[-> flutter/shell/common/engine.cc]
void Engine::BeginFrame (fml::TimePoint
frame_time) {
TRACE_EVENT0("flutter", "Engine::BeginFrame");
runtime_controller_ ->BeginFrame(frame_time);
// [С½Ú3.9]
} |
3.9 RuntimeController::BeginFrame
[-> flutter/runtime/runtime_controller.cc]
bool RuntimeController::BeginFrame (fml::TimePoint
frame_time) {
if (auto* window = GetWindowIfAvailable()) {
window->BeginFrame(frame_time); // [С½Ú3.10]
return true;
}
return false;
} |
3.10 Window::BeginFrame
[-> flutter/lib/ui/window/window.cc]
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);
//×¢Òâ´Ë´¦µÄframeTime±ãÊÇÇ°Ãæ С½Ú3.1ÖÐdoFrame·½·¨ÖÐ µÄ²ÎÊýframeTimeNanos
int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
// [¼ûС½Ú4.2]
DartInvokeField(library_.value(), "_beginFrame",
{Dart_NewInteger(microseconds)});
//Ö´ÐÐMicroTask
UIDartState::Current() ->FlushMicrotasksNow();
// [¼ûС½Ú4.4]
DartInvokeField(library_.value(), "_drawFrame",
{});
} |
Window::BeginFrame()¹ý³ÌÖ÷Òª¹¤×÷£º
Ö´ÐÐ_beginFrame
Ö´ÐÐFlushMicrotasksNow
Ö´ÐÐ_drawFrame
¿É¼û£¬MicrotaskλÓÚbeginFrameºÍdrawFrameÖ®¼ä£¬ÄÇôMicrotaskµÄºÄʱ»áÓ°Ïìui»æÖƹý³Ì¡£
DartInvokeField()ͨ¹ýdartÐéÄâ»úµ÷ÓÃÁËwindow.onBeginFrame()ºÍonDrawFrame·½·¨£¬¼ûhooks.dartÎļþÖÐÈçϹý³Ì
@pragma('vm:entry-point')
void _beginFrame (int microseconds) {
_invoke1<Duration> (window.onBeginFrame,
window._onBeginFrameZone, new Duration(microseconds:
microseconds));
}
@pragma('vm:entry-point')
void _drawFrame() {
_invoke(window.onDrawFrame, window._onDrawFrameZone);
} |
ËÄ¡¢Framework²ã»æÖÆ
ÔÚÒýÇæ²ãµÄ´¦Àí¹ý³Ì»áµ÷Óõ½window.onBeginFrame()ºÍonDrawFrame£¬»Øµ½framework²ã´ÓÕâ¸öÁ½¸ö·½·¨¿ªÊ¼ËµÆð¡£
4.1 SchedulerBinding.initInstances
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
mixin SchedulerBinding
on BindingBase, ServicesBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
ui.window.onBeginFrame = _handleBeginFrame; //[¼ûС½Ú4.2]
ui.window.onDrawFrame = _handleDrawFrame; //[¼ûС½Ú4.4]
SystemChannels.lifecycle. setMessageHandler (_handleLifecycleMessage);
}
} |
¿É¼û£¬ÒýÇæ²ãÖеÄWindow::BeginFrame()µ÷ÓõÄÁ½¸ö·½·¨£¬½øÈëµ½dart²ãÔò·Ö±ðÊÇ_handleBeginFrame()ºÍ_handleDrawFrame()·½·¨
4.1.1 Window³õʼ»¯
[-> flutter/lib/ui/window.dart]
class Window
{
Window._()
FrameCallback get onBeginFrame => _onBeginFrame;
FrameCallback _onBeginFrame;
VoidCallback get onDrawFrame => _onDrawFrame;
VoidCallback _onDrawFrame;
...
} |
Window³õʼ»¯¹ý³Ì£¬¿ÉÒÔÖªµÀonBeginFrameºÍonDrawFrame·Ö±ð±£´æ_onBeginFrameºÍ_onDrawFrame·½·¨¡£
4.2 _handleBeginFrame
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
void _handleBeginFrame (Duration
rawTimeStamp) {
if (_warmUpFrame) {
_ignoreNextEngineDrawFrame=true;
return;
}
handleBeginFrame(rawTimeStamp); //[¼ûС½Ú4.3]
} |
4.3 handleBeginFrame
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
void handleBeginFrame (Duration
rawTimeStamp) {
Timeline.startSync('Frame', arguments: timelineWhitelistArguments);
_firstRawTimeStampInEpoch ??= rawTimeStamp;
_currentFrameTimeStamp = _adjustForEpoch(rawTimeStamp
?? _lastRawTimeStamp);
if (rawTimeStamp != null)
_lastRawTimeStamp = rawTimeStamp;
profile(() {
_profileFrameNumber += 1;
_profileFrameStopwatch.reset();
_profileFrameStopwatch.start();
});
//´Ëʱ½×¶ÎµÈÓÚSchedulerPhase.idle;
_hasScheduledFrame = false;
try {
Timeline.startSync('Animate', arguments: timelineWhitelistArguments);
_schedulerPhase = SchedulerPhase. transientCallbacks;
//Ö´Ðж¯»µÄ»Øµ÷·½·¨
final Map<int, _FrameCallbackEntry> callbacks
= _transientCallbacks;
_transientCallbacks = <int, _FrameCallbackEntry>{};
callbacks.forEach((int id, _FrameCallbackEntry
callbackEntry) {
if (!_removedIds.contains(id))
_invokeFrameCallback (callbackEntry.callback,
_currentFrameTimeStamp, callbackEntry.debugStack);
});
_removedIds.clear();
} finally {
_schedulerPhase = SchedulerPhase. midFrameMicrotasks;
}
} |
¸Ã·½·¨Ö÷Òª¹¦ÄÜÊDZéÀú_transientCallbacks£¬Ö´ÐÐÏàÓ¦µÄAnimate²Ù×÷£¬¿Éͨ¹ýscheduleFrameCallback()/cancelFrameCallbackWithId()À´Íê³ÉÌí¼ÓºÍɾ³ý³ÉÔ±£¬ÔÙÀ´¼òµ¥¿´¿´ÕâÁ½¸ö·½·¨¡£
4.3.1 scheduleFrameCallback
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
int scheduleFrameCallback (FrameCallback
callback, { bool rescheduling = false }) {
scheduleFrame(); //´¥·¢Ö¡»æÖƵĵ÷¶È
_nextFrameCallbackId += 1;
_transientCallbacks [_nextFrameCallbackId] = _FrameCallbackEntry(callback,
rescheduling: rescheduling);
return _nextFrameCallbackId;
} |
callback±£´æÔÚ_FrameCallbackEntry¶ÔÏóÀïÃæ
4.3.2 cancelFrameCallbackWithId
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
void cancelFrameCallbackWithId (int
id) {
assert(id > 0);
_transientCallbacks.remove(id);
_removedIds.add(id);
} |
4.4 _handleDrawFrame
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
void _handleDrawFrame()
{
if (_ignoreNextEngineDrawFrame) {
_ignoreNextEngineDrawFrame = false;
return;
}
handleDrawFrame(); //[¼ûС½Ú4.5]
} |
4.5 handleDrawFrame
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
void handleDrawFrame()
{
assert(_schedulerPhase == SchedulerPhase.midFrameMicrotasks);
Timeline.finishSync(); // ±êʶ½áÊø"Animate"½×¶Î
try {
_schedulerPhase = SchedulerPhase. persistentCallbacks;
//Ö´ÐÐPERSISTENT FRAME»Øµ÷
for (FrameCallback callback in _persistentCallbacks)
_invokeFrameCallback(callback, _currentFrameTimeStamp);
//[¼ûС½Ú4.5.1]
_schedulerPhase = SchedulerPhase. postFrameCallbacks;
// Ö´ÐÐPOST-FRAME»Øµ÷
final List<FrameCallback> localPostFrameCallbacks
= List<FrameCallback>.from (_postFrameCallbacks);
_postFrameCallbacks.clear();
for (FrameCallback callback in localPostFrameCallbacks)
_invokeFrameCallback(callback, _currentFrameTimeStamp);
} finally {
_schedulerPhase = SchedulerPhase.idle;
Timeline.finishSync(); //±êʶ½áÊø¡±Frame¡°½×¶Î
profile(() {
_profileFrameStopwatch.stop();
_profileFramePostEvent();
});
_currentFrameTimeStamp = null;
}
} |
¸Ã·½·¨Ö÷Òª¹¦ÄÜ£º
±éÀú_persistentCallbacks£¬Ö´ÐÐÏàÓ¦µÄ»Øµ÷·½·¨£¬¿Éͨ¹ýaddPersistentFrameCallback()×¢²á£¬Ò»µ©×¢²áºó²»¿ÉÒÆ³ý£¬ºóÐøÃ¿Ò»´Îframe»Øµ÷¶¼»áÖ´ÐУ»
±éÀú_postFrameCallbacks£¬Ö´ÐÐÏàÓ¦µÄ»Øµ÷·½·¨£¬¿Éͨ¹ýaddPostFrameCallback()×¢²á£¬handleDrawFrame()Ö´ÐÐÍê³Éºó»áÇå¿Õ_postFrameCallbacksÄÚÈÝ¡£
4.5.1 _invokeFrameCallback
[-> lib/src/scheduler/binding.dart:: SchedulerBinding]
void _invokeFrameCallback (FrameCallback
callback, Duration timeStamp, [ StackTrace callbackStack
]) {
try {
callback(timeStamp); //[¼ûС½Ú4.5.2]
} catch (exception, exceptionStack){
FlutterError.reportError (FlutterErrorDetails(...));
}
} |
ÕâÀïµÄcallbackÊÇ_persistentCallbacksÁбíÖеijÉÔ±£¬ÔÙÀ´¿´¿´Æä³ÉÔ±ÊÇÈçºÎÌí¼Ó½øÈ¥µÄ¡£
4.5.2 WidgetsBinding.initInstances
[-> lib/src/widgets/binding.dart]
mixin WidgetsBinding
on BindingBase, SchedulerBinding, GestureBinding,
RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances(); //[¼ûС½Ú4.5.3]
_instance = this;
buildOwner.onBuildScheduled = _handleBuildScheduled;
ui.window.onLocaleChanged = handleLocaleChanged;
ui.window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
SystemChannels.navigation. setMethodCallHandler (_handleNavigationInvocation);
SystemChannels.system.setMessageHandler (_handleSystemMessage);
}
} |
ÔÚflutter appÆô¶¯¹ý³Ì£¬Ò²¾ÍÊÇÖ´ÐÐrunApp¹ý³Ì»áÓÐWidgetsFlutterBinding³õʼ»¯¹ý³Ì£¬WidgetsBindingµÄinitInstances()£¬¸ù¾ÝmixinµÄ˳Ðò£¬¿ÉÖª´Ë´¦µÄsuper.initInstances() ±ãÊÇRendererBindingÀà¡£
4.5.3 RendererBinding.initInstances
[-> lib/src/rendering/binding.dart]
mixin RendererBinding
on BindingBase, ServicesBinding, SchedulerBinding,
SemanticsBinding, HitTestable {
void initInstances() {
super.initInstances();
_instance = this;
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
ui.window
..onMetricsChanged = handleMetricsChanged
..onTextScaleFactorChanged = handleTextScaleFactorChanged
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
..onSemanticsAction = _handleSemanticsAction;
initRenderView();
_handleSemanticsEnabledChanged();
addPersistentFrameCallback (_handlePersistentFrameCallback);
//[¼ûС½Ú4.5.4]
}
void _handlePersistentFrameCallback (Duration
timeStamp) {
drawFrame(); //[¼ûС½Ú4.6]
}
} |
4.5.4 SchedulerBinding.addPersistentFrameCallback
[-> lib/src/scheduler/binding.dart]
mixin SchedulerBinding
on BindingBase, ServicesBinding {
void addPersistentFrameCallback (FrameCallback
callback) {
_persistentCallbacks.add(callback);
}
} |
4.6 WidgetsBinding.drawFrame
[-> lib/src/widgets/binding.dart]
void drawFrame()
{
try {
if (renderViewElement != null)
buildOwner.buildScope (renderViewElement); //[¼ûС½Ú4.6.1]
super.drawFrame(); //[¼ûС½Ú4.6.4]
buildOwner.finalizeTree(); //[¼ûС½Ú4.12]
} finally {
}
} |
4.6.1 BuildOwner.buildScope
[-> lib/src/widgets/framework.dart]
void buildScope(Element
context, [VoidCallback callback]) {
if (callback == null && _dirtyElements.isEmpty)
return;
Timeline.startSync('Build', arguments: timelineWhitelistArguments);
try {
_scheduledFlushDirtyElements = true;
if (callback != null) {
_dirtyElementsNeedsResorting = false;
callback(); //Ö´Ðлص÷·½·¨
}
_dirtyElements.sort(Element._sort); //ÅÅÐò
_dirtyElementsNeedsResorting = false;
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
try {
//¾ßÌåElement×ÓÀàÖ´ÐÐÖØ½¨²Ù×÷ [¼ûС½Ú4.6.2]
_dirtyElements[index].rebuild();
} catch (e, stack) {
}
index += 1;
if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting)
{
_dirtyElements.sort(Element._sort);
_dirtyElementsNeedsResorting = false;
dirtyCount = _dirtyElements.length;
while (index > 0 && _dirtyElements [index
- 1].dirty) {
index -= 1;
}
}
}
} finally {
for (Element element in _dirtyElements){
element._inDirtyList = false;
}
_dirtyElements.clear();
_scheduledFlushDirtyElements = false;
_dirtyElementsNeedsResorting = null;
Timeline.finishSync();
}
} |
4.6.2 Element.rebuild
[-> lib/src/widgets/framework.dart]
void rebuild()
{
if (!_active || !_dirty)
return;
performRebuild();
} |
performRebuild¾ßÌåÖ´Ðз½·¨£¬È¡¾öÓÚÏàÓ¦µÄElement×ÓÀ࣬ÕâÀïÒÔComponentElementΪÀý
4.6.3 ComponentElement.performRebuild
[-> lib/src/widgets/framework.dart]
void performRebuild()
{
Widget built;
try {
built = build(); //Ö´ÐÐbuild·½·¨
} catch (e, stack) {
built = ErrorWidget.builder (_debugReportException ('building
$this', e, stack));
} finally {
_dirty = false;
}
try {
_child = updateChild (_child, built, slot); //¸üÐÂ×ÓÔªËØ
} catch (e, stack) {
built = ErrorWidget.builder (_debugReportException ('building
$this', e, stack));
_child = updateChild(null, built, slot);
}
} |
4.6.4 RendererBinding.drawFrame
[-> lib/src/rendering/binding.dart]
void drawFrame()
{
pipelineOwner.flushLayout(); //[¼ûС½Ú4.7]
pipelineOwner.flushCompositingBits(); //[¼ûС½Ú4.8]
pipelineOwner.flushPaint(); //[¼ûС½Ú4.9]
renderView.compositeFrame(); //[¼ûС½Ú4.10]
pipelineOwner.flushSemantics(); //[¼ûС½Ú4.11]
} |
RendererBindingµÄinitInstances()¹ý³Ì×¢²áÁËÒ»¸öPersistentµÄÖ¡»Øµ÷·½·¨_handlePersistentFrameCallback()£¬¹ÊhandleDrawFrame()¹ý³Ì»áµ÷Óø÷½·¨¡£pipelineOwner¹ÜÀíäÖȾ¹ÜµÀ£¬ÌṩÁËÒ»¸öÓÃÓÚÇý¶¯äÖȾ¹ÜµÀµÄ½Ó¿Ú£¬²¢´æ´¢ÁËÄÄЩäÖȾ¶ÔÏóÇëÇó·ÃÎÊ״̬£¬ÒªË¢Ð¹ܵÀ£¬ÐèÒª°´Ë³ÐòÔËÐÐÈçÏÂ5¸ö½× ¶Î£º
[flushLayout]£º¸üÐÂÐèÒª¼ÆËãÆä²¼¾ÖµÄäÖȾ¶ÔÏó£¬Ôڴ˽׶μÆËãÿ¸öäÖȾ¶ÔÏóµÄ´óСºÍλÖã¬äÖȾ¶ÔÏó¿ÉÄÜ»áŪÔàÆä»æ»»òÕߺϳÉ״̬£¬Õâ¸ö¹ý³Ì¿ÉÄÜ»¹»áµ÷Óõ½build¹ý³Ì¡£
ºÄʱ¶ÔÓ¦timelineµÄ¡®Layout¡¯¹ý³Ì
[flushCompositingBits]£º¸üоßÓÐÔàºÏ³ÉλµÄÈκÎäÖȾ¶ÔÏó£¬Ôڴ˽׶Îÿ¸öäÖȾ¶ÔÏó¶¼»áÁ˽âÆä×ÓÏîÊÇ·ñÐèÒªºÏ³É¡£ÔÚ»æÖƽ׶ÎʹÓôËÐÅϢѡÔñÈçºÎʵÏֲüôµÈÊÓ¾õЧ¹û¡£Èç¹ûäÖȾ¶ÔÏóÓÐÒ»¸ö×Ô¼ººÏ³ÉµÄ×ÓÏËüÐèҪʹÓò¼¾ÖÐÅÏ¢À´´´½¨²Ã¼ô£¬ÒԱ㽫²Ã¼ôÓ¦ÓÃÓÚÒѺϳɵÄ×ÓÏî
ºÄʱ¶ÔÓ¦timelineµÄ¡®Compositing bits¡¯¹ý³Ì
[flushPaint]£º·ÃÎÊÐèÒª»æÖƵÄÈκÎäÖȾ¶ÔÏó£¬Ôڴ˽׶Σ¬äÖȾ¶ÔÏóÓлú»á½«»æÖÆÃüÁî¼Ç¼µ½[PictureLayer]£¬²¢¹¹½¨ÆäËûºÏ³ÉµÄ[Layer]£»
ºÄʱ¶ÔÓ¦timelineµÄ¡®Paint¡¯¹ý³Ì
[compositeFrame]£º½«Compositing bits·¢Ë͸øGPU£»
ºÄʱ¶ÔÓ¦timelineµÄ¡®Compositing¡¯¹ý³Ì
[flushSemantics]£º±àÒëäÖȾ¶ÔÏóµÄÓïÒ壬²¢½«ÓïÒå·¢Ë͸ø²Ù×÷ϵͳ£»
ºÄʱ¶ÔÓ¦timelineµÄ¡®Semantics¡¯¹ý³Ì
packages/flutter/lib/src/rendering/debug.dart£¬ÕâÀïÃæ¼Ç¼×ŹØÓÚrender¹ý³ÌÏà¹ØµÄµ÷ÊÔ¿ª¹Ø£¬¿ÉÒÔÖðһʵ¼ù¡£
4.7 PipelineOwner.flushLayout
[-> lib/src/rendering/object.dart]
void flushLayout()
{
profile(() {
Timeline.startSync('Layout', arguments: timelineWhitelistArguments);
});
try {
//±éÀúËùÓеÄäÖȾ¶ÔÏó
while (_nodesNeedingLayout.isNotEmpty){
final List<RenderObject> dirtyNodes = _nodesNeedingLayout;
_nodesNeedingLayout = <RenderObject>[];
for (RenderObject node in dirtyNodes..sort ((RenderObject
a, RenderObject b) => a.depth - b.depth)) {
//Èç¹ûäÖȾ¶ÔÏóÐèÒªÖØÐ²¼¾Ö£¬ ÔòÖ´Ðв¼¾Ö²Ù×÷ [¼ûС½Ú4.7.1]
if (node._needsLayout && node.owner ==
this)
node._layoutWithoutResize();
}
}
} finally {
profile(() {
Timeline.finishSync();
});
}
} |
4.7.1 _layoutWithoutResize
[-> lib/src/rendering/object.dart]
void _layoutWithoutResize()
{
try {
performLayout(); //Ö´Ðв¼¾Ö²Ù×÷[]
markNeedsSemanticsUpdate(); //[¼ûС½Ú4.7.2]
} catch (e, stack) {
_debugReportException ('performLayout', e, stack);
}
_needsLayout = false; //Íê³Élayout²Ù×÷
markNeedsPaint(); // [¼ûС½Ú4.7.3]
} |
¸Ã·½·¨Ö÷Òª¹¤×÷£º
performLayout²Ù×÷£º²ÎÊýsizedByParentΪfalseÐèҪͬʱ¸Ä±ääÖȾ¶ÔÏóºÍÖ¸µ¼×ÓÏîµÄ²¼¾Ö£¬ÐÔÄܸüÂý£»
markNeedsSemanticsUpdate£º±ê¼ÇÐèÒª¸üÐÂÓïÒ壻
markNeedsPaint£º±ê¼ÇÐèÒª»æÖÆ£»
SchedulerBinding.scheduleWarmUpFrame
RenderView.performLayout
RenderObject.layout
_RenderLayoutBuilder.performLayout
_LayoutBuilderElement._layout
BuildOwner.buildScope |
4.7.2 markNeedsSemanticsUpdate
[-> lib/src/rendering/object.dart]
void markNeedsSemanticsUpdate()
{
if (!attached || owner. _semanticsOwner == null)
{
_cachedSemanticsConfiguration = null;
return;
}
final bool wasSemanticsBoundary = _semantics
!= null && _cachedSemanticsConfiguration?. isSemanticBoundary
== true;
_cachedSemanticsConfiguration = null;
bool isEffectiveSemanticsBoundary = _semanticsConfiguration. isSemanticBoundary
&& wasSemanticsBoundary;
RenderObject node = this;
while (!isEffectiveSemanticsBoundary &&
node.parent is RenderObject) {
if (node != this && node ._needsSemanticsUpdate)
break;
node._needsSemanticsUpdate = true;
node = node.parent;
isEffectiveSemanticsBoundary = node._semanticsConfiguration. isSemanticBoundary;
if (isEffectiveSemanticsBoundary &&
node._semantics == null) {
return;
}
}
if (node != this && _semantics != null
&& _needsSemanticsUpdate) {
owner._nodesNeedingSemantics. remove(this);
}
if (!node._needsSemanticsUpdate) {
node._needsSemanticsUpdate = true;
if (owner != null) {
//¼Ç¼ÐèÒª¸üÐÂÓïÒåµÄäÖȾ¶ÔÏó
owner._nodesNeedingSemantics.add(node);
owner.requestVisualUpdate();
}
}
} |
4.7.3 markNeedsPaint
[-> lib/src/rendering/object.dart]
void markNeedsPaint()
{
if (_needsPaint)
return;
_needsPaint = true;
if (isRepaintBoundary) {
if (owner != null) {
//¼Ç¼ÐèÒªÖØÐ»æÖƵÄäÖȾ¶ÔÏó
owner._nodesNeedingPaint.add(this);
owner.requestVisualUpdate();
}
} else if (parent is RenderObject){
final RenderObject parent = this.parent;
parent.markNeedsPaint();
} else {
if (owner != null)
owner.requestVisualUpdate();
}
} |
4.8 PipelineOwner.flushCompositingBits
[-> lib/src/rendering/object.dart]
void flushCompositingBits()
{
profile(() { Timeline.startSync ('Compositing bits');
});
_nodesNeedingCompositingBitsUpdate. sort((RenderObject
a, RenderObject b) => a.depth - b.depth);
for (RenderObject node in _nodesNeedingCompositingBitsUpdate)
{
//¸ù¾ÝÐèÒªÀ´¾ö¶¨ÊÇ·ñ¸üÐÂλºÏ³É
if (node._needsCompositingBitsUpdate &&
node.owner == this)
node._updateCompositingBits(); // [¼ûС½Ú4.8.1]
}
_nodesNeedingCompositingBitsUpdate.clear(); //Çå¿ÕÐèҪλºÏ³ÉµÄäÖȾ¶ÔÏó
profile(() { Timeline.finishSync(); });
} |
4.8.1 _updateCompositingBits
[-> lib/src/rendering/object.dart]
void _updateCompositingBits()
{
if (!_needsCompositingBitsUpdate)
return;
final bool oldNeedsCompositing = _needsCompositing;
_needsCompositing = false;
visitChildren((RenderObject child) {
//±éÀúËùÓÐ×ÓÏîÀ´¸üÐÂλºÏ³É
child._updateCompositingBits();
if (child.needsCompositing)
_needsCompositing = true;
});
if (isRepaintBoundary || alwaysNeedsCompositing)
_needsCompositing = true;
if (oldNeedsCompositing != _needsCompositing)
markNeedsPaint();
_needsCompositingBitsUpdate = false;
} |
4.9 PipelineOwner.flushPaint
[-> lib/src/rendering/object.dart]
void flushPaint()
{
profile(() { Timeline.startSync ('Paint', arguments:
timelineWhitelistArguments); });
try {
final List<RenderObject> dirtyNodes = _nodesNeedingPaint;
_nodesNeedingPaint = <RenderObject>[];
//ÅÅÐòÔà½Úµã£¬Éî¶È×î´óµÄ½ÚµãÅŵÚһλ
for (RenderObject node in dirtyNodes.. sort((RenderObject
a, RenderObject b) => b.depth - a.depth)) {
if (node._needsPaint && node.owner ==
this) {
//´Ë½ÚµãÊÇ·ñÁ¬½Óµ½Ê÷ÖУ¬ Èç¹ûÁ¬½ÓÔòÖØ»æ£¬·ñÔòÌø¹ý
if (node._layer.attached) {
PaintingContext.repaintCompositedChild (node);
//[С½Ú4.9.1]
} else {
node._skippedPaintingOnLayer();
}
}
}
} finally {
profile(() { Timeline.finishSync(); });
}
} |
4.9.1 repaintCompositedChild
[-> lib/src/rendering/object.dart]
static void
repaintCompositedChild (RenderObject child,
{ bool debugAlsoPaintedParent = false }){
_repaintCompositedChild(
child,
debugAlsoPaintedParent: debugAlsoPaintedParent,
);
}
static void _repaintCompositedChild(
RenderObject child, {
bool debugAlsoPaintedParent = false,
PaintingContext childContext,
}) {
if (child._layer == null) {
child._layer = OffsetLayer();
} else {
child._layer.removeAllChildren();
}
childContext ??= PaintingContext (child._layer,
child.paintBounds);
child._paintWithContext (childContext, Offset.zero);
childContext.stopRecordingIfNeeded();
} |
4.10 RenderView.compositeFrame
[-> lib/src/rendering/view.dart]
void compositeFrame()
{
Timeline.startSync ('Compositing', arguments: timelineWhitelistArguments);
try {
//´´½¨SceneBuilder [¼ûС½Ú4.10.1]
final ui.SceneBuilder builder = ui.SceneBuilder();
//´´½¨Scene [¼ûС½Ú4.10.2]
final ui.Scene scene = layer. buildScene(builder);
if (automaticSystemUiAdjustment)
_updateSystemChrome();
ui.window.render(scene); // [¼ûС½Ú4.10.3]
scene.dispose();
} finally {
Timeline.finishSync();
}
} |
¸Ã·½·¨Ö÷Òª¹¤×÷£º
·Ö±ð´´½¨Flutter¿ò¼Ü(dart)ºÍÒýÇæ²ã(C++)µÄÁ½¸öSceneBuilder£»
·Ö±ð´´½¨Flutter¿ò¼Ü(dart)ºÍÒýÇæ²ã(C++)µÄÁ½¸öScene£»
Ö´ÐÐrender()½«layerÊ÷·¢Ë͸øGPUỊ̈߳»
4.10.1 SceneBuilder³õʼ»¯
[-> lib/ui/compositing.dart]
class SceneBuilder
extends NativeFieldWrapperClass2 {
@pragma('vm:entry-point')
SceneBuilder() { _constructor(); }
void _constructor() native 'SceneBuilder_constructor';
...
} |
SceneBuilder_constructorÕâÊÇnative·½·¨£¬×îÖÕµ÷Óõ½ÒýÇæÖеÄlib/ui/compositing/scene_builder.hÖеÄSceneBuilder::create()·½·¨£¬ ´´½¨C++µÄSceneBuilder¶ÔÏó¡£
4.10.2 OffsetLayer.buildScene
[-> lib/src/rendering/layer.dart]
ui.Scene buildScene (ui.SceneBuilder
builder) {
updateSubtreeNeedsAddToScene(); //±éÀúlayerÊ÷£¬½«ÐèÒª×ÓÊ÷¼ÓÈëµ½scene
addToScene(builder); //½«layerÌí¼Óµ½SceneBuilder
return builder.build(); //µ÷ÓÃC++²ãµÄbuildÀ´¹¹½¨Scene¶ÔÏó¡£
} |
±éÀúlayerÊ÷£¬½«ÐèÒª¸üеÄÈ«²¿¶¼¼ÓÈëµ½SceneBuilder¡£ÔÙµ÷ÓÃbuild()£¬Í¬ÑùÒ²ÊÇnative·½·¨£¬Ö´ÐÐSceneBuilder::build()À´¹¹½¨Scene¶ÔÏó¡£
4.10.3 Window::Render
[-> flutter/lib/ui/window/window.cc]
void Render(Dart_NativeArguments
args){
Dart_Handle exception = nullptr;
Scene* scene = tonic::DartConverter <Scene*> ::FromArguments(args,
1, exception);
if (exception) {
Dart_ThrowException(exception);
return;
}
UIDartState::Current()->window() ->client()->Render(scene);
// [4.10.4]
} |
ui.window.render()λÓÚwindow.dartÎļþ£¬ÕâÊÇÒ»¸önative·½·¨£¬»áµ÷Óõ½window.ccµÄRender()·½·¨¡£
4.10.4 RuntimeController::Render
[-> flutter/runtime/runtime_controller.cc]
void RuntimeController ::Render(Scene*
scene) {
//´ÓsceneÖÐÈ¡³ölayerÊ÷ [¼ûС½Ú4.10.5]
client_.Render (scene->takeLayerTree());
} |
4.10.5 Engine::Render
[-> flutter/shell/common/engine.cc]
void Engine::Render
(std::unique_ptr<flow:: LayerTree>
layer_tree) {
if (!layer_tree)
return;
SkISize frame_size = SkISize::Make (viewport_metrics_.physical_width,
viewport_metrics_.physical_height);
if (frame_size.isEmpty())
return;
layer_tree->set_frame_size(frame_size);
animator_->Render(std::move(layer_tree));
// [4.10.6]
} |
4.10.6 Animator::Render
[-> flutter/shell/common/animator.cc]
void Animator::Render
(std::unique_ptr<flow::LayerTree>
layer_tree) {
if (dimension_change_pending_ &&
layer_tree->frame_size() != last_layer_tree_size_)
{
dimension_change_pending_ = false;
}
last_layer_tree_size_ = layer_tree->frame_size();
if (layer_tree) {
layer_tree->set_construction_time (fml::TimePoint::Now()
-
last_begin_frame_time_);
}
//Ìá½»´ý´¦ÀíµÄcontinuation£¬ ±¾´ÎPipelineProduceÍê³É //[¼ûС½Ú4.10.7]
producer_continuation_.Complete (std::move(layer_tree));
delegate_.OnAnimatorDraw (layer_tree_pipeline_);
//[¼ûС½Ú4.10.8]
} |
UIÏ̵߳ĺÄʱ´ÓdoFrame(frameTimeNanos)ÖеÄframeTimeNanosΪÆðµã£¬ÒÔAnimator::Render()·½·¨½áÊøÎªÖյ㣬 ²¢½«½á¹û±£´æµ½LayerTreeµÄ³ÉÔ±±äÁ¿construction_time_£¬Õâ±ãÊÇUIÏ̵߳ĺÄʱʱ³¤¡£
4.10.7 ProducerContinuation.Complete
[-> flutter/synchronization/pipeline.h]
class ProducerContinuation
{
void Complete(ResourcePtr resource){
if (continuation_) {
continuation_(std::move(resource), trace_id_);
continuation_ = nullptr;
TRACE_EVENT_ASYNC_END0 ("flutter", "PipelineProduce",
trace_id_);
TRACE_FLOW_STEP("flutter", "PipelineItem",
trace_id_);
}
} |
4.10.8 Shell::OnAnimatorDraw
[-> flutter/shell/common/shell.cc]
void Shell::OnAnimatorDraw(
fml::RefPtr<flutter::Pipeline <flow::LayerTree>>
pipeline) {
//ÏòGPUÏß³ÌÌá½»»æÖÆÈÎÎñ
task_runners_.GetGPUTaskRunner()->PostTask(
[rasterizer = rasterizer_->GetWeakPtr(),
pipeline = std::move(pipeline)]() {
if (rasterizer) {
//ÓÉGPUÏß³ÌÀ´¸ºÔðÕ¤¸ñ»¯²Ù×÷
rasterizer->Draw(pipeline);
}
});
} |
Õâ¸ö·½·¨Ö÷ÒªÊÇÏòGPUÏß³ÌÌá½»»æÖÆÈÎÎñ¡£
4.11 PipelineOwner.flushSemantics
[-> lib/src/rendering/view.dart]
void flushSemantics()
{
if (_semanticsOwner == null)
return;
profile(() { Timeline.startSync ('Semantics');
});
try {
final List<RenderObject> nodesToProcess
= _nodesNeedingSemantics.toList()
..sort((RenderObject a, RenderObject b) =>
a.depth - b.depth);
_nodesNeedingSemantics.clear();
//±éÀú_nodesNeedingSemantics£¬ ¸üÐÂÐèÒª¸üÐÂÓïÒåµÄäÖȾ¶ÔÏó
for (RenderObject node in nodesToProcess) {
if (node._needsSemanticsUpdate && node.owner
== this)
node._updateSemantics(); // [¼ûС½Ú4.11.1]
}
_semanticsOwner.sendSemanticsUpdate(); // ·¢ËÍÓïÒå¸üÐÂ[¼ûС½Ú4.11.2]
} finally {
profile(() { Timeline.finishSync(); });
}
} |
4.11.1 _updateSemantics
[-> lib/src/rendering/object.dart]
void _updateSemantics()
{
if (_needsLayout) {
//´Ë×ÓÊ÷ÖÐûÓÐ×ã¹»µÄÐÅÏ¢À´¼ÆËãÓïÒ壬 ×ÓÊ÷¿ÉÄܱ»ÊÓͼ´°¿Ú±£³Ö»î×ŵ«Ã»Óв¼¾Ö
return;
}
final _SemanticsFragment fragment = _getSemanticsForParent(
mergeIntoParent: _semantics?. parent?.isPartOfNodeMerging
?? false,
);
final _InterestingSemanticsFragment interestingFragment
= fragment;
final SemanticsNode node = interestingFragment.compileChildren(
parentSemanticsClipRect: _semantics?.parentSemanticsClipRect,
parentPaintClipRect: _semantics?. parentPaintClipRect,
).single;
} |
4.11.2 sendSemanticsUpdate
[-> lib/src/semantics/semantics.dart]
void sendSemanticsUpdate()
{
if (_dirtyNodes.isEmpty)
return;
final Set<int> customSemanticsActionIds
= Set<int>();
final List<SemanticsNode> visitedNodes =
<SemanticsNode>[];
while (_dirtyNodes.isNotEmpty) {
final List<SemanticsNode> localDirtyNodes
= _dirtyNodes. where((SemanticsNode node) =>
!_detachedNodes.contains(node)).toList();
_dirtyNodes.clear();
_detachedNodes.clear();
localDirtyNodes.sort ((SemanticsNode a, SemanticsNode
b) => a.depth - b.depth);
visitedNodes.addAll(localDirtyNodes);
for (SemanticsNode node in localDirtyNodes) {
if (node.isPartOfNodeMerging) {
//Èç¹ûºÏ²¢µ½¸¸½Úµã£¬È·±£¸¸½ÚµãÒѱ»Ìí¼Óµ½ÔàÁбí
if (node.parent != null && node.parent.isPartOfNodeMerging)
node.parent._markDirty(); //½«½ÚµãÌí¼Óµ½ÔàÁбí
}
}
}
visitedNodes.sort((SemanticsNode a, SemanticsNode
b) => a.depth - b.depth);
final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
for (SemanticsNode node in visitedNodes) {
if (node._dirty && node.attached)
node._addToUpdate(builder, customSemanticsActionIds);
}
_dirtyNodes.clear();
for (int actionId in customSemanticsActionIds)
{
final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId);
builder.updateCustomAction(id: actionId, label:
action.label, hint: action.hint, overrideId: action.action?.index
?? -1);
}
ui.window.updateSemantics(builder.build()); //
[¼ûС½Ú4.11.3]
notifyListeners(); //֪ͨÒÑ×¢²áµÄ¼àÌýÆ÷
} |
¿ÉÒÔ¿´¿´¼àÌýÆ÷µÄÊý¾Ý£¬ÊÇ·ñÓ°ÏìÐÔÄÜ¡£
updateSemanticsÕâÊÇwindow.dartÖеÄÒ»¸önative·½·¨£¬µ÷Óõ½ÈçÏ·½·¨¡£
4.11.3 Window::updateSemantics
[-> flutter/lib/ui/window/window.cc]
void UpdateSemantics (Dart_NativeArguments
args) {
Dart_Handle exception = nullptr;
SemanticsUpdate* update =
tonic::DartConverter<SemanticsUpdate*> ::FromArguments(args,
1, exception);
if (exception) {
Dart_ThrowException(exception);
return;
}
UIDartState::Current()->window() ->client()->UpdateSemantics(update);
// [¼ûС½Ú4.11.4]
} |
4.11.4 RuntimeController::UpdateSemantics
[-> flutter/runtime/runtime_controller.cc]
void RuntimeController::
UpdateSemantics(SemanticsUpdate* update){
if (window_data_.semantics_enabled) {
client_.UpdateSemantics (update->takeNodes(),
update->takeActions()); // [¼ûС½Ú4.11.5]
}
} |
4.11.5 Engine::UpdateSemantics
[-> flutter/shell/common/engine.cc]
void Engine::UpdateSemantics (blink::SemanticsNodeUpdates
update,
blink::CustomAccessibility ActionUpdates actions)
{
delegate_.OnEngineUpdateSemantics (std::move(update),
std::move(actions)); // [¼ûС½Ú4.11.6]
} |
4.11.6 Shell::OnAnimatorDraw
[-> flutter/shell/common/shell.cc]
void Shell::OnEngineUpdateSemantics(
blink::SemanticsNodeUpdates update,
blink::CustomAccessibilityActionUpdates actions)
{
task_runners_.GetPlatformTaskRunner() ->PostTask(
[view = platform_view_->GetWeakPtr(), update
= std::move(update),
actions = std::move(actions)] {
if (view) {
view->UpdateSemantics(std::move(update),
std::move(actions));
}
});
} |
Õâ¸ö·½·¨Ö÷ÒªÊÇÏòƽ̨Ïß³ÌÌá½»SemanticÈÎÎñ¡£
Ôٻص½Ð¡½Ú4.6£¬¿ÉÖª½ÓÏÂÀ´ÔÙÖ´ÐÐfinalizeTree()²Ù×÷£»
4.12 BuildOwner.finalizeTree
[-> lib/src/widgets/framework.dart]
void finalizeTree()
{
Timeline.startSync('Finalize tree', arguments:
timelineWhitelistArguments);
try {
lockState(() {
//±éÀúËùÓеÄElement£¬Ö´ÐÐunmount()¶¯×÷£¬ ÇÒÈ¡ÏûGlobalKeysµÄ×¢²á
_inactiveElements._unmountAll();
});
} catch (e, stack) {
_debugReportException('while finalizing the widget
tree', e, stack);
} finally {
Timeline.finishSync();
}
} |
±éÀúËùÓеÄElement£¬Ö´ÐÐÏàÓ¦¾ßÌåElement×ÓÀàµÄunmount()²Ù×÷£¬ÏÂÃæÒÔ³£¼ûµÄStatefulElementΪÀýÀ´ËµÃ÷¡£
4.12.1 StatefulElement.unmount
[-> lib/src/widgets/framework.dart]
void unmount()
{
super.unmount(); //[¼ûС½Ú4.12.2]
_state.dispose(); //Ö´ÐÐStateµÄdispose()·½·¨
_state._element = null;
_state = null;
} |
4.12.2 Element.unmount
[-> lib/src/widgets/framework.dart]
void unmount()
{
if (widget.key is GlobalKey) {
final GlobalKey key = widget.key;
key._unregister(this); //È¡ÏûGlobalKeyµÄ×¢²á
}
} |
¸½Â¼
±¾ÎÄÉæ¼°µ½Ïà¹ØÔ´ÂëÎļþ
flutter/shell/common/
- vsync_waiter.cc
- engine.cc
- animator.cc
- shell.cc
- rasterizer.cc
flutter/shell/platform/android/
- vsync_waiter_android.cc
- platform_view_android_jni.cc
- library_loader.cc
- io/flutter/view/VsyncWaiter.java
flutter/runtime/runtime_controller.cc
flutter/synchronization/pipeline.h
flutter/fml/message_loop_impl.cc
flutter/lib/ui/window/window.cc
flutter/lib/ui/window.dart
flutter/lib/ui/hooks.dart
lib/src/widgets/framework.dart
lib/src/widgets/binding.dart
lib/src/scheduler/binding.dart
lib/src/semantics/semantics.dart
lib/src/rendering/
- binding.dart
- object.dart
- view.dart |
|