vsync信号

上个小节说明了HWC模块的加载等操作,并且也说明了HWC模块主要用于产生vsync信号,现在的问题是, vsync信号是如何产生的呢? 又是如何传输到SurfaceFlinger 中,处理的呢?在上面的论述中,HWComposer 的构造方法在加载完FB模块打开设备文件以及加载HWC模块之后,会注册vsync信号,

mHwc->registerProcs(mHwc, &mCBContext->procs);

HWComposer_hwc1.h中的mCBContext变量申明如下,

cb_context*                     mCBContext;

是cb_context 的结构体,该结构体定义如下,

HWComposer_hwc1.cpp中的cb_context结构体定义如下,

struct HWComposer::cb_context {
    struct callbacks : public hwc_procs_t {
        // these are here to facilitate the transition when adding
        // new callbacks (an implementation can check for NULL before
        // calling a new callback).
        void (*zero[4])(void);
    };
    callbacks procs;
    HWComposer* hwc;
};

里面有2个变量,一个指向HWComposer对象,1个结构体callbacks,这个结构体会传给HAL层的HWC模块,这样,当有vsync信号时,就可以通过这个结构体进行回调。callbacks由继承自 hwc_procs_t, hwcomposer.h中的 hwc_procs_t的定义如下,

typedef struct hwc_procs {  
void (*invalidate)(const struct hwc_procs* procs);  
void (*vsync)(const struct hwc_procs* procs, int disp, int64_t timestamp);  
void (*hotplug)(const struct hwc_procs* procs, int disp, int connected);  
} hwc_procs_t;  

invalidate方法:会触发屏幕刷新,在invalidate被调用不久会调用prepare和set,但是不保证调用了invalidate屏幕就一定会刷新,比如之前屏幕已经刷新过了,就不会在刷新。 

vsync方法:是分析这部分代码的目的,在收到一个vsync事件,并且HWC_EVENT_VSYNC是enabled的,这个vsync方法会被hwcomposer hal模块调用,其中的参数disp标示这个vsync事件是属于那个显示设备。 

hotplug方法:在一个显示设备连接或断开时会调用hotplug,主显示设备一直都是连接的,这个方法不会被调用,主要是针对可热插拔的设备。 

 对应的HWC的hwc_registerProcs方法逻辑如下,

hwc_context_t* ctx = (hwc_context_t*)(dev);
•••
ctx->proc = procs; //vsync回调HWComposer的vsync函数。
// Now that we have the functions needed, kick off
// the uevent & vsync threads
init_uevent_thread(ctx);
init_vsync_thread(ctx);

也就是说,HWC模块调用proc中的方法时,实际上是回调hwc_procs 结构体(mCBContext)中对应的方法。当有回调函数注册时,会开启uevent,vsync两个线程。uevent线程跟屏幕invalidate有关, vsync和vsync信号相关,主要分析vsync线程。HWC模块的hwc_vsync.cpp的init_vsync_thread方法调用流程图如下,

vsync信号_第1张图片

init_vsync_thread方法如下,

int ret;
pthread_t vsync_thread;
ALOGI("Initializing VSYNC Thread");
ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);

创建vsync线程,入口方法为vsync_loop。该方法逻辑如下,

1,当不是模拟vsync的情况,当有多个显示设备时,对每个显示设备都要执行回调,发出通知,

do {
   int err = poll(*pfd, (int)(num_displays * num_events), -1);
•••

在该线程运行过程中通过ioctl系统调用进入到fb驱动等待VSync中断,如果VSync中断到来,则ioctl函数从驱动中返回。

2,使用模拟vsync的情况,通常是明确通过属性设置了或在开机时vsync时间戳节点还没打开,这时候会使用模拟vsync,模拟vsync指发给主显示设备。

do {
   usleep(16666);
   uint64_t timestamp = systemTime();
   ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY, timestamp);
} while (true);

vsync信号间隔16.66ms发送一次,也就是说1秒钟发送60次vsync信号。

回调mCBContext中的vsync方法,在HWComposer_hwc1.cpp中的HWComposer构造方法中,

mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
mCBContext->procs.vsync = &hook_vsync;

mCBContext中的vsync方法 指向的是HWComposer的hook_vsync方法,如下,

cb_context* ctx = reinterpret_cast(
            const_cast(procs));
ctx->hwc->vsync(disp, timestamp);

绕了一圈,最后还是调用HWComposer的vsync方法,调用流程图如下,

HWComposer的vsync方法如下,

char tag[16];
snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);

mEventHandler.onVSyncReceived(this, disp, timestamp);

mEventHandler是什么对象呢? 在SurfaceFlinger_hwc1.cpp 的SurfaceFlinger的init方法构造HWComposer对象时,

mHwc.reset(new HWComposer(this,
    *static_cast(this)));
mHwc->registerCallback(this, mComposerSequenceId);

传入的是SurfaceFlinger对象,因此mEventHandler 是SurfaceFlinger对象。

HWComposer直接通过mEventHandler把vsync信号传到surfaceflinger。onVSyncReceived方法如下,

bool needsHwVsync = false;
{ // Scope for the lock
   Mutex::Autolock _l(mHWVsyncLock);
   if (type == 0 && mPrimaryHWVsyncEnabled) {
       needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
   }
}
if (needsHwVsync) {
   enableHardwareVsync();
} else {
   disableHardwareVsync(false);
}

逻辑很简单,首先调用DispSync的addResyncSample方法判断是否需要Vsync信号,如果需要就调用enableHardwareVsync方法进行处理,否则调用disableHardwareVsync方法进行处理。

你可能感兴趣的:(---【android,8.1,surface机制】)