{
Mutex::Autolock lock(mCallbackMutex);
while (callbackTicket != mCurrentCallbackTicket) { mCallbackCondition.wait(mCallbackMutex); }
if (frameAvailableListener != NULL) {
frameAvailableListener->onFrameAvailable(item); } else if (frameReplacedListener != NULL) {
frameReplacedListener->onFrameReplaced(item); }
++mCurrentCallbackTicket;
mCallbackCondition.broadcast(); }
这样就要FramebufferSurface的onFrameAvailable函数中去了,我们来看下这个函数。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片
void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) { sp
status_t err = nextBuffer(buf, acquireFence); if (err != NO_ERROR) {
ALOGE(\ strerror(-err), err); return; }
err = mHwc.fbPost(mDisplayType, acquireFence, buf); if (err != NO_ERROR) {
ALOGE(\ } }
这个函数先用nextBuffer获取数据,然后调用了HWComposer的fbPost函数。我们先来看下nextBuffer函数,这个函数主要通过acquireBufferLocked获取BufferItem,其中的mBuf就是buffer了。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
status_t FramebufferSurface::nextBuffer(sp
Mutex::Autolock lock(mMutex);
BufferItem item;
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) { outBuffer = mCurrentBuffer; return NO_ERROR;
} else if (err != NO_ERROR) {
ALOGE(\ return err; }
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT && item.mBuf != mCurrentBufferSlot) {
// Release the prwww.sm136.comevious buffer.
err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); if (err < NO_ERROR) {
ALOGE(\ return err; } }
mCurrentBufferSlot = item.mBuf;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; outFence = item.mFence; outBuffer = mCurrentBuffer; return NO_ERROR; }
而这个acquireBufferLocked还是用mConsumer的acquireBuffer来获取BufferItem。mConsumer就是BufferQueueConsumer类。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 status_t ConsumerBase::acquireBufferLocked(BufferItem *item, nsecs_t presentWhen, uint64_t maxFrameNumber) {
status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber); if (err != NO_ERROR) { return err; }
if (item->mGraphicBuffer != NULL) {
mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer; }
mSlots[item->mBuf].mFrameNumber = item->mFrameNumber; mSlots[item->mBuf].mFence = item->mFence;
CB_LOGV(\ item->mBuf, item->mFrameNumber);
return OK; }
回到FramebufferSurface的onFrameAvailable中这样获取了buffer之后,调用了HWComposer的fbPost方法。
三、egl合成数据在HWComposer的处理
继上面调用fbPost方法,我们来看下,这里是调用了setFramebufferTarget方法。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 int HWComposer::fbPost(int32_t id,
const sp
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { return setFramebufferTarget(id, acquireFence, buffer); } else {
acquireFence->waitForever(\ return mFbDev->post(mFbDev, buffer->handle); } }
我们来看下setFramebufferTarget方法,这里就是把该设备的DisplayData数据中的framebufferTarget填充,主要是其handle数据,这里就是egl合成好的数据buffer。 也就是最终egl合成好的数据放在DisplayData的framebufferTarget变量的handle中。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片
status_t HWComposer::setFramebufferTarget(iwww.tt951.comnt32_t id,
const sp
DisplayData& disp(mDisplayData[id]); if (!disp.framebufferTarget) {
// this should never happen, but apparently eglCreateWindowSurface() // triggers a Surface::queueBuffer() on some // devices (!?) -- log and ignore.
ALOGE(\ return NO_ERROR; }
int acquireFenceFd = -1;
if (acquireFence->isValid()) {
acquireFenceFd = acquireFence->dup(); }
// ALOGD(\ disp.fbTargetHandle = buf->handle;//egl合成好的数据
disp.framebufferTarget->handle = disp.fbTargetHandle;//egl合成好的数据,最终是放在这里
disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
return NO_ERROR; }
四、硬件模块合成
这样就剩最后一步了,把不管是普通layer的数据,还是egl合成好的数据发送到硬件模块合成了,最后就到显示设备了。
继第一节分析的doComposition函数最后会调用postFramebuffer函数,我们再来分析下这个函数,这个函数主要是调用了HWComposer的commit函数。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 void SurfaceFlinger::postFramebuffer() {
ATRACE_CALL();
const nsecs_t now = systemTime(); mDebugInSwapBuffers = now;
HWComposer& hwc(getHwComposer()); if (hwc.initCheck() == NO_ERROR) {
if (!hwc.supportsFramebufferTarget()) { // EGL spec says:
// \ // for the current rendering API.\
getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext); }
hwc.commit(); } ......
我们来看下HWComposer的commit函数,这个函数就是先设置了egl的那个设备的surface和display,然后处理虚拟设备的outbuf等,最后调用了硬件模块合成到显示设备上。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 status_t HWComposer::commit() { int err = NO_ERROR; if (mHwc) {
if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // On version 1.0, the OpenGL ES target surface is communicated // by the (dpy, sur) fields and we are guaranteed to have only // a single dinc630.comsplay.
mLists[0]->dpy = eglGetCurrentDisplay();//设置下egl相关变量 mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW); }
for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i if (disp.outbufHandle) {//只有虚拟设备需要设置outbuf mLists[i]->outbuf = disp.outbufHandle; mLists[i]->outbufAcquireFenceFd = disp.outbufAcquireFence->dup(); } } err = mHwc->set(mHwc, mNumDisplays, mLists);//调用硬件模块合成 ......