Android6.0 图像合成过程详解(二) doComposition函数


http://blog.csdn.net/kc58236582/article/details/52868973


上篇博客分析到setUpHWComposer函数,这里我们继续分析图像合成的过程从doComposition函数开始,以及在这过程中解答一些上篇博客提出的疑问。


一、doComposition合成图层

doComposition这个函数就是合成所有层的图像

  1. void SurfaceFlinger::doComposition() {  
  2.     ATRACE_CALL();  
  3.     const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);  
  4.     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {  
  5.         const sp<DisplayDevice>& hw(mDisplays[dpy]);  
  6.         if (hw->isDisplayOn()) {  
  7.             // transform the dirty region into this screen's coordinate space  
  8.             const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));  
  9.   
  10.             // repaint the framebuffer (if needed)  
  11.             doDisplayComposition(hw, dirtyRegion);  
  12.   
  13.             hw->dirtyRegion.clear();  
  14.             hw->flip(hw->swapRegion);  
  15.             hw->swapRegion.clear();  
  16.         }  
  17.         // inform the h/w that we're done compositing  
  18.         hw->compositionComplete();  
  19.     }  
  20.     postFramebuffer();  
  21. }  

上面函数遍历所有的DisplayDevice然后调用doDisplayComposition函数。然后我们再看看doDisplayComposition函数

  1. void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,  
  2.         const Region& inDirtyRegion)  
  3. {  
  4.     bool isHwcDisplay = hw->getHwcDisplayId() >= 0;  
  5.     if (!isHwcDisplay && inDirtyRegion.isEmpty()) {  
  6.         return;  
  7.     }  
  8.   
  9.     Region dirtyRegion(inDirtyRegion);  
  10.   
  11.     //swapRegion设置为需要更新的区域  
  12.     hw->swapRegion.orSelf(dirtyRegion);  
  13.   
  14.     uint32_t flags = hw->getFlags();//获得显示设备支持的更新方式标志  
  15.     if (flags & DisplayDevice::SWAP_RECTANGLE) {//支持矩阵更新          
  16.         dirtyRegion.set(hw->swapRegion.bounds());  
  17.     } else {  
  18.         if (flags & DisplayDevice::PARTIAL_UPDATES) {//支持部分更新  
  19.             dirtyRegion.set(hw->swapRegion.bounds());  
  20.         } else {  
  21.             //将更新区域调整为整个窗口大小  
  22.             dirtyRegion.set(hw->bounds());  
  23.             hw->swapRegion = dirtyRegion;  
  24.         }  
  25.     }  
  26.   
  27.     if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {  
  28.         if (!doComposeSurfaces(hw, dirtyRegion)) return;//合成  
  29.     } else {  
  30.         RenderEngine& engine(getRenderEngine());  
  31.         mat4 colorMatrix = mColorMatrix;  
  32.         if (mDaltonize) {  
  33.             colorMatrix = colorMatrix * mDaltonizer();  
  34.         }  
  35.         mat4 oldMatrix = engine.setupColorTransform(colorMatrix);  
  36.         doComposeSurfaces(hw, dirtyRegion);//合成  
  37.         engine.setupColorTransform(oldMatrix);  
  38.     }  
  39.   
  40.     // update the swap region and clear the dirty region  
  41.     hw->swapRegion.orSelf(dirtyRegion);  
  42.   
  43.     // swap buffers (presentation)  
  44.     hw->swapBuffers(getHwComposer());//使用egl将egl中的合成好的图像,输出到DisplayDevice的mSurface中  
  45. }  

这个函数设置下需要更新的区域,后面调用doComposeSurfaces函数来合成图层,调用完doComposeSurfaces函数后,如果需要egl合成图像话,在这个函数中合成好。而最后调用swapBuffers只是将egl合成好的图像输出到DisplayDevice的mSurface中。

我们再来看看doComposeSurfaces函数,我们先来看一开始的代码,先判断是否有egl合成,然后再看是否有hwc合成(硬件合成)

  1. bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)  
  2. {  
  3.     RenderEngine& engine(getRenderEngine());  
  4.     const int32_t id = hw->getHwcDisplayId();  
  5.     HWComposer& hwc(getHwComposer());  
  6.     HWComposer::LayerListIterator cur = hwc.begin(id);  
  7.     const HWComposer::LayerListIterator end = hwc.end(id);  
  8.   
  9.     bool hasGlesComposition = hwc.hasGlesComposition(id);  
  10.     if (hasGlesComposition) {//是否有egl合成  
  11.         if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {  
  12.             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",  
  13.                   hw->getDisplayName().string());  
  14.             eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);  
  15.             if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {  
  16.               ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");  
  17.             }  
  18.             return false;  
  19.         }  
  20.   
  21.         // Never touch the framebuffer if we don't have any framebuffer layers  
  22.         const bool hasHwcComposition = hwc.hasHwcComposition(id);  
  23.         if (hasHwcComposition) {//是否有hwc合成  
  24.             // when using overlays, we assume a fully transparent framebuffer  
  25.             // NOTE: we could reduce how much we need to clear, for instance  
  26.             // remove where there are opaque FB layers. however, on some  
  27.             // GPUs doing a "clean slate" clear might be more efficient.  
  28.             // We'll revisit later if needed.  
  29.             engine.clearWithColor(0, 0, 0, 0);  
  30.         } else {  
  31.             // we start with the whole screen area  
  32.             const Region bounds(hw->getBounds());  
  33.   
  34.             // we remove the scissor part  
  35.             // we're left with the letterbox region  
  36.             // (common case is that letterbox ends-up being empty)  
  37.             const Region letterbox(bounds.subtract(hw->getScissor()));  
  38.   
  39.             // compute the area to clear  
  40.             Region region(hw->undefinedRegion.merge(letterbox));  
  41.   
  42.             // but limit it to the dirty region  
  43.             region.andSelf(dirty);  
  44.   
  45.             // screen is already cleared here  
  46.             if (!region.isEmpty()) {  
  47.                 // can happen with SurfaceView  
  48.                 drawWormhole(hw, region);  
  49.             }  
  50.         }  
  51.   
  52.         if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {  
  53.             // just to be on the safe side, we don't set the  
  54.             // scissor on the main display. It should never be needed  
  55.             // anyways (though in theory it could since the API allows it).  
  56.             const Rect& bounds(hw->getBounds());  
  57.             const Rect& scissor(hw->getScissor());  
  58.             if (scissor != bounds) {  
  59.                 // scissor doesn't match the screen's dimensions, so we  
  60.                 // need to clear everything outside of it and enable  
  61.                 // the GL scissor so we don't draw anything where we shouldn't  
  62.   
  63.                 // enable scissor for this frame  
  64.                 const uint32_t height = hw->getHeight();  
  65.                 engine.setScissor(scissor.left, height - scissor.bottom,  
  66.                         scissor.getWidth(), scissor.getHeight());  
  67.             }  
  68.         }  
  69.     }  
  70. ......  

我们来看hasGlesComposition函数和hasHwcComposition函数,就是看其对应的DisplayData中是否有hasFbComp和hasOvComp。

  1. bool HWComposer::hasGlesComposition(int32_t id) const {  
  2.     if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))  
  3.         return true;  
  4.     return mDisplayData[id].hasFbComp;  
  5. }  
  1. bool HWComposer::hasHwcComposition(int32_t id) const {  
  2.     if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))  
  3.         return false;  
  4.     return mDisplayData[id].hasOvComp;  
  5. }  
