Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android顯示系統中VSYNC簡介

Android顯示系統中VSYNC簡介

編輯:關於Android編程

Android系統中關於VSYNC的簡介

92HWComposer::HWComposer(

93 const sp&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

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

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

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(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(

274 const_cast(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(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)

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 > 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

152 const sp&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)

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(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

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}

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved