zoukankan      html  css  js  c++  java
  • 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. ......  


  • 相关阅读:
    《Linux/Unix设计思想》随笔 ——Linux/Unix哲学概述
    C99 inline关键字
    关于C++内存对齐
    HLSL中constant variables的packing规则
    全局照明算法基础——从辐射亮度到渲染方程
    透视投影矩阵推导
    基于光线追踪的渲染中景深(Depth of field)效果的实现
    直线的光栅化算法
    透视投影后的线性插值校正
    linux内核编译与开发
  • 原文地址:https://www.cnblogs.com/ztguang/p/12645201.html
Copyright © 2011-2022 走看看