而这两个值是在prepare中调用Hwc的prepare函数之后赋值的
  1. status_t HWComposer::prepare() {  
  2.    ......  
  3.    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);  
  4.     ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));  
  5.   
  6.     if (err == NO_ERROR) {  
  7.         // here we're just making sure that "skip" layers are set  
  8.         // to HWC_FRAMEBUFFER and we're also counting how many layers  
  9.         // we have of each type.  
  10.         //  
  11.         // If there are no window layers, we treat the display has having FB  
  12.         // composition, because SurfaceFlinger will use GLES to draw the  
  13.         // wormhole region.  
  14.         for (size_t i=0 ; i<mNumDisplays ; i++) {  
  15.             DisplayData& disp(mDisplayData[i]);  
  16.             disp.hasFbComp = false;  
  17.             disp.hasOvComp = false;  
  18.             if (disp.list) {  
  19.                 for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {  
  20.                     hwc_layer_1_t& l = disp.list->hwLayers[i];  
  21.   
  22.                     //ALOGD("prepare: %d, type=%d, handle=%p",  
  23.                     //        i, l.compositionType, l.handle);  
  24.   
  25.                     if (l.flags & HWC_SKIP_LAYER) {  
  26.                         l.compositionType = HWC_FRAMEBUFFER;  
  27.                     }  
  28.                     if (l.compositionType == HWC_FRAMEBUFFER) {  
  29.                         disp.hasFbComp = true;//只要有一个layer是HWC_FRAMEBUFFER  
  30.                     }  
  31.                     if (l.compositionType == HWC_OVERLAY) {  
  32.                         disp.hasOvComp = true;//有一个layer是HWC_OVERLAY  
  33.                     }  
  34.                     if (l.compositionType == HWC_CURSOR_OVERLAY) {  
  35.                         disp.hasOvComp = true;//有一个layer是HWC_CURSOR_OVERLAY  
  36.                     }  
  37.                 }  
  38.                 if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {//layer的数量 有framebufferTarget为1 没有为0  
  39.                     disp.hasFbComp = true;  
  40.                 }  
  41.             } else {  
  42.                 disp.hasFbComp = true;//没有list  
  43.             }  
  44.         }  
  45.     }  
  46.     return (status_t)err;  
  47. }  

我们继续看doComposeSurfaces函数,下面这个函数当cur!=end代表起码有两个以上图层,然后遍历图层,当layer是HWC_FRAMEBUFFER代表是需要egl合成的,而HWC_FRAMEBUFFER_TARGET是egl合成后使用的直接就跳了,HWC_CURSOR_OVERLAY和HWC_OVERLAY是用HWC模块(硬件合成)的,也就不用调用Layer的draw方法。而如果图层只要1个或者没有,那么直接使用egl合成。

  1.     HWComposer::LayerListIterator cur = hwc.begin(id);  
  2.     const HWComposer::LayerListIterator end = hwc.end(id);  
  3.     ......  
  4.   
  5.     const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());  
  6.     const size_t count = layers.size();  
  7.     const Transform& tr = hw->getTransform();  
  8.     if (cur != end) { //代表起码有两个以上图层  
  9.         // we're using h/w composer  
  10.         for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {//遍历图层  
  11.             const sp<Layer>& layer(layers[i]);  
  12.             const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));  
  13.             if (!clip.isEmpty()) {  
  14.                 switch (cur->getCompositionType()) {  
  15.                     case HWC_CURSOR_OVERLAY:  
  16.                     case HWC_OVERLAY: {  
  17.                         const Layer::State& state(layer->getDrawingState());  
  18.                         if ((cur->getHints() & HWC_HINT_CLEAR_FB)  
  19.                                 && i  
  20.                                 && layer->isOpaque(state) && (state.alpha == 0xFF)  
  21.                                 && hasGlesComposition) {  
  22.                             // never clear the very first layer since we're  
  23.                             // guaranteed the FB is already cleared  
  24.                             layer->clearWithOpenGL(hw, clip);  
  25.                         }  
  26.                         break;  
  27.                     }  
  28.                     case HWC_FRAMEBUFFER: {  
  29.                         layer->draw(hw, clip);//只有是HWC_FRAMEBUFFER才会调用Layer的draw合成  
  30.                         break;  
  31.                     }  
  32.                     case HWC_FRAMEBUFFER_TARGET: {  
  33.                         // this should not happen as the iterator shouldn't  
  34.                         // let us get there.  
  35.                         ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);  
  36.                         break;  
  37.                     }  
  38.                 }  
  39.             }  
  40.             layer->setAcquireFence(hw, *cur);  
  41.         }  
  42.     } else {  
  43.         // we're not using h/w composer  
  44.         for (size_t i=0 ; i<count ; ++i) {//只有一个或者没有图层  就直接使用Layer的draw合成  
  45.             const sp<Layer>& layer(layers[i]);  
  46.             const Region clip(dirty.intersect(  
  47.                     tr.transform(layer->visibleRegion)));  
  48.             if (!clip.isEmpty()) {  
  49.                 layer->draw(hw, clip);  
  50.             }  
  51.         }  
  52.     }  
  53.   
  54.     // disable scissor at the end of the frame  
  55.     engine.disableScissor();  
  56.     return true;  
  57. }  

