Android顯示系統中VSYNC簡介
Android系統中關於VSYNC的簡介
92HWComposer::HWComposer(
93 const sp<SurfaceFlinger>&flinger,
94 EventHandler& handler)
95 : mFlinger(flinger),
96 mFbDev(0), mHwc(0), mNumDisplays(1),
97 mCBContext(new cb_context),
98 mEventHandler(handler),
99 mVSyncCount(0),mDebugForceFakeVSync(false)
100{
101 for (size_t i =0 ; i<MAX_DISPLAYS ; i++){
102 mLists[i] = 0;
103 }
104
105 char value[PROPERTY_VALUE_MAX];
106 property_get("debug.sf.no_hw_vsync", value, "0");
107 mDebugForceFakeVSync = atoi(value);
108
109 boolneedVSyncThread = true;
110
111 // Note: some devices may insist that theFB HAL be opened before HWC.
112 int fberr = loadFbHalModule();
113 loadHwcModule();
114
115 if (mFbDev && mHwc &&hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
116 // close FB HAL if we don't needed it.
117 // FIXME: this is temporary until we'renot forced to open FB HAL
118 // before HWC.
119 framebuffer_close(mFbDev);
120 mFbDev = NULL;
121 }
122
123 // If we have no HWC, or a pre-1.1 HWC, anFB dev is mandatory.
124 if ((!mHwc || !hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_1))
125 && !mFbDev) {
126 ALOGE("ERROR: failed to openframebuffer (%s), aborting",
127 strerror(-fberr));
128 abort();
129 }
130
131 // these display IDs are always reserved
132 for (size_t i=0 ;i<NUM_PHYSICAL_DISPLAYS ; i++) {
133 mAllocatedDisplayIDs.markBit(i);
134 }
135
136 if (mHwc) {
137 ALOGI("Using %s version%u.%u", HWC_HARDWARE_COMPOSER,
138 (hwcApiVersion(mHwc) >> 24)& 0xff,
139 (hwcApiVersion(mHwc) >> 16)& 0xff);
140 if (mHwc->registerProcs) {
141 mCBContext->hwc = this;
142 mCBContext->procs.invalidate= &hook_invalidate;
143 mCBContext->procs.vsync= &hook_vsync;
144 if (hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_1))
145 mCBContext->procs.hotplug =&hook_hotplug;
146 else
147 mCBContext->procs.hotplug =NULL;
148 memset(mCBContext->procs.zero,0, sizeof(mCBContext->procs.zero));
149 mHwc->registerProcs(mHwc,&mCBContext->procs);
150 }
151
152 // don't need avsync thread if we have a hardware composer
153 needVSyncThread= false;
154 // always turn vsync off when we start
155 eventControl(HWC_DISPLAY_PRIMARY,HWC_EVENT_VSYNC, 0);
156
157 // the number of displays we actuallyhave depends on the
158 // hw composer version
159 if (hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_EXP)) {
160 // 1.?? adds support for virtualdisplays
161 mNumDisplays = MAX_DISPLAYS;
162 } else if (hwcHasApiVersion(mHwc,HWC_DEVICE_API_VERSION_1_1)) {
163 // 1.1 adds support for multipledisplays
164 mNumDisplays = MAX_DISPLAYS;
165 } else {
166 mNumDisplays = 1;
167 }
168 }
169
170 if (mFbDev) {
171 ALOG_ASSERT(!(mHwc &&hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
172 "should only have fbdev ifno hwc or hwc is 1.0");
173
174 DisplayData&disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
175 disp.connected = true;
176 disp.width = mFbDev->width;
177 disp.height = mFbDev->height;
178 disp.format = mFbDev->format;
179 disp.xdpi = mFbDev->xdpi;
180 disp.ydpi = mFbDev->ydpi;
181 if (disp.refresh == 0) {
182 disp.refresh = nsecs_t(1e9 /mFbDev->fps);
183 ALOGW("getting VSYNC periodfrom fb HAL: %lld", disp.refresh);
184 }
185 if (disp.refresh == 0) {
186 disp.refresh = nsecs_t(1e9 / 60.0);
187 ALOGW("getting VSYNC periodfrom thin air: %lld",
188 mDisplayData[HWC_DISPLAY_PRIMARY].refresh);
189 }
190 } else if (mHwc) {
191 // here we're guaranteed to have atleast HWC 1.1
192 for (size_t i =0 ;i<NUM_PHYSICAL_DISPLAYS ; i++) {
193 queryDisplayProperties(i);
194 }
195 }
196
197 if(needVSyncThread) {
198 // we don't have VSYNC support, we needto fake it
199 mVSyncThread =new VSyncThread(*this);
200 }
201}
在HWComposer建構函式中,如果有硬體HardwareComposer,那麼使用硬體的”hwcVSyncThread”主題vsync_loop查詢vsync_event;否則使用VSyncThread Fake VSYNC。
使用硬體hwcVSyncThread的情況如下
52static void*vsync_loop(void *param)
53{
54 hwc_context_t * ctx =reinterpret_cast<hwc_context_t *>(param);
55
56 char thread_name[64] =HWC_VSYNC_THREAD_NAME;
57 prctl(PR_SET_NAME, (unsigned long)&thread_name, 0, 0, 0);
58 setpriority(PRIO_PROCESS, 0,HAL_PRIORITY_URGENT_DISPLAY +
59 android::PRIORITY_MORE_FAVORABLE);
60
61 const int MAX_DATA = 64;
62 char vdata[MAX_DATA];
63 bool logvsync = false;
64
65 struct pollfd pfd[2];
66 int fb_fd[2];
67 uint64_t timestamp[2] = {0,0};
68 int num_displays;
69
70 char property[PROPERTY_VALUE_MAX];
71 if(property_get("debug.hwc.fakevsync", property, NULL) > 0){
72 if(atoi(property) == 1)
73 ctx->vstate.fakevsync = true;
74 }
75
76 if(property_get("debug.hwc.logvsync", property, 0) > 0) {
77 if(atoi(property) == 1)
78 logvsync = true;
79 }
80
81 if (ctx->mExtDisplay->isConnected())
82 num_displays = 2;
83 else
84 num_displays = 1;
85
86 char vsync_node_path[MAX_SYSFS_FILE_PATH];
87 for (int dpy = HWC_DISPLAY_PRIMARY; dpy< num_displays; dpy++) {
88 snprintf(vsync_node_path,sizeof(vsync_node_path),
89 "/sys/class/graphics/fb%d/vsync_event",
90 dpy == HWC_DISPLAY_PRIMARY ? 0:
91 overlay::Overlay::getInstance()->
92 getFbForDpy(HWC_DISPLAY_EXTERNAL));
93 ALOGI("%s: Reading vsync fordpy=%d from %s", __FUNCTION__, dpy,
94 vsync_node_path);
95 fb_fd[dpy] = open(vsync_node_path,O_RDONLY);
96
97 if (fb_fd[dpy] < 0) {
98 // Make sure fb device is openedbefore starting this thread so this
99 // never happens.
100 ALOGE ("%s:not able to openvsync node for dpy=%d, %s",
101 __FUNCTION__, dpy,strerror(errno));
102 if (dpy == HWC_DISPLAY_PRIMARY) {
103 ctx->vstate.fakevsync =true;
104 break;
105 }
106 }
107 // Read once from the fds to clear thefirst notify
108 pread(fb_fd[dpy], vdata , MAX_DATA, 0);
109
110 pfd[dpy].fd = fb_fd[dpy];
111 if (pfd[dpy].fd >= 0)
112 pfd[dpy].events = POLLPRI |POLLERR;
113 }
114
115 if (LIKELY(!ctx->vstate.fakevsync)) {
116 do {
117 int err = poll(pfd, num_displays,-1);
118 if(err > 0) {
119 for (int dpy =HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
120 if (pfd[dpy].revents &POLLPRI) {
121 int len =pread(pfd[dpy].fd, vdata, MAX_DATA, 0);
122 if (UNLIKELY(len <0)) {
123 // If the read wasjust interrupted - it is not a
124 // fatal error.Just continue in this case
125 ALOGE ("%s:Unable to read vsync for dpy=%d : %s",
126 __FUNCTION__,dpy, strerror(errno));
127 continue;
128 }
129 // extract timestamp
130 if (!strncmp(vdata,"VSYNC=", strlen("VSYNC="))) {
131 timestamp[dpy] =strtoull(vdata + strlen("VSYNC="),
132 NULL, 0);
133 }
134 // send timestamp toSurfaceFlinger
135 ALOGD_IF (logvsync,
136 "%s:timestamp %llu sent to SF for dpy=%d",
137 __FUNCTION__,timestamp[dpy], dpy);
138 ctx->proc->vsync(ctx->proc, dpy, timestamp[dpy]);
139 }
140 }
141
142 } else {
143 ALOGE("%s: vsync pollfailed errno: %s", __FUNCTION__,
144 strerror(errno));
145 continue;
146 }
147 } while (true);
148
149 } else {
150
151 //Fake vsync is used only when setexplicitly through a property or when
152 //the vsync timestamp node cannot beopened at bootup. There is no
153 //fallback to fake vsync from the truevsync loop, ever, as the
154 //condition can easily escapedetection.
155 //Also, fakevsync is delivered only for the primary display.
156 do {
157 usleep(16666);
158 timestamp[HWC_DISPLAY_PRIMARY] =systemTime();
159 ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY,
160 timestamp[HWC_DISPLAY_PRIMARY]);
161
162 } while (true);
163 }
164
165 for (int dpy = HWC_DISPLAY_PRIMARY; dpy<= HWC_DISPLAY_EXTERNAL; dpy++ ) {
166 if(fb_fd[dpy] >= 0)
167 close (fb_fd[dpy]);
168 }
169
170 return NULL;
171}
首先讀硬體事件,如果除錯fake,則使用usleep fake 60HZ VSYNC,回撥hook_vsync; 這是在hwc_registerProcs中註冊的;
85static voidhwc_registerProcs(struct hwc_composer_device_1* dev,
86 hwc_procs_tconst* procs)
87{
88 ALOGI("%s", __FUNCTION__);
89 hwc_context_t* ctx = (hwc_context_t*)(dev);
90 if(!ctx) {
91 ALOGE("%s: Invalid context",__FUNCTION__);
92 return;
93 }
94 ctx->proc =procs;
95
96 // Now that we have the functions needed,kick off
97 // the uevent & vsync threads
98 init_uevent_thread(ctx);
99 init_vsync_thread(ctx); 啟動”hwcVSyncThread”執行緒,執行vsync_loop
100}
ctx->proc->vsync即呼叫HWComposer::hook_vsync處理如下。
271voidHWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
272 int64_t timestamp) {
273 cb_context* ctx =reinterpret_cast<cb_context*>(
274 const_cast<hwc_procs_t*>(procs));
275 ctx->hwc->vsync(disp,timestamp);
276}
Ctx->hwc->vsync函式是HWComposer::vsync,程式碼如下
289voidHWComposer::vsync(int disp, int64_t timestamp) {
290 ATRACE_INT("VSYNC",++mVSyncCount&1);
291 mEventHandler.onVSyncReceived(disp,timestamp);
292 Mutex::Autolock _l(mLock);
293 mLastHwVSync = timestamp;
294}
mEventHandler是SurfaceFlinger自身。
使用VSyncThread模擬的情況
1075boolHWComposer::VSyncThread::threadLoop() {
1076 { // scope for lock
1077 Mutex::Autolock _l(mLock);
1078 while (!mEnabled) {
1079 mCondition.wait(mLock);
1080 }
1081 }
1082
1083 const nsecs_t period = mRefreshPeriod;
1084 const nsecs_t now =systemTime(CLOCK_MONOTONIC);
1085 nsecs_t next_vsync = mNextFakeVSync;
1086 nsecs_t sleep = next_vsync - now;
1087 if (sleep < 0) {
1088 // we missed, find where the next vsyncshould be
1089 sleep = (period - ((now - next_vsync) %period));
1090 next_vsync = now + sleep;
1091 }
1092 mNextFakeVSync = next_vsync + period;
1093
1094 struct timespec spec;
1095 spec.tv_sec = next_vsync / 1000000000;
1096 spec.tv_nsec = next_vsync % 1000000000;
1097
1098 int err;
1099 do {
1100 err = clock_nanosleep(CLOCK_MONOTONIC,TIMER_ABSTIME, &spec, NULL);
1101 } while (err<0 && errno ==EINTR);
1102
1103 if (err == 0) {
1104 mHwc.mEventHandler.onVSyncReceived(0,next_vsync);
1105 }
1106
1107 return true;
1108}
mHwc的mEventHandler就是SurfaceFlinger,這是在SurfaceFlinger的readyToRun時構造HWComposer時初始化的。
474status_tSurfaceFlinger::readyToRun()
475{
476 ALOGI( "SurfaceFlinger's main thread ready to run. "
477 "Initializing graphicsH/W...");
478
479 Mutex::Autolock _l(mStateLock);
480
481 // initialize EGL for the default display
482 mEGLDisplay =eglGetDisplay(EGL_DEFAULT_DISPLAY);
483 eglInitialize(mEGLDisplay, NULL, NULL);
484
485 // Initialize the H/W composer object. There may or may not be an
486 // actual hardware composer underneath.
487 mHwc = new HWComposer(this,
488 *static_cast<HWComposer::EventHandler *>(this));
至此兩種情況都呼叫到了SurfaceFlinger::onVSyncReceived,該函式處理如下:
704voidSurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
705 if (mEventThread == NULL) {
706 // This is a temporary workaround forb/7145521. A non-null pointer
707 // does not mean EventThread hasfinished initializing, so this
708 // is not a correct fix.
709 ALOGW("WARNING: EventThread notstarted, ignoring vsync");
710 return;
711 }
712 if (uint32_t(type) <DisplayDevice::NUM_DISPLAY_TYPES) {
713 // we should only receiveDisplayDevice::DisplayType from the vsync callback
714 mEventThread->onVSyncReceived(type,timestamp);
715 }
716}
EventThread的onVSyncReceived
114voidEventThread::onVSyncReceived(int type, nsecs_t timestamp) {
115 ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES,
116 "received vsync event for aninvalid display (id=%d)", type);
117
118 Mutex::Autolock _l(mLock);
119 if (type < HWC_NUM_DISPLAY_TYPES) {
120 mVSyncEvent[type].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
121 mVSyncEvent[type].header.id = type;
122 mVSyncEvent[type].header.timestamp =timestamp;
123 mVSyncEvent[type].vsync.count++;
124 mCondition.broadcast();
125 }
126}
EventThread的threadLoop中,waitForEvent等到VSYNC後,然後postEvent(DISPLAY_EVENT_VSYNC)回Connnections
144boolEventThread::threadLoop() {
145 DisplayEventReceiver::Event event;
146 Vector<sp<EventThread::Connection> > signalConnections;
147 signalConnections = waitForEvent(&event); // mCondition.wait
148
149 // dispatch events to listeners...
150 const size_t count =signalConnections.size();
151 for (size_t i=0 ; i<count ; i++) {
152 const sp<Connection>&conn(signalConnections[i]);
153 // now see if we still need to reportthis event
154 status_t err = conn->postEvent(event);
155 if (err == -EAGAIN || err ==-EWOULDBLOCK) {
156 // The destination doesn't acceptevents anymore, it's probably
157 // full. For now, we just drop theevents on the floor.
158 // FIXME: Note that some eventscannot be dropped and would have
159 // to be re-sent later.
160 // Right-now we don't have theability to do this.
161 ALOGW("EventThread: droppingevent (%08x) for connection %p",
162 event.header.type,conn.get());
163 } else if (err < 0) {
164 // handle any other error on thepipe as fatal. the only
165 // reasonable thing to do is toclean-up this connection.
166 // The most common error we'll gethere is -EPIPE.
167 removeDisplayEventConnection(signalConnections[i]);
168 }
169 }
170 return true;
171}
DisplayEventConnection主要有SurfaceFlinger的MessageQueue;其餘的Java應用也可以通過NativeDisplayEventReceiver來註冊。下面只關注SurfaceFlinger的MessageQueue。
474status_tSurfaceFlinger::readyToRun()
475{
476 ALOGI( "SurfaceFlinger's main thread ready to run. "
477 "Initializing graphicsH/W...");
478
479 Mutex::Autolock _l(mStateLock);
540 mEventQueue.setEventThread(mEventThread);
103voidMessageQueue::setEventThread(const sp<EventThread>& eventThread)
104{
105 mEventThread = eventThread;
106 mEvents =eventThread->createEventConnection();
107 mEventTube = mEvents->getDataChannel();
108 mLooper->addFd(mEventTube->getFd(),0, ALOOPER_EVENT_INPUT,
109 MessageQueue::cb_eventReceiver,this);
110}
177intMessageQueue::cb_eventReceiver(int fd, int events, void* data) {
178 MessageQueue* queue =reinterpret_cast<MessageQueue *>(data);
179 return queue->eventReceiver(fd,events);
180}
181
182intMessageQueue::eventReceiver(int fd, int events){
183 ssize_t n;
184 DisplayEventReceiver::Event buffer[8];
185 while ((n =DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
186 for (int i=0 ; i<n ; i++) {
187 if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
188#ifINVALIDATE_ON_VSYNC
189 mHandler->dispatchInvalidate();
190#else
191 mHandler->dispatchRefresh();
192#endif
193 break;
194 }
195 }
196 }
197 return 1;
198}
向Handler的佇列中傳送訊息,在Handler所在訊息迴圈執行緒中進行處理
52voidMessageQueue::Handler::dispatchRefresh() {
53 if ((android_atomic_or(eventMaskRefresh,&mEventMask) & eventMaskRefresh) == 0) {
54 mQueue.mLooper->sendMessage(this,Message(MessageQueue::REFRESH));
55 }
56}
57
58voidMessageQueue::Handler::dispatchInvalidate() {
59 if ((android_atomic_or(eventMaskInvalidate,&mEventMask) & eventMaskInvalidate) == 0) {
60 mQueue.mLooper->sendMessage(this,Message(MessageQueue::INVALIDATE));
61 }
62}
63
64voidMessageQueue::Handler::dispatchTransaction() {
65 if((android_atomic_or(eventMaskTransaction, &mEventMask) &eventMaskTransaction) == 0) {
66 mQueue.mLooper->sendMessage(this,Message(MessageQueue::TRANSACTION));
67 }
68}
69
70voidMessageQueue::Handler::handleMessage(const Message& message) {
71 switch (message.what) {
72 case INVALIDATE:
73 android_atomic_and(~eventMaskInvalidate, &mEventMask);
74 mQueue.mFlinger->onMessageReceived(message.what);
75 break;
76 case REFRESH:
77 android_atomic_and(~eventMaskRefresh, &mEventMask);
78 mQueue.mFlinger->onMessageReceived(message.what);
79 break;
80 case TRANSACTION:
81 android_atomic_and(~eventMaskTransaction,&mEventMask);
82 mQueue.mFlinger->onMessageReceived(message.what);
83 break;
84 }
85}
明顯應該是呼叫到了MessageQueue對應的SurfaceFlinger了
130voidSurfaceFlinger::onFirstRef()
131{
132 mEventQueue.init(this);
133
134 run("SurfaceFlinger",PRIORITY_URGENT_DISPLAY);
135
136 // Wait for the main thread to be done withits initialization
137 mReadyToRunBarrier.wait();
138}
SurfaceFlinger啟動合成處理入口。
745voidSurfaceFlinger::onMessageReceived(int32_t what) {
746 ATRACE_CALL();
747 switch (what) {
748 case MessageQueue::TRANSACTION:
749 handleMessageTransaction();
750 break;
751 case MessageQueue::INVALIDATE:
752 handleMessageTransaction();
753 handleMessageInvalidate();
754 signalRefresh();
755 break;
756 case MessageQueue::REFRESH:
757 handleMessageRefresh();
758 break;
759 }
760}
需要關注上SurfaceFlinger中幾個主要執行緒,加以理解本文。
這幾個執行緒大致是SurfaceFlinger, EventThread, VSyncThread, hwcEventThread, GLUpdater, Binder worker threads。