Android 显示系统:Vsync机制
一、Vsync简介:
屏幕的刷新过程是每一行从左到右(行刷新,水平刷新,Horizontal Scanning),从上到下(屏幕刷新,垂直刷新,Vertical Scanning)。当整个屏幕刷新完毕,即一个垂直刷新周期完成,会有短暂的空白期,此时发出 VSync 信号。所以,VSync 中的 V 指的是垂直刷新中的垂直-Vertical。
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,VSync是Vertical Synchronization(垂直同步)的缩写,是一种在PC上很早就广泛使用的技术,可以简单的把它认为是一种定时中断。而在Android 4.1(JB)中已经开始引入VSync机制,用来同步渲染,让AppUI和SurfaceFlinger可以按硬件产生的VSync节奏进行工作。
二、黄油计划:三个方法改进显示系统
1.Vsync同步:
可见vsync信号没有提醒CPU/GPU工作的情况下,第二次vsync到来需要显示内容时,CPU和GPU还没有来得及准备好下一帧的数据,所以只能接着显示上一帧的数据,产生Jank!
CPU/GPU接收vsync信号提前准备下一帧要显示的内容,所以能够及时准备好每一帧的数据,保证画面的流程。
2.多级缓冲:
除了Vsync的机制,Android还使用了多级缓冲的手段以优化UI流程度,例如双缓冲(A+B),在显示buffer A的数据时,CPU/GPU就开始在buffer B中准备下一帧数据:
但是不能保证每一帧CPU、GPU都运行状态良好,可能由于资源抢占等性能问题导致某一帧GPU掉链子,vsync信号到来时buffer B的数据还没准备好,而此时Display又在显示buffer A的数据,导致后面CPU/GPU没有新的buffer着手准备数据,空白时间无事可做,后面Jank频出:
因此用三级缓冲来提高系统对性能波动的容忍度:
虽然GPU在准备buffer B的数据耗时过长,第二帧Jank,但是新增1个buffer可以减少CPU和GPU在vsync同步间的空白间隙,此时CPU/GPU能够利用buffer C继续工作,所以后面就不会再产生Jank了,当然具体使用多少个buffer要根据实际硬件性能情况调整,最终目的就是解决Display的Jank产生。
3.Vsync虚拟化(Vsync App + Vsync SurfaceFlinger):
虽然vsync使得CPU/GPU/Display同步了,但App UI和SurfaceFlinger的工作显然是一个流水线的模型。即对于一帧内容,先等App UI画完了,SurfaceFlinger再出场对其进行合并渲染后放入framebuffer,最后整到屏幕上。而现有的VSync模型是让大家一起开始干活,这样对于同一帧内容,第一个VSync信号时App UI的数据开始准备,第二个VSync信号时SurfaceFlinger工作,第三个VSync信号时用户看到Display内容,这样就两个VSync period(每个16ms)过去了,影响用户体验。
解决思路:SurfaceFlinger在App UI准备好数据后及时开工做合成。
Android 4.4(KitKat)引入了VSync的虚拟化,即把硬件的VSync信号先同步到一个本地VSync模型中,再从中一分为二,引出两条VSync时间与之有固定偏移的线程。示意图如下:
这样,大家工作既保持一定的节拍,又可以相互错开,一前一后保持着流水节奏。
注意其中两个Phase offset参数(即VSYNC_EVENT_PHASE_OFFSET_NS和SF_VSYNC_EVENT_PHASE_OFFSET_NS)是可调的。
处理流程:
类型DispSync表示了一个基于硬件VSync信号的同步模型,它会根据从HWComposer来的硬件VSync信号的采样来进行同步。其它两个EventThread分别用了两个不同的虚拟VSync信号源(用DispSyncSource表示,其中包含了与真实VSync信号的偏移值),这两个VSync信号源就是被虚拟出来分别用于控制App UI和SurfaceFlinger渲染。在EventThread的线程循环中,如果有需要就会向DispSync注册相应的listener。DispSyncThread就像乐队鼓手一样控制着大家的节奏。它在主循环中会先通过已经向DispSync注册的listener计算下一个要产生的虚拟VSync信号还要多久,等待相应时间后就会调用相应listener的callback函数。这样,对于那些注册了listener的监听者来说,就好像被真实的VSync信号控制着一样。至于EventControlThread是用来向真实的VSync硬件发命令。
三、Vsync框架
1.硬件或者软件创建vsyncThread产生vsync。
2.DispSyncThread处理vsync,把vsync虚拟化成vsync-app和vsync-sf。
3.vsync-app/sf按需产生(如果App和SurfaceFlinger都没有更新请求,则休眠省电):
APP端:APP需要更新界面时发出vsync请求给EventThread(设置connection.count>=0),DispSyncThread收到vsync信号后休眠offset,然后唤醒EventThread通知APP开始渲染。
SF端:sf请求EventThread-sf,EventThread-sf收到vsync后通知SF可以开始合成。
(vsync框架图)
4.代码分析:
4.1 创建五个线程:SurfaceFlingerThread、DispSyncThread、EventThead-App、EventThead-SF、VsyncThread,都属于SurfaceFlinger进程:
(1)启动SurfaceFlinger主线程:android-8.0.0_r4\frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp
- int main(int, char**) {
- startHidlServices();
- signal(SIGPIPE, SIG_IGN);
- // When SF is launched in its own process, limit the number of
- // binder threads to 4.
- ProcessState::self()->setThreadPoolMaxThreadCount();
- // start the thread pool
- sp<ProcessState> ps(ProcessState::self());
- ps->startThreadPool();
- // instantiate surfaceflinger
- sp<SurfaceFlinger> flinger = new SurfaceFlinger(); //其中创建了 mPrimaryDispSync 成员变量
- setpriority(PRIO_PROCESS, , PRIORITY_URGENT_DISPLAY);
- set_sched_policy(, SP_FOREGROUND);
- // Put most SurfaceFlinger threads in the system-background cpuset
- // Keeps us from unnecessarily using big cores
- // Do this after the binder thread pool init
- if (cpusets_enabled()) set_cpuset_policy(, SP_SYSTEM);
- // initialize before clients can connect
- flinger->init(); //传入mPrimaryDispSync并创建EventThread(app/sf)、HWComposer
- // publish surface flinger
- sp<IServiceManager> sm(defaultServiceManager());
- sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
- // publish GpuService
- sp<GpuService> gpuservice = new GpuService();
- sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
- struct sched_param param = {};
- param.sched_priority = ;
- if (sched_setscheduler(, SCHED_FIFO, ¶m) != ) {
- ALOGE("Couldn't set SCHED_FIFO");
- }
- // run surface flinger in this thread (SF的主线程)
- flinger->run();
- return ;
- }
(2)new SurfaceFlinger() 时创建了成员变量 DispSync mPrimaryDispSync; android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger.h
- 其中 DispSync 的构造函数会启动DispSyncThread线程:
- DispSync::DispSync(const char* name) :
- mName(name),
- mRefreshSkipCount(),
- mThread(new DispSyncThread(name)), //创建了DispSyncThread
- mIgnorePresentFences(!SurfaceFlinger::hasSyncFramework){
- mPresentTimeOffset = SurfaceFlinger::dispSyncPresentTimeOffset;
- mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
- // set DispSync to SCHED_FIFO to minimize jitter
- struct sched_param param = {};
- param.sched_priority = ;
- if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, ¶m) != ) {
- ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
- }
- reset();
- beginResync();
- if (kTraceDetailedInfo) {
- // If we're not getting present fences then the ZeroPhaseTracer
- // would prevent HW vsync event from ever being turned off.
- // Even if we're just ignoring the fences, the zero-phase tracing is
- // not needed because any time there is an event registered we will
- // turn on the HW vsync events.
- if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
- addEventListener("ZeroPhaseTracer", , new ZeroPhaseTracer());
- }
- }
- }
- (3)接着分析SurfaceFlinger对象,它是一个strong point,在引用时会调用其onFirstRef()方法:
- void SurfaceFlinger::onFirstRef()
- {
//初始化消息队列,其中创建了loop和handle- mEventQueue.init(this);
- }
flinger->run()的实现: android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger_hwc1.cpp
- void SurfaceFlinger::run() {
- do {
- waitForEvent(); //其中就是调用mEventQueue.waitMessage()
- } while (true);
- }
waitMessage中等待AP和EventTHread给它发数据:
- void MessageQueue::waitMessage() {
- do {
- IPCThreadState::self()->flushCommands();
- int32_t ret = mLooper->pollOnce(-);
- switch (ret) {
- case Looper::POLL_WAKE:
- case Looper::POLL_CALLBACK:
- continue;
- case Looper::POLL_ERROR:
- ALOGE("Looper::POLL_ERROR");
- continue;
- case Looper::POLL_TIMEOUT:
- // timeout (should not happen)
- continue;
- default:
- // should not happen
- ALOGE("Looper::pollOnce() returned unknown status %d", ret);
- continue;
- }
- } while (true);
- }
SurfaceFlinger初始化最重要的函数是init():
- void SurfaceFlinger::init() {
- ALOGI( "SurfaceFlinger's main thread ready to run. "
- "Initializing graphics H/W...");
- ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
- { // Autolock scope
- Mutex::Autolock _l(mStateLock);
- // initialize EGL for the default display
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
- // start the EventThread (创建了两个EventThread,他们的名字和offset不同)
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc, *this, false);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
- // 创建sf与EventThread之间的connection
- mEventQueue.setEventThread(mSFEventThread);
- // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
- struct sched_param param = {};
- param.sched_priority = ;
- if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != ) {
- ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
- }
- if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != ) {
- ALOGE("Couldn't set SCHED_FIFO for EventThread");
- }
- // Get a RenderEngine for the given display / config (can't fail)
- mRenderEngine = RenderEngine::create(mEGLDisplay,
- HAL_PIXEL_FORMAT_RGBA_8888);
- }
其中 mEventQueue.setEventThread(mSFEventThread) 的实现:
- //sufaceflinger/MessageQueue.cpp
- void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
- {
- mEventThread = eventThread;
- //创建连接,从连接获得dataChannel,把它的Fd添加到Looper,
- //也就是把EventThread里的一个fd传给了SF线程,
- //以后EventThread与SF就可以通过这个fd通信,
- mEvents = eventTHread->createEnvetConnection();
- mEventTube = mEvents->getDataChannel();
- mLooper->addFd(mEventTube->getFd(), , Looper::EVENT_INPUT,
- MessageQueue::cb_eventReceiver, this); //这个cb_eventRecevier很重要,它负责处理EventThread发过来的信号
- }
(4)hwcomposer的构造函数:android-8.0.0_r4\frameworks\native\services\surfaceflinger\DisplayHardware\HWComposer_hwc1.cpp
- HWComposer::HWComposer(
- const sp<SurfaceFlinger>& flinger,
- EventHandler& handler)
- : mFlinger(flinger),
- mFbDev(), mHwc(), mNumDisplays(),
- mCBContext(new cb_context),
- mEventHandler(handler),
- mDebugForceFakeVSync(false)
- {
- for (size_t i = ; i<MAX_HWC_DISPLAYS ; i++) {
- mLists[i] = ;
- }
- for (size_t i= ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
- mLastHwVSync[i] = ;
- mVSyncCounts[i] = ;
- }
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.no_hw_vsync", value, "");
- mDebugForceFakeVSync = atoi(value);
- bool needVSyncThread = true;
- // Note: some devices may insist that the FB HAL be opened before HWC.
- int fberr = loadFbHalModule();
- loadHwcModule();
- if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // close FB HAL if we don't needed it.
- // FIXME: this is temporary until we're not forced to open FB HAL
- // before HWC.
- framebuffer_close(mFbDev);
- mFbDev = NULL;
- }
- // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
- if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
- && !mFbDev) {
- ALOGE("ERROR: failed to open framebuffer (%s), aborting",
- strerror(-fberr));
- abort();
- }
- // these display IDs are always reserved
- for (size_t i= ; i<NUM_BUILTIN_DISPLAYS ; i++) {
- mAllocatedDisplayIDs.markBit(i);
- }
- if (mHwc) {
- ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
- (hwcApiVersion(mHwc) >> ) & 0xff,
- (hwcApiVersion(mHwc) >> ) & 0xff);
- if (mHwc->registerProcs) {
- mCBContext->hwc = this;
- mCBContext->procs.invalidate = &hook_invalidate;
- mCBContext->procs.vsync = &hook_vsync;
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
- mCBContext->procs.hotplug = &hook_hotplug;
- else
- mCBContext->procs.hotplug = NULL;
- memset(mCBContext->procs.zero, , sizeof(mCBContext->procs.zero));
- mHwc->registerProcs(mHwc, &mCBContext->procs);
- }
- // don't need a vsync thread if we have a hardware composer
- needVSyncThread = false;
- // always turn vsync off when we start
- eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, );
- // the number of displays we actually have depends on the
- // hw composer version
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- // 1.3 adds support for virtual displays
- mNumDisplays = MAX_HWC_DISPLAYS;
- } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // 1.1 adds support for multiple displays
- mNumDisplays = NUM_BUILTIN_DISPLAYS;
- } else {
- mNumDisplays = ;
- }
- }
- if (mFbDev) {
- ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
- "should only have fbdev if no hwc or hwc is 1.0");
- DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
- disp.connected = true;
- disp.format = mFbDev->format;
- DisplayConfig config = DisplayConfig();
- config.width = mFbDev->width;
- config.height = mFbDev->height;
- config.xdpi = mFbDev->xdpi;
- config.ydpi = mFbDev->ydpi;
- config.refresh = nsecs_t(1e9 / mFbDev->fps);
- disp.configs.push_back(config);
- disp.currentConfig = ;
- } else if (mHwc) {
- // here we're guaranteed to have at least HWC 1.1
- for (size_t i = ; i<NUM_BUILTIN_DISPLAYS ; i++) {
- queryDisplayProperties(i);
- }
- }
- if (needVSyncThread) {
- // we don't have VSYNC support, we need to fake it
// 如果不支持硬件Vsync则创建软件vysnc线程,它是一个sp<>,其onFirstRef()真正创建运行这个线程- mVSyncThread = new VSyncThread(*this);
- }
- }
加载并准备hw composer模块。Sets mHwc
- void HWComposer::loadHwcModule()
- {
- hw_module_t const* module;
- if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != ) {
- ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
- return;
- }
- int err = hwc_open_1(module, &mHwc);
- if (err) {
- ALOGE("%s device failed to initialize (%s)",
- HWC_HARDWARE_COMPOSER, strerror(-err));
- return;
- }
- if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
- hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
- hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
- ALOGE("%s device version %#x unsupported, will not be used",
- HWC_HARDWARE_COMPOSER, mHwc->common.version);
- hwc_close_1(mHwc);
- mHwc = NULL;
- return;
- }
- }
4.2 SurfaceFLinger使用vsync过程
(1)App发数据给sf,sf发请求给EventThread-sf:AP是Producer,它通过listener->onFrameAvailable() ->进入消费者 -> mFrameAvailableListener(就是Layer对象) -> 进入SF线程-> mFlinger->signalLayerUpdate() -> mEventQueue.invalidate();
- //surfaceflinger/MessageQueue.cpp
- void MessageQueue::invalidate() {
- //mEvents是sp<IDisplayEventConnection>
- //也就是sf线程使用connection向EventThread线程请求下一个vsync信号
- mEvents->requestNextVsync();
- }
- --->
- //surfaceFlinger/EventThread.cpp
- void EventThread::Connection::requestNextVsync() {
- mEventThread->requestrNextVsync(this);
- }
- --->
- void EventTHread::requestNextVysnc(
- const sp<EventTHread::Connection>& connection) {
- if(connection->count < ){
- //若cnt小于0,则cnt=0,然后发出广播,来唤醒某个线程,
- //当connection的cnt >= 0怎么它需要从EventThread得到vsync
- //这个函数得代码在EventThread,但是它执行在SF线程
- //也就是说,SF线程使用EventThread的函数向EventThread发出广播来唤醒EventThread线程
- connection->count = ;
- mCondition.boradcast();
- }
- }
(2)EventThread-sf发请求给DispSyncThread,EventThread里面一定有一个threadLoop: android-8.0.0_r4\frameworks\native\services\surfaceflinger\EventThread.cpp
- bool EventThread::threadLoop() {
- DisplayEventReceiver::Event event;
- Vector< sp<EventThread::Connection> > signalConnections;
- //1,EventThread向DispSyncThread发出vsync请求
//2,等待vsync- signalConnections = waitForEvent(&event);
- // dispatch events to listeners...
const size_t count = signalConnections.size();- for (size_t i= ; i<count ; i++) {
- const sp<Connection>& conn(signalConnections[i]);
- // now see if we still need to report this event
- // 当EventThread收到Vsync,把它转交给SF线程
- status_t err = conn->postEvent(event);
- if (err == -EAGAIN || err == -EWOULDBLOCK) {
- // The destination doesn't accept events anymore, it's probably
- // full. For now, we just drop the events on the floor.
- // FIXME: Note that some events cannot be dropped and would have
- // to be re-sent later.
- // Right-now we don't have the ability to do this.
- ALOGW("EventThread: dropping event (%08x) for connection %p",
- event.header.type, conn.get());
- } else if (err < ) {
- // handle any other error on the pipe as fatal. the only
- // reasonable thing to do is to clean-up this connection.
- // The most common error we'll get here is -EPIPE.
- removeDisplayEventConnection(signalConnections[i]);
- }
- }
- return true;
- }
分析waitForEvent():
- //this will return when
- //1, a vsync event has benn recevied
- //2,there was as least one connection interested in receiving it when we started waiting
- Vector< sp<EventThread::Connection > >EventThread::waitForEvent(
- DisplayEventReceiver::Event* event)
- {
- //find out connections waitting for events
- size_t count = mDisplayEventConnections.size();
- ofr(size_t i=; i<count; i++) {
- if(connection->count >= ) {
- //we need vsync events because at least
- //one connnection is waiting for it
- waitForVSync = true;
- }
- ......
- if(waitFOrVSync){
- enableVSyncLocked(); //如果上面的count >= 0,代表需要得到vsync信号,然后调用enableVSyncLocked()
- }
- if(waitForVSync){
- ......
- } else {
- //EventThread之后就会休眠等待vsync
- mCondition.wait(mLock);
- }
- }
- }
enableVSyncLocked中给DisplaySyncThread设置回调,在DisplaySyncThread收到vsync信号后就调用这个回调函数:
- void EventThread::enableVSyncLocked() {
- if(!mVsyncEnabled) {
- mVsyncEnabled = true;
- mVSyncSource->setCallback(static_cast<VSyncSource::Callback*)(this));
- mVSYncSource->setVSyncEnabled(true);
- }
- }
(3)H/S vsync唤醒DispSyncThread:
- //surfaceFlinger/DIsplayHardware/HWComposer_hwc1.cpp
- bool HWComposer::VSyncThread::threadLoop() {
- clock_nanosleep();
- //休眠 完成后,调用它,发出vsync信号
- //mEventHanlder就是SurfaceFlinger,
- mHwc.mEventHandler.onVSyncReceived(, next_vsync);
- }
- --->
- //surfaceflinger/SurafceFLinger.cpp
- void SurfaceFLinger::onVSyncReceived(type, nescs_t timestamp){
- if(type == && mPrimaryHWVsyncEnabled) {
- //DispSync::addResyncSample => updateModelLocked() =>
- //mThread->updateModel => mCond.signal()来唤醒某个线程,
- //mCond.signal()在DispSync.cpp,属于DispSYncThread,
- //还是之前说的套路,swVsyncThread使用DispSync的函数唤醒DispSYncThread
- needsHwVsync = mPrimaryDIspSync.addResyncSample(timestamp);
- }
- if(needsHwVsync) {
- enableHardwareVsync();
- }
- }
(4)DispSyncThread发信号给EventThread,EventThread发信号给SF线程。
- //surfaceflinger/DispSync.cpp
- class DispSyncThread : public Thread {
- virtual bool threadLoop() {
- //计算最近的eventThread的时间,EventThread是Listener,
- // =>computeListenerNextEventTimeLocked
- targetTime = computeNextEventTimeLocked(now);
- //休眠
- if(now < targetTime) {
- mCond.waitRelative(mMutex, targetrTime-now);
- }
- //之后被vsync信号唤醒,获取callback
- callbackInvacations = gatherCallbackInvocationsLocked(now);
- if(callbackInvocations.size() > ) {
- //执行callback,导致EventThread的onVsyncEvent函数被调用
- fireCallbackInvocations(callbackInvovcations);
- }
- }
- }
如果EventThread发现Connection的cnt >= 0,就会向DispSyncThread注册回调函数,最后会通过callback构造出Listener,而且EventThread运行时间是收到vsync之后加一个offset,fireCallbackInvocations()调用EventThread类的onVSyncEvent来唤醒EventThread线程:
- //surfaceFlinger/EventThread.cpp
- void EventThread::onVSyncEvent(nsecs_t timestamp) {
- Mutex::Autolock _l(mLock);
- mVSyncEvent[].header.id = ;
- mVsyncEvent[].vsync.count++;
- //发出广播,唤醒EvenThread::threadLoop()向app或sf发出信号
- mCondition.broadcast();
- }
EventThread::threadLoop()在waitForEvent里面休眠(mCondition.wait),收到广播后被唤醒,然后调用conn->postEvent(event)向SF线程或者AP发出信号,并通过connection的fd把数据写到SF线程,同样SF线程通过fd获得数据,然后调用SF线程的处理函数。
- status_t EventThread::Connection::postEvent(
- const DisplayEventReceiver::Event& event) {
- ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, );
- return size < ? status_t(size) : status_t(NO_ERROR);
- }
(5)sf线程对vsync的处理:在flinger->init()创建connection时,得到了一个fd,然后会检测fd。
flinger->init() => MessageQueue::setEventThread:
- mEventTube = mEvent->getDataChannel();
- //检测fd,从fd得到数据,会调用MessageQueue::cb_eventRecevier函数
- mLooper->addFd(mEventTube0>getFd(),....,MessageQueue::cb_eventRecevier, this);
--->- //surfaceflinger/MessageQueue.cpp
- int MessageQueue::cb_eventRecevier(int fd, int event, void* data) {
- return queue->eventRecevier(fd, events);
- }
--->- int MessageQueue::eventReceiver(int fd, int events) {
- mHanlder->displatchInvalidate();
- }
- --->
- void MessageQueue::Handler::displayInvaliadate() {
- mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
- }
- SurfaceFlinger中接收并处理消息:
- void MessageQueue::Handler::handleMessage(const Message& message) {
- switch(message.what) {
- ...
- case INVALIDATE:
- mQueue.mFlinger->onMessageReceived(message.what);
- }
- }
- --->
- // android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger_hwc1.cpp
- void SurfaceFlinger::onMessageReceived(int32_t what) {
- ATRACE_CALL();
- switch (what) {
- case MessageQueue::INVALIDATE: {
- bool refreshNeeded = handleMessageTransaction(); //处理事务(设置flag,并未实际操作各个buffer):
//①在handleTransactionLocked()中遍历每个Layer,执行layer->doTransaction(0)
//②处理Display事务(add/remove)
//③Layer角度发生了变化
//④处理sf本身事务: Layer的增加或者删除
- refreshNeeded |= handleMessageInvalidate(); //处理各Layer的buffer更换,使原来的界面无效,并准备好新数据用来更新:
//①accquire next buffer
//②release previous buffer
//③bindTextureImageLocked() ---> glEGLImageTargetTexture2DOES()
- refreshNeeded |= mRepaintEverything;
- if (refreshNeeded) {
- // Signal a refresh if a transaction modified the window state,
- // a new buffer was latched, or if HWC has requested a full
- // repaint
- signalRefresh(); //发出Refresh信号,导致下面的 handleMessageRefresh()函数被调用
- }
- break;
- }
- case MessageQueue::REFRESH: {
- handleMessageRefresh(); //①计算各Layer的可视区域
//②合成显示:a.调用opengl把各个Layer的可视区域在一个内存上描绘出来
// b.使用hw composer硬件合成
- break; } } }
(Vsync时序图)
Android 显示系统:Vsync机制的更多相关文章
- 11.5 Android显示系统框架_Vsync机制_黄油计划_三个方法改进显示系统
5. Vsync机制5.1 黄油计划_三个方法改进显示系统vsync, triple buffering, vsync虚拟化 参考文档:林学森 <深入理解Android内核设计思想>第2版 ...
- Android 显示系统:SurfaceFlinger详解
一.Android系统启动 Android设备从按下开机键到桌面显示画面,大致过程如下图流程: 开机显示桌面.从桌面点击 App 图标到 Activity显示在屏幕上的过程又是怎样的呢?下面介绍And ...
- 11.1 Android显示系统框架_framebuffer原理及改进
1. Android显示系统框架Android Graphic UI with GPU Hardware Accelerationhttps://community.nxp.com/docs/DOC- ...
- Android 显示系统:OpenGL简介和Gralloc代码分析
一.OpenGL ES与EGL Android的GUI系统是基于OpenGL/EGL来实现的. 由于OpenGL是通用函数库,在不同平台系统上需要被“本土化”——把它与具体平台的窗口系统建立起关联,F ...
- 11.5 Android显示系统框架_Vsync机制_代码分析
5.5 surfaceflinger对vsync的处理buffer状态图画得不错:http://ju.outofmemory.cn/entry/146313 android设备可能连有多个显示器,AP ...
- 11.4 Android显示系统框架_APP与SurfaceFlinger内部机制分析
4.1 APP跟SurfaceFlinger之间的重要数据结构 一个应用程序有一个或者多个surface(一般只有一个),一个surface有一个或者多个buffer,这些buffer需要应用向sur ...
- Android 显示系统:飞思卡尔平台图形界面与GPU硬件加速
图形是Android平台中的一个大主题,包含java/jni图形框架和2d/3d图形引擎(skia.OpenGL-ES.renderscript). 本文档描述了飞思卡尔设备上的一般Android图形 ...
- 11.2 Android显示系统框架_android源码禁用hwc和GPU
2. 修改tiny4412_Android源码禁用hwc和gpu(厂家不会提供hwc和gpu的源代码,没有源代码就没法分析了,因此在这里禁用该功能并用软件库实现)最终源码: git clone htt ...
- 11.3 Android显示系统框架_最简单的surface测试程序
APP有一个surface(界面),其有多个buffer用来存放界面数据,这些buffer是向surfaceflinger申请的: 因此我们编写的surface测试程序步骤: (1)获得surface ...
随机推荐
- ln -s vs mount --bind
First ,Symlinks and bind mounts are a whole different ballgame. ln -s you create a symbolic link,whi ...
- CentOS7.X 搭建LAMP
第一部分搭建LAMP基础环境 1.检查CentOS是否为7.x版本 2.安装LAMP中的apache,采用yum源方法安装 yum install httpd httpd-devel A ...
- java - day010 - 基本类型包装,自动装箱和拆箱,日期,集合
基本类型的包装类 byte Byte short Short int Integer long Long float Float double Double char Character boolea ...
- 模拟一个http 请求的json格式报文,带 rsa 签名操作
一.对需要加密的字符串,定义RsaSignUnsign 类,代码如下: 实现了: 1.实现了生成新的pubkey.pri_key方法: 2.将新生成的keys 写入文件: 3.从文件获取pubkey. ...
- python3 random
一.random 1.生成伪随机数 2.伪随机数是可预测的,严格意义上不具有随机性质,通常用数学公式的方法(比如统计分布,平方取中等)获得 3.正如数列需要有首项,产生伪随机数需要一个初值用来计算整个 ...
- validatebox自定义验证规则以及使用
//===============jsp======state==== //开启验证 <script type="text/javascript"> y ...
- 使用Django 测试客户端一起测试视图,模板和URL
Django 测试客户端 self.client.get(url) 测试客户端是Django中TestCase类的一个属性名. 至此已经在网站中可以创建一个清单了. 那么,现在是可以在unit te ...
- 冒泡排序之javascript
冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字 ...
- Educational Codeforces Round 67 (Rated for Div. 2) B题【前缀+二分】【补题ING系列】
题意:给出一个字符串s, 可以从左往右拿走s的字符, 至少要到s的第几个位置才能拼成t 思路:用二维数组记录前缀,然后二分即可. #include<bits/stdc++.h> using ...
- 005_STM32程序移植之_RC522读卡模块
1. 测试环境:STM32C8T6 2. 测试模块:RC522读卡模块 3. 测试接口: RC522读卡模块: VCC------------------3.3V GND--------------- ...