Layer的draw我们就不看了主要是使用egl合成纹理,但是有一点疑问,我们从来没有把layer中的mActiveBuffer放到egl中去,那么egl又是怎么合成各个layer的呢,我想肯定客户进程在绘制各个layer的时候,也是用egl绘制的,所有后面合成的时候egl有各个layer的buffer。


后面我们再来看下DisplayDevice::swapBuffers函数,是使用eglSwapBuffers来把egl合成的数据放到mSurface中去。

  1. void DisplayDevice::swapBuffers(HWComposer& hwc) const {  
  2.     // We need to call eglSwapBuffers() if:  
  3.     //  (1) we don't have a hardware composer, or  
  4.     //  (2) we did GLES composition this frame, and either  
  5.     //    (a) we have framebuffer target support (not present on legacy  
  6.     //        devices, where HWComposer::commit() handles things); or  
  7.     //    (b) this is a virtual display  
  8.     if (hwc.initCheck() != NO_ERROR ||  
  9.             (hwc.hasGlesComposition(mHwcDisplayId) &&  
  10.              (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {  
  11.         EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);  
  12.         if (!success) {  
  13.             EGLint error = eglGetError();  
  14.             if (error == EGL_CONTEXT_LOST ||  
  15.                     mType == DisplayDevice::DISPLAY_PRIMARY) {  
  16.                 LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",  
  17.                         mDisplay, mSurface, error);  
  18.             } else {  
  19.                 ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",  
  20.                         mDisplay, mSurface, error);  
  21.             }  
  22.         }  
  23.     }  
  24.     else if(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL)  
  25.     {  
  26.         EGLBoolean success = eglSwapBuffersVIV(mDisplay, mSurface);  
  27.         if (!success) {  
  28.             EGLint error = eglGetError();  
  29.             ALOGE("eglSwapBuffersVIV(%p, %p) failed with 0x%08x",  
  30.                         mDisplay, mSurface, error);  
  31.         }  
  32.     }  
  33.   
  34.     status_t result = mDisplaySurface->advanceFrame();  
  35.     if (result != NO_ERROR) {  
  36.         ALOGE("[%s] failed pushing new frame to HWC: %d",  
  37.                 mDisplayName.string(), result);  
  38.     }  
  39. }  


二、FramebufferSurface收到egl合成数据

之前分析DisplayDevice时候,还分析了FramebufferSurface,我们这里再来看下。

在SurfaceFlinger.cpp中的init函数,在创建DisplayDevice之前,我们先调用createBufferQueue来创建了一个buffer的生产者和消费者,然后把消费者放入了FramebufferSurface,生产者放入了DisplayDevice中。

  1. sp<IGraphicBufferProducer> producer;  
  2.   sp<IGraphicBufferConsumer> consumer;  
  3.   BufferQueue::createBufferQueue(&producer, &consumer,  
  4.           new GraphicBufferAlloc());  
  5.   
  6.   sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,  
  7.           consumer);  
  8.   int32_t hwcId = allocateHwcDisplayId(type);  
  9.   sp<DisplayDevice> hw = new DisplayDevice(this,  
  10.           type, hwcId, mHwc->getFormat(hwcId), isSecure, token,  
  11.           fbs, producer,  
  12.           mRenderEngine->getEGLConfig());  

