Android VSYNC详解
来源:互联网 发布:nginx获取http header 编辑:程序博客网 时间:2024/05/06 05:51
Android UI层的刷新界面数据和SurfaceFlinger将显示数据刷新到屏幕,都依赖VSYNC信号。
VSYNC信号来自LCD模块,先看一下SurfaceFlinger加载LCD模块生成VSYNC信号回调到SurfaceFlinger的过程。
void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); status_t err; Mutex::Autolock _l(mStateLock); .... // Initialize the H/W composer object. There may or may not be an // actual hardware composer underneath. mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this)); // First try to get an ES2 config err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT, &mEGLConfig); if (err != NO_ERROR) { // If ES2 fails, try ES1 err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES_BIT, &mEGLConfig); } if (err != NO_ERROR) { // still didn't work, probably because we're on the emulator... // try a simplified query ALOGW("no suitable EGLConfig found, trying a simpler query"); err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig); } if (err != NO_ERROR) { // this EGL is too lame for android LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); } .... // initialize our non-virtual displays for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) { DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i); // set-up the displays that are already connected if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) { // All non-virtual displays are currently considered secure. bool isSecure = true; createBuiltinDisplayLocked(type); wp<IBinder> token = mBuiltinDisplays[i]; sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc()); sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq); sp<DisplayDevice> hw = new DisplayDevice(this, type, allocateHwcDisplayId(type), isSecure, token, fbs, bq, mEGLConfig); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always // assume a connected display is unblanked. ALOGD("marking display %d as acquired/unblanked", i); hw->acquireScreen(); } mDisplays.add(token, hw); } } // make the GLContext current so that we can create textures when creating Layers // (which may happens before we render something) getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext); // start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); // set a fake vsync period if there is no HWComposer if (mHwc->initCheck() != NO_ERROR) { mPrimaryDispSync.setPeriod(16666667); } // initialize our drawing state mDrawingState = mCurrentState; // set initial conditions (e.g. unblank default device) initializeDisplays(); // start boot animation startBootAnim();}
在HWC的构造函数中会加载HWC模块
.... HWComposer::HWComposer( const sp<SurfaceFlinger>& flinger, EventHandler& handler) : mFlinger(flinger), mFbDev(0), mHwc(0), mNumDisplays(1), mCBContext(new cb_context), mEventHandler(handler), mDebugForceFakeVSync(false){.... // 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=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) { mAllocatedDisplayIDs.markBit(i); } if (mHwc) { ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER, (hwcApiVersion(mHwc) >> 24) & 0xff, (hwcApiVersion(mHwc) >> 16) & 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, 0, 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, 0); // 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 = 1; } } 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.width = mFbDev->width; disp.height = mFbDev->height; disp.format = mFbDev->format; disp.xdpi = mFbDev->xdpi; disp.ydpi = mFbDev->ydpi; if (disp.refresh == 0) { disp.refresh = nsecs_t(1e9 / mFbDev->fps); ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh); } if (disp.refresh == 0) { disp.refresh = nsecs_t(1e9 / 60.0); ALOGW("getting VSYNC period from thin air: %lld", mDisplayData[HWC_DISPLAY_PRIMARY].refresh); } } else if (mHwc) { // here we're guaranteed to have at least HWC 1.1 for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) { queryDisplayProperties(i); } } if (needVSyncThread) { // we don't have VSYNC support, we need to fake it mVSyncThread = new VSyncThread(*this); }} ....// Load and prepare the hardware composer module. Sets mHwc.void HWComposer::loadHwcModule(){ hw_module_t const* module; //Hardware??? module? ?????. if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) { ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID); return; } //?? ???? ?? ??? module? ?? HWComposer? ?????. 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; }} ....int hw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module){ int status; int i; const struct hw_module_t *hmi = NULL; char prop[PATH_MAX]; char path[PATH_MAX]; char name[PATH_MAX]; if (inst) snprintf(name, PATH_MAX, "%s.%s", class_id, inst); else strlcpy(name, class_id, PATH_MAX); /* * Here we rely on the fact that calling dlopen multiple times on * the same .so will simply increment a refcount (and not load * a new copy of the library). * We also assume that dlopen() is thread-safe. */ /* Loop through the configuration variants looking for a module */ for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) { if (i < HAL_VARIANT_KEYS_COUNT) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, prop); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH1, name, prop); if (access(path, R_OK) == 0) break; } else { snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH2, name); if (access(path, R_OK) == 0) break; snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LIBRARY_PATH1, name); if (access(path, R_OK) == 0) break; } } status = -ENOENT; if (i < HAL_VARIANT_KEYS_COUNT+1) { /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ status = load(class_id, path, module); } return status;} int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}/** * Load the file defined by the variant and if successful * return the dlopen handle and the hmi. * @return 0 = success, !0 = failure. */static int load(const char *id, const char *path, const struct hw_module_t **pHmi){ int status; void *handle; struct hw_module_t *hmi; /* * load the symbols resolving undefined symbols before * dlopen returns. Since RTLD_GLOBAL is not or'd in with * RTLD_NOW the external symbols will not be global */ handle = dlopen(path, RTLD_NOW); if (handle == NULL) { char const *err_str = dlerror(); ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown"); status = -EINVAL; goto done; } /* Get the address of the struct hal_module_info. */ const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym); if (hmi == NULL) { ALOGE("load: couldn't find symbol %s", sym); status = -EINVAL; goto done; } /* Check that the id matches */ if (strcmp(id, hmi->id) != 0) { ALOGE("load: id=%s != hmi->id=%s", id, hmi->id); status = -EINVAL; goto done; } hmi->dso = handle; /* success */ status = 0; done: if (status != 0) { hmi = NULL; if (handle != NULL) { dlclose(handle); handle = NULL; } } else { ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi; return status;}
以上dlsym()函数负责加载动态库。然后再通过hwc_open_1()函数调用module库中对应的open函数,也就是hwc_device_open()函数
static inline int hwc_open_1(const struct hw_module_t* module, hwc_composer_device_1_t** device) { return module->methods->open(module, HWC_HARDWARE_COMPOSER, (struct hw_device_t**)device);} static inline int hwc_close_1(hwc_composer_device_1_t* device) { return device->common.close(&device->common);}....static int hwc_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device){ int status = -EINVAL; if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { struct hwc_context_t *dev; dev = (hwc_context_t*)malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); //Initialize hwc context initContext(dev); //Setup HWC methods dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = HWC_DEVICE_API_VERSION_1_2; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = hwc_device_close; dev->device.prepare = hwc_prepare; dev->device.set = hwc_set; dev->device.eventControl = hwc_eventControl; dev->device.blank = hwc_blank; dev->device.query = hwc_query; dev->device.registerProcs = hwc_registerProcs; dev->device.dump = hwc_dump; dev->device.getDisplayConfigs = hwc_getDisplayConfigs; dev->device.getDisplayAttributes = hwc_getDisplayAttributes; *device = &dev->device.common; status = 0; } return status;}
然后通过回调函数调用到hwc_registerProcs函数注册vsync相关
/* * Save callback functions registered to HWC */static void hwc_registerProcs(struct hwc_composer_device_1* dev, hwc_procs_t const* procs){ ALOGI("%s", __FUNCTION__); hwc_context_t* ctx = (hwc_context_t*)(dev); if(!ctx) { ALOGE("%s: Invalid context", __FUNCTION__); return; } ctx->proc = procs; // Now that we have the functions needed, kick off // the uevent & vsync threads init_uevent_thread(ctx); init_vsync_thread(ctx);}void init_vsync_thread(hwc_context_t* ctx){ int ret; pthread_t vsync_thread; ALOGI("Initializing VSYNC Thread"); ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx); if (ret) { ALOGE("%s: failed to create %s: %s", __FUNCTION__, HWC_VSYNC_THREAD_NAME, strerror(ret)); }}static void *vsync_loop(void *param){ const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event"; const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event"; int dpy = HWC_DISPLAY_PRIMARY; hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param); char thread_name[64] = HWC_VSYNC_THREAD_NAME; prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0); setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY + android::PRIORITY_MORE_FAVORABLE); const int MAX_DATA = 64; static char vdata[MAX_DATA]; uint64_t cur_timestamp=0; ssize_t len = -1; int fd_timestamp = -1; int ret = 0; bool fb1_vsync = false; bool logvsync = false; char property[PROPERTY_VALUE_MAX]; if(property_get("debug.hwc.fakevsync", property, NULL) > 0) { if(atoi(property) == 1) ctx->vstate.fakevsync = true; } if(property_get("debug.hwc.logvsync", property, 0) > 0) { if(atoi(property) == 1) logvsync = true; } /* Currently read vsync timestamp from drivers e.g. VSYNC=41800875994 */ fd_timestamp = open(vsync_timestamp_fb0, O_RDONLY); if (fd_timestamp < 0) { // Make sure fb device is opened before starting this thread so this // never happens. ALOGE ("FATAL:%s:not able to open file:%s, %s", __FUNCTION__, (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0, strerror(errno)); ctx->vstate.fakevsync = true; } do { if (LIKELY(!ctx->vstate.fakevsync)) { len = pread(fd_timestamp, vdata, MAX_DATA, 0); if (len < 0) { // If the read was just interrupted - it is not a fatal error // In either case, just continue. if (errno != EAGAIN && errno != EINTR && errno != EBUSY) { ALOGE ("FATAL:%s:not able to read file:%s, %s", __FUNCTION__, vsync_timestamp_fb0, strerror(errno)); } continue; } // extract timestamp const char *str = vdata; if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) { cur_timestamp = strtoull(str + strlen("VSYNC="), NULL, 0); } } else { usleep(16666); cur_timestamp = systemTime(); } // send timestamp to HAL if(ctx->vstate.enable) { ALOGD_IF (logvsync, "%s: timestamp %llu sent to HWC for %s", __FUNCTION__, cur_timestamp, "fb0"); ctx->proc->vsync(ctx->proc, dpy, cur_timestamp); } } while (true); if(fd_timestamp >= 0) close (fd_timestamp); return NULL;}
在 /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp中设置vsync函数
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, 0, sizeof(mCBContext->procs.zero)); mHwc->registerProcs(mHwc, &mCBContext->procs); }void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp, int64_t timestamp) { cb_context* ctx = reinterpret_cast<cb_context*>( const_cast<hwc_procs_t*>(procs)); ctx->hwc->vsync(disp, timestamp);}void HWComposer::vsync(int disp, int64_t timestamp) { if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) { { Mutex::Autolock _l(mLock); // There have been reports of HWCs that signal several vsync events // with the same timestamp when turning the display off and on. This // is a bug in the HWC implementation, but filter the extra events // out here so they don't cause havoc downstream. if (timestamp == mLastHwVSync[disp]) { ALOGW("Ignoring duplicate VSYNC event from HWC (t=%lld)", timestamp); return; } mLastHwVSync[disp] = timestamp; } char tag[16]; snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp); ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); mEventHandler.onVSyncReceived(disp, timestamp); }}
这里的onVSyncReceived就是SurfaceFlinger对应的onVSyncReceived函数
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { 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); }} ....void SurfaceFlinger::enableHardwareVsync() { Mutex::Autolock _l(mHWVsyncLock); if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) { mPrimaryDispSync.beginResync(); //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true); mEventControlThread->setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; }}
在addResyncSample()函数中调用updateModel
bool DispSync::addResyncSample(nsecs_t timestamp) { Mutex::Autolock lock(mMutex); size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; mResyncSamples[idx] = timestamp; if (mNumResyncSamples < MAX_RESYNC_SAMPLES) { mNumResyncSamples++; } else { mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES; } updateModelLocked(); if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) { resetErrorLocked(); } if (kIgnorePresentFences) { // If we don't have the sync framework we will never have // addPresentFence called. This means we have no way to know whether // or not we're synchronized with the HW vsyncs, so we just request // that the HW vsync events be turned on whenever we need to generate // SW vsync events. return mThread->hasAnyEventListeners(); } return mPeriod == 0 || mError > kErrorThreshold;}void DispSync::updateModelLocked() { if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) { nsecs_t durationSum = 0; for (size_t i = 1; i < mNumResyncSamples; i++) { size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES; durationSum += mResyncSamples[idx] - mResyncSamples[prev]; } mPeriod = durationSum / (mNumResyncSamples - 1); double sampleAvgX = 0; double sampleAvgY = 0; double scale = 2.0 * M_PI / double(mPeriod); for (size_t i = 0; i < mNumResyncSamples; i++) { size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; nsecs_t sample = mResyncSamples[idx]; double samplePhase = double(sample % mPeriod) * scale; sampleAvgX += cos(samplePhase); sampleAvgY += sin(samplePhase); } sampleAvgX /= double(mNumResyncSamples); sampleAvgY /= double(mNumResyncSamples); mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale); if (mPhase < 0) { mPhase += mPeriod; } if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Period", mPeriod); ATRACE_INT64("DispSync:Phase", mPhase); } // Artificially inflate the period if requested. mPeriod += mPeriod * mRefreshSkipCount; mThread->updateModel(mPeriod, mPhase); }}void updateModel(nsecs_t period, nsecs_t phase) { Mutex::Autolock lock(mMutex); mPeriod = period; mPhase = phase; mCond.signal();}
然后在DispSync.cpp文件的threadLoop函数中在等待mCond信号完成。
virtual bool threadLoop() { status_t err; nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); nsecs_t nextEventTime = 0; while (true) { Vector<CallbackInvocation> callbackInvocations; nsecs_t targetTime = 0; { // Scope for lock Mutex::Autolock lock(mMutex); if (mStop) { return false; } if (mPeriod == 0) { err = mCond.wait(mMutex); if (err != NO_ERROR) { ALOGE("error waiting for new events: %s (%d)", strerror(-err), err); return false; } continue; } nextEventTime = computeNextEventTimeLocked(now); targetTime = nextEventTime; bool isWakeup = false; if (now < targetTime) { err = mCond.waitRelative(mMutex, targetTime - now); if (err == TIMED_OUT) { isWakeup = true; } else if (err != NO_ERROR) { ALOGE("error waiting for next event: %s (%d)", strerror(-err), err); return false; } } now = systemTime(SYSTEM_TIME_MONOTONIC); if (isWakeup) { mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64; if (mWakeupLatency > 500000) { // Don't correct by more than 500 us mWakeupLatency = 500000; } if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime); ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency); } } callbackInvocations = gatherCallbackInvocationsLocked(now); } if (callbackInvocations.size() > 0) { fireCallbackInvocations(callbackInvocations); } } return false; } void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) { for (size_t i = 0; i < callbacks.size(); i++) {//这里调用下面的代码段中初始化的两个DispSyncSource类对象的onDispSyncEvent回调函数 callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime); } }void SurfaceFlinger::init() { ... // start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app");//这个是VSYNC-app mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf");//这个是VSYNC-sf ...}
这样从fireCallbackInvocations()->SurfaceFlinger.cpp文件中DisSyncSource类的onDispSyncEvent()->EventThread.cpp的onVSyncEvent()
virtual void onDispSyncEvent(nsecs_t when) { sp<VSyncSource::Callback> callback; { Mutex::Autolock lock(mCallbackMutex); callback = mCallback; if (mTraceVsync) { mValue = (mValue + 1) % 2; ATRACE_INT(mVsyncEventLabel.string(), mValue);//这个就是可以在systrace里边看到的 } } if (callback != NULL) {// callback->onVSyncEvent(when); }}void EventThread::onVSyncEvent(nsecs_t timestamp) { Mutex::Autolock _l(mLock); mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = 0; mVSyncEvent[0].header.timestamp = timestamp; mVSyncEvent[0].vsync.count++; mCondition.broadcast();}
看到这里又有一个mCondition,EventThread的threadLoop函数也在等待这个条件。具体看EventThread里边的threadLoop()->waitEvent()函数.
bool EventThread::threadLoop() { DisplayEventReceiver::Event event; Vector< sp<EventThread::Connection> > signalConnections; signalConnections = waitForEvent(&event); // dispatch events to listeners... const size_t count = signalConnections.size(); for (size_t i=0 ; i<count ; i++) { const sp<Connection>& conn(signalConnections[i]); // now see if we still need to report this event 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 < 0) { // 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;}
waitEvent()函数里边,timstamp非0表示有vsync信号过来需要处理。然后再根据mDisplayEventConnections的大小来判断是否有client在等待vsync信号。
然后由此判断是否要使能vsync,或者根据timestamp判断是否等待目前的vsync处理完。最后返回一个signalConnections。
conn->postEvent()这个这里就是发vsync信号给对应的连接,目前android有surfaceflinger和Choreographoer两个在等待这个。
status_t EventThread::Connection::postEvent( const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR);}ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel, Event const* events, size_t count){ return BitTube::sendObjects(dataChannel, events, count);}
通过这里,最终调用到MessageQueue:cb_eventReceiver()
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) { MessageQueue* queue = reinterpret_cast<MessageQueue *>(data); return queue->eventReceiver(fd, events);}int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { ssize_t n; DisplayEventReceiver::Event buffer[8]; while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) { for (int i=0 ; i<n ; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {#if INVALIDATE_ON_VSYNC mHandler->dispatchInvalidate();#else mHandler->dispatchRefresh();#endif break; } } } return 1;}
然后就是通过MessageQueue传递给SurfaceFlinger的onMessageReceived()函数
void MessageQueue::Handler::dispatchInvalidate() { if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) { mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); }}void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: android_atomic_and(~eventMaskInvalidate, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; case REFRESH: android_atomic_and(~eventMaskRefresh, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; case TRANSACTION: android_atomic_and(~eventMaskTransaction, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; }}void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { case MessageQueue::TRANSACTION: { handleMessageTransaction(); break; } case MessageQueue::INVALIDATE: { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); 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(); } break; } case MessageQueue::REFRESH: { handleMessageRefresh(); break; } }}
然后就是通过MessageQueue传递给SurfaceFlinger的onMessageReceived()函数
2. Choregrapher的部分
Choregrapher通过DisplayEventReceiver和NativeDisplayEventReceiver创建connection的过程可以参考http://blog.csdn.net/houliang120/article/details/50958212
最后反正就是从android_view_DisplayEventReceiver.cpp文件的handleEvent()->dispatchVsync()最终同步调用到FrameDisplayEventReceiver的onVsync()然后又异步调用到FrameDisplayEventReceiver的run函数。
看下面的onVsync函数中Message.obtain()函数传了this为参数,所以msg有了callback。在Handler.java的dispatchMessage()函数中可以看到,有了callback之后,就直接调用穿进去的runnable类型的run函数了,也就是FrameDisplayEventReceiver类型的run()函数
0 0
- Android VSYNC详解
- Android Vsync详解
- Android 5.1 SurfaceFlinger VSYNC详解
- android vsync
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(3) VSYNC的处理
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android 4.4 Graphic系统详解(2) VSYNC的生成
- Android显示系统Vsync
- android Vsync workflow
- 【Android】Android SurfaceFlinger之VSync
- Myeclipse SVN插件安装以及使用
- static,你还敢用吗?
- Google 开源项目风格指南_6_命名约定
- SpringMVC初始化参数绑定--日期格式
- android studio preview 出现 Rendering Problems的解决方法
- Android VSYNC详解
- 通过前端页面传递数据到spring mvc控制器发生乱码的解决办法
- Spring MVC之视图解析
- Mysql存储过程从0开始(上)
- javadoc文档生成
- 国际化文件整理
- MacBook不能开机案例一则
- JS调用Android、Ios原生控件_优就业
- 普通 Java 项目转换为 Maven 项目