您的位置:首页 > 移动开发 > Android开发

Android SurfaceFlinger VSync流程分析

2017-09-08 17:33 627 查看
一,VSync机制的作用及VSync在SurfaceFlinger服务中的位置:

VSync信号通常都来自硬件控制器,在Android中也可以采用软件模拟;

VSync的作用,如下图(以双缓冲为例,为了提高流畅性有时也采用triple三缓冲):LCD控制器在读取每一帧数据的开始都会产生一个VSync信号(垂直同步信号或帧同步信号);



LCD的频率是60Hz,显示每一帧的间隔是16ms,所以每一个VSync信号的时间间隔是16ms,上图中的A和B都是帧缓冲区framebuffer,每一个framebuffer由CPU和GPU共同完成;

在硬件芯片中,晶振产生的时钟脉冲驱动整个硬件电路连续运行;在Surfaceflinger中,VSync信号就好像晶振电路产生的时钟信号一样驱动Surfaceflinger中所有模块和谐的运行,如下图;



二,VSync流程及重要代码:

1,整体流程概览,如下图:



重点介绍如下过程:

2,App绘制请求发送流程(过程1(App)):

App进程调用invalidate或postinvalidate方法发送绘制请求;



invalidate方法最终会调用的BpDisplayEventConnection的requestNextVsync方法,在该方法中通过Binder IPC访问服务端的requestNextSync方法;

BpDisplayEventConnection方法的实例化过程如下:

1>,在ViewRootImpl的构造函数中会实例化Choreographer对象,

public ViewRootImpl(Context context, Display display) {
. . . . .
mChoreographer = Choreographer.getInstance();
}


2>,在mChoreographer 的构造函数中实例化FrameDisplayEventReceiver对象:

private Choreographer(Looper looper) {
. . . . . .
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
}


3>,在FrameDisplayEventReceiver的父类构造函数中会调用到,android_view_DisplayEventReceiver.cpp中的nativeInit方法,

4>,在nativeInit方法中有如下过程:

static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject messageQueueObj) {
. . . . . .
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
receiverWeak, messageQueue);
status_t status = receiver->initialize();
. . . . . .


1),创建NativeDisplayEventReceiver类类型指针,


在NativeDisplayEventReceiver的构造函数中会调用DisplayEventReceiver类的无参构造函数实例化成员mReceiver;

DisplayEventReceiver::DisplayEventReceiver() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection();
if (mEventConnection != NULL) {
mDataChannel = mEventConnection->getDataChannel();
}
}
}


在这段代码中获取Surfaceflinger服务的代理对象,然后通过Binder IPC创建BpDisplayEventConnection对象,然后mEventConnection->getDataChannel()方法再次通过Binder IPC创建 BitTube对象mDataChannel ,在Binder IPC创建mDataChannel 过程中会从服务端EventThread::Connection::Connection中(在EventThread类中定义)接收一个socketpair创建的FIFO文件描述符;

EventThread::Connection::Connection创建描述符的代码:

Connection构造函数调用BitTube的无参构造函数,在BitTube的构造函数中调用init函数;

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// sine we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
mReceiveFd = sockets[0];
mSendFd = sockets[1];
} else {
mReceiveFd = -errno;
ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
}
}


2)调用到NativeDisplayEventReceiver类的父类DisplayEventDispatcher中的initialize()方法,
将BpDisplayEventConnection对象获取到的mDataChannel (BitTube类型)中的文件描述符添加到UI主线程Looper的epoll中,
当文件描述符中被写入数据时,该epoll_wait会被唤醒;


3,Vsync信号驱动App进程绘制流程(过程4(App)):

4,Surfaceflinger图册合成请求发送流程(过程1(sf)):

5,Vsync信号驱动Surfaceflinger合成流程(过程4(sf)):
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android lcd