1. 程式人生 > >Android顯示系統中VSYNC簡介

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。