我们先来看生产者,下面是DisplayDevice的构造函数,生产者作为参数直接新建了一个Surface,然后把这个Surface作为参数调用eglCreateWindowSurface返回的就是mSurface,之前我们分析最后egl合成的数据时调用eglSwapBuffers并且把数据放到mSurface,这样最后肯定就到消费者(FramebufferSurface)去了。

  1. mNativeWindow = new Surface(producer, false);  
  2. ANativeWindow* const window = mNativeWindow.get();  
  3.   
  4. /* 
  5.  * Create our display's surface 
  6.  */  
  7.   
  8. EGLSurface surface;  
  9. EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);  
  10. if (config == EGL_NO_CONFIG) {  
  11.     config = RenderEngine::chooseEglConfig(display, format);  
  12. }  
  13. surface = eglCreateWindowSurface(display, config, window, NULL);  

最后到消费者那端的onFrameAvailable,也就是FramebufferSurface的onFrameAvailable中,我们现在来分析下这个过程,也就解答了一个onFrameAvailable的疑惑。


FramebufferSurface的父类是ConsumerBase类,我们来看其构造函数。先是构造了mConsumer,这里其实就是BufferQueueConsumer类,后面调用了其consumerConnect方法。

  1. ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :  
  2.         mAbandoned(false),  
  3.         mConsumer(bufferQueue) {  
  4.     mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());  
  5.   
  6.     wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);  
  7.     sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);  
  8.   
  9.     status_t err = mConsumer->consumerConnect(proxy, controlledByApp);  
  10.     if (err != NO_ERROR) {  
  11.         CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",  
  12.                 strerror(-err), err);  
  13.     } else {  
  14.         mConsumer->setConsumerName(mName);  
  15.     }  
  16. }  

我们来看下BufferQueueConsumer类的consumerConnect方法,就是调用了connect方法。

  1. virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,  
  2.         bool controlledByApp) {  
  3.     return connect(consumer, controlledByApp);  
  4. }  

这个方法中将mCore->mConsumerListener = consumerListener,这个mCore就是BufferQueueCore类。我们再从ConsumerBase的构造函数看这个consumerListener参数其实就是FrameBufferSurface对象本身。

  1. status_t BufferQueueConsumer::connect(  
  2.         const sp<IConsumerListener>& consumerListener, bool controlledByApp) {  
  3.     ATRACE_CALL();  
  4.   
  5.     if (consumerListener == NULL) {  
  6.         BQ_LOGE("connect(C): consumerListener may not be NULL");  
  7.         return BAD_VALUE;  
  8.     }  
  9.   
  10.     BQ_LOGV("connect(C): controlledByApp=%s",  
  11.             controlledByApp ? "true" : "false");  
  12.   
  13.     Mutex::Autolock lock(mCore->mMutex);  
  14.   
  15.     if (mCore->mIsAbandoned) {  
  16.         BQ_LOGE("connect(C): BufferQueue has been abandoned");  
  17.         return NO_INIT;  
  18.     }  
  19.   
  20.     mCore->mConsumerListener = consumerListener;//设置回调  
  21.     mCore->mConsumerControlledByApp = controlledByApp;  
  22.   
  23.     return NO_ERROR;  
  24. }  


