Android Project Butter 黄油计划 深入剖析android新特性 笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012654756/article/details/88981304

9.3 Project Butter 黄油计划

Android4.1 Jelly Bean引入了ProjectButter

先说背景,再讲解为什么ProjectButter能提升流畅性

用户感受到流畅性在于自己的输入事件与返回结果之间的延迟,若事件延迟短,则跟手,流畅,

这只是用户的角度看问题,系统中,从事件输入到最终结果响应,过程非常复杂:

(Activity)Event->SetPropertyValue->Invalidate->Measure&Layout->PrepareDraw ->

(SF)DequeueBuffer

(Activity)UpdateDisplayList->DrwaDisplayList->SwapBuffers ->

(SF)EnqueueBuffer,

(SF)CompositeWindows->PostBuffer

Acitivity进程内,主要是接收到事件后进程控件属性的更新,然后根据新的属性重新测量和布局,

布局完成后从SF获取一个缓冲,然后将新空间树的结构更新到这个buffer中,最后交给SF合成和显示。

下节讲SF,现在只要知道,SF是系统中专门负责绘制UI的系统服务就可以。

9.3.1 FPS

FramesPerSecond,FrameRate,Hz,

平稳的60FPS就算是流畅,但ipad pro 2017的refreshRate已经达到120Hz。

平稳是指,不可以有卡帧、掉帧的情况

1000ms / 60 = 16.67ms

每一帧必须保证在这个时间内处理完

Jank的产生:

VSync Vsync

Disp 0 | 1 | 1 | 2 | 3 |

GPU 1 | |2 |3 4 |

CPU 1 | 2 | 3 | 4 |

CPU负责测试和布局的计算

GPU负责图像的合成

Display是最终的显示模块,代表用户看到的结果

所有界面的刷新都要经历这三个模块的流水线作业,

流程:

开始没画面,disp0,

CPU产出1st帧的内容,然后交给GPU,接着在Disp上显示

假设CPU忙其他事,没能连续产生2nd帧内容,则导致一系列延迟,第一帧画面停留了2个VSync

ProjectBuffer引入两个机制提升流程性:

1,VSYNC机制

2,Triple Buffer

9.3.2 VSYNC

Vertical Synchronization,垂直同步

用来防止Tearing撕裂,

视频、游戏由一幅幅图像组成,称为帧

每帧有很多像素点

显示器显示每一帧画面时,需要一行一行刷新到屏幕,(逐行扫描)

显示器通过GPU的Buffer拿到要显示的每一帧数据,

假设显示器将当前帧内容刷新到一半时,来了新的一帧数据,两帧内容一起显示,Tearing。

VSYNC的目的就是避免这种情况,它告知GPU等到屏幕内容刷新完再加载下一帧画面内容,避免了Tearing

Android之前的版本已经使用VSYNC避免Tearing,jellyBean对VSYNC进行了加强,

所有显示组件都以VSYNC信号为基准来保证步调一致,

CPU收到VSYNC,产生帧数据

交给GPU处理

display出来

9.3.3 Choreographer与VSYNC

编舞者

Choreographer是伴随ProjectButter新增的API,

负责统一动画、输入、绘画的时机。

负责接受VSYNC信号然后安排下一帧所需的相关工作

开发者可以通过Choreographer.postFrameCallback(FrameCallback c)API来提交一个回调,这个回调会在下一帧时刻执行。

每个Looper线程都有自己的Choreographer,

其他线程可以发布回调,以在Choreographer运行,但他们将在Choreographer所属的Looper上运行。

这个有结构图,分java层,C++层,

图的结构说明:

Choreographer提供FrameCallback,来让开发者实现帧渲染监听的回调,Choreographer负责调度这些回调,

<<interface>> <---------- android.view.Choreographer

FrameCallback +getInstance():Choreographer

+doFrame() : void +scheduleVsyncLocked() : void

+doFrame() : void

+doCallbacks() : void

//依赖关系,Choreographer只有传入了FrameCallback才有用

FrameDisplayEventReceiver是DisplayEventReceiver的子类;

android.view.DisplayEventReceiver <------ FrameDisplayEventReceiver

+nativeScheduleVsync() +scheduleVsync()

+scheduleVsync()

+onVsync()

+onHotplug()

-dispatchVsync()

-dispatchHotplug()

//+是public,-是private

FrameDisplayEventReceiver与android.view.Choreographer是聚合关系,强调整体包含部分,

Choreographer包含FrameDisplayEventReciver

以上是JAVA层

DisplayEventReceiver通过JNI与native端的NativeDsiplayEventReceiver连通,

NativeDisplayEventReceiver是DisplayEventDispatcher的子类;

DisplayEventDispatcher <------- NativeDsiaplyEventReceiver

-handleEvent() +scheduleVsync

+processPrendingEvents() -dispatchVsync()

-dispatchVsync() -dispatchHotplug()

-dispatchHotplug()

+scheduleVsync()

DisplayEventDispatcher包含了一个DisplayeventReceiver对象

DisplayEventReceiver

+requestNextVsnc()

+getEvents()

+getFd()

DisplayEventReceiver包含IDisplayEventConnection与BitTube

IDisplayEventConnection

+getDataChannel() : BitTube

+setVsyncRate(count:int) : void

+requestNextVsync() : void

BitTube

+recvObjects()

+sendObjects()

+getFd():int

DisplayEventReceiver可以获取到显示时间的接收器,包含了VSYNC事件,

所以,VSYNC事件传递流程:

BitTube => DisplayEventReceiver => DisplayEventDispatcher =>

NativeDisplayEventRevicer => DisplayEventReceiver =>

FrameDisplayEventReceiver => Choreographer

VSYNC事件的接收

上图还有IDisplayEventConnection和BitTube类没介绍,他们与接收VSYNC事件密切相关,详细看下

DisplayEventReceiver包含了IDisplayEventConnction与BitTube两个类型的指针:

//DisplayEventReceiver.h

sp<IDisplayEventConnection> mEventConnection;

std::unique_ptr<gui :: BitTube> mDataChannel;

并在DisplayEventReceiver构造函数中对他们初始化,

//DisplayEventReceiver.cpp

DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource){

sp<ISurfaceComposer> sf(ComposerService::getComposerService());

if(sf != NULL) {

mEventConnection = sf -> createDisplayEventConnnection(vsyncSource);

if(mEventConnnection != NULL){

mDataChannel = std::make_unique<gui::BitTube>();

mEventConnection->stealReceiveChannel(mDataChannel.get());

}

}

}

ISurfaceComposer在下一节讲,这里只要知道,通过sf->createDisplayEventConnection变获取到了SurfaceFlinger的连接就可以了。

Tube是通道,BitTube就是传输bit数据的通道,

VSYNC事件就是通过这个通道从SF传递到位于AP进程的DisplayEventReceiver中的,

数据传递的方法是通过BitTube的sendObject和recvObjects两个静态方法:

......

9.3.4 TripleBuffer

猜你喜欢

转载自blog.csdn.net/u012654756/article/details/88981304
今日推荐