我们再看BufferQueueProducer::queueBuffer函数,这个函数应该是生产者已经使用好buffer了,这个使用会调用如下代码这个listener就是BufferQueueCore的mConsumerListener,传输的数据时BufferItem。再传之前把BufferItem的mGraphicBuffer清了,因为消费者可以自己获取buffer,不用通过BufferItem传。

  1. item.mGraphicBuffer.clear();  
  2. item.mSlot = BufferItem::INVALID_BUFFER_SLOT;  
  3.   
  4. // Call back without the main BufferQueue lock held, but with the callback  
  5. // lock held so we can ensure that callbacks occur in order  
  6. {  
  7.     Mutex::Autolock lock(mCallbackMutex);  
  8.     while (callbackTicket != mCurrentCallbackTicket) {  
  9.         mCallbackCondition.wait(mCallbackMutex);  
  10.     }  
  11.   
  12.     if (frameAvailableListener != NULL) {  
  13.         frameAvailableListener->onFrameAvailable(item);  
  14.     } else if (frameReplacedListener != NULL) {  
  15.         frameReplacedListener->onFrameReplaced(item);  
  16.     }  
  17.   
  18.     ++mCurrentCallbackTicket;  
  19.     mCallbackCondition.broadcast();  
  20. }  

这样就要FramebufferSurface的onFrameAvailable函数中去了,我们来看下这个函数。

  1. void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {  
  2.     sp<GraphicBuffer> buf;  
  3.     sp<Fence> acquireFence;  
  4.     status_t err = nextBuffer(buf, acquireFence);  
  5.     if (err != NO_ERROR) {  
  6.         ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",  
  7.                 strerror(-err), err);  
  8.         return;  
  9.     }  
  10.     err = mHwc.fbPost(mDisplayType, acquireFence, buf);  
  11.     if (err != NO_ERROR) {  
  12.         ALOGE("error posting framebuffer: %d", err);  
  13.     }  
  14. }  
这个函数先用nextBuffer获取数据,然后调用了HWComposer的fbPost函数。我们先来看下nextBuffer函数,这个函数主要通过acquireBufferLocked获取BufferItem,其中的mBuf就是buffer了。
  1. status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {  
  2.     Mutex::Autolock lock(mMutex);  
  3.   
  4.     BufferItem item;  
  5.     status_t err = acquireBufferLocked(&item, 0);  
  6.     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {  
  7.         outBuffer = mCurrentBuffer;  
  8.         return NO_ERROR;  
  9.     } else if (err != NO_ERROR) {  
  10.         ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);  
  11.         return err;  
  12.     }  
  13.   
  14.     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&  
  15.         item.mBuf != mCurrentBufferSlot) {  
  16.         // Release the previous buffer.  
  17.         err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,  
  18.                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);  
  19.         if (err < NO_ERROR) {  
  20.             ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);  
  21.             return err;  
  22.         }  
  23.     }  
  24.     mCurrentBufferSlot = item.mBuf;  
  25.     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;  
  26.     outFence = item.mFence;  
  27.     outBuffer = mCurrentBuffer;  
  28.     return NO_ERROR;  
  29. }  
而这个acquireBufferLocked还是用mConsumer的acquireBuffer来获取BufferItem。mConsumer就是BufferQueueConsumer类。
  1. status_t ConsumerBase::acquireBufferLocked(BufferItem *item,  
  2.         nsecs_t presentWhen, uint64_t maxFrameNumber) {  
  3.     status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);  
  4.     if (err != NO_ERROR) {  
  5.         return err;  
  6.     }  
  7.   
  8.     if (item->mGraphicBuffer != NULL) {  
  9.         mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;  
  10.     }  
  11.   
  12.     mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;  
  13.     mSlots[item->mBuf].mFence = item->mFence;  
  14.   
  15.     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,  
  16.             item->mBuf, item->mFrameNumber);  
  17.   
  18.     return OK;  
  19. }  

回到FramebufferSurface的onFrameAvailable中这样获取了buffer之后,调用了HWComposer的fbPost方法。


三、egl合成数据在HWComposer的处理

继上面调用fbPost方法,我们来看下,这里是调用了setFramebufferTarget方法。

  1. int HWComposer::fbPost(int32_t id,  
  2.         const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {  
  3.     if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  4.         return setFramebufferTarget(id, acquireFence, buffer);  
  5.     } else {  
  6.         acquireFence->waitForever("HWComposer::fbPost");  
  7.         return mFbDev->post(mFbDev, buffer->handle);  
  8.     }  
  9. }  

我们来看下setFramebufferTarget方法,这里就是把该设备的DisplayData数据中的framebufferTarget填充,主要是其handle数据,这里就是egl合成好的数据buffer。

也就是最终egl合成好的数据放在DisplayData的framebufferTarget变量的handle中。

  1. status_t HWComposer::setFramebufferTarget(int32_t id,  
  2.         const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {  
  3.     if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {  
  4.         return BAD_INDEX;  
  5.     }  
  6.     DisplayData& disp(mDisplayData[id]);  
  7.     if (!disp.framebufferTarget) {  
  8.         // this should never happen, but apparently eglCreateWindowSurface()  
  9.         // triggers a Surface::queueBuffer()  on some  
  10.         // devices (!?) -- log and ignore.  
  11.         ALOGE("HWComposer: framebufferTarget is null");  
  12.         return NO_ERROR;  
  13.     }  
  14.   
  15.     int acquireFenceFd = -1;  
  16.     if (acquireFence->isValid()) {  
  17.         acquireFenceFd = acquireFence->dup();  
  18.     }  
  19.   
  20.     // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);  
  21.     disp.fbTargetHandle = buf->handle;//egl合成好的数据  
  22.     disp.framebufferTarget->handle = disp.fbTargetHandle;//egl合成好的数据,最终是放在这里  
  23.     disp.framebufferTarget->acquireFenceFd = acquireFenceFd;  
  24.     return NO_ERROR;  
  25. }  



四、硬件模块合成

这样就剩最后一步了,把不管是普通layer的数据,还是egl合成好的数据发送到硬件模块合成了,最后就到显示设备了。

继第一节分析的doComposition函数最后会调用postFramebuffer函数,我们再来分析下这个函数,这个函数主要是调用了HWComposer的commit函数。

  1. void SurfaceFlinger::postFramebuffer()  
  2. {  
  3.     ATRACE_CALL();  
  4.   
  5.     const nsecs_t now = systemTime();  
  6.     mDebugInSwapBuffers = now;  
  7.   
  8.     HWComposer& hwc(getHwComposer());  
  9.     if (hwc.initCheck() == NO_ERROR) {  
  10.         if (!hwc.supportsFramebufferTarget()) {  
  11.             // EGL spec says:  
  12.             //   "surface must be bound to the calling thread's current context,  
  13.             //    for the current rendering API."  
  14.             getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);  
  15.         }  
  16.         hwc.commit();  
  17.     }  
  18. ......  
我们来看下HWComposer的commit函数,这个函数就是先设置了egl的那个设备的surface和display,然后处理虚拟设备的outbuf等,最后调用了硬件模块合成到显示设备上。
  1. status_t HWComposer::commit() {  
  2.     int err = NO_ERROR;  
  3.     if (mHwc) {  
  4.         if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  5.             // On version 1.0, the OpenGL ES target surface is communicated  
  6.             // by the (dpy, sur) fields and we are guaranteed to have only  
  7.             // a single display.  
  8.             mLists[0]->dpy = eglGetCurrentDisplay();//设置下egl相关变量  
  9.             mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);  
  10.         }  
  11.   
  12.         for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {  
  13.             DisplayData& disp(mDisplayData[i]);  
  14.             if (disp.outbufHandle) {//只有虚拟设备需要设置outbuf  
  15.                 mLists[i]->outbuf = disp.outbufHandle;  
  16.                 mLists[i]->outbufAcquireFenceFd =  
  17.                         disp.outbufAcquireFence->dup();  
  18.             }  
  19.         }  
  20.   
  21.         err = mHwc->set(mHwc, mNumDisplays, mLists);//调用硬件模块合成  
  22. ......  


posted @ 2016-11-27 08:16  张同光  阅读(480)  评论(0编辑  收藏  举报