SurfaceFlinger中图像合成流程

android中图像的显示是通过HWComposer合成的,(不支持硬件composer的不考虑,现在基本都支持)。 硬件支持合成就是你输入多路视频,图像信号,出来一路合成好的数据。
硬件合成只支持有限的记录信号,所有如何存在太多的信号,需要先通过软件进行合成,surfaceflinger是通过gpu合成的。

SurfaceFlinger::init(){
   //包装了硬件合成的硬件抽象层
  mHwc = new HWComposer ( this , * static_cast < HWComposer :: EventHandler *>( this ));

 //初始化部分
 for (size_t i=0 ; i
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp token = mBuiltinDisplays[i];

            sp bq = new BufferQueue(new GraphicBufferAlloc());

            //数据加工好了以后FramebufferSurface内部把他送给HWComposer
            sp fbs = new FramebufferSurface(*mHwc, i, bq);

            //数据生产者,每个屏幕都有一个,以后在这个屏幕上的绘制都是操作了bq
            //DisplayDevice就是bufferqueue的生产者
            sp hw = new DisplayDevice(this, type, allocateHwcDisplayId(type), isSecure, token,
                    fbs, bq,
                    mEGLConfig);

            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                hw->acquireScreen();
            }
            mDisplays.add(token, hw);
        }
    }
  }


VSYNC信号来了后会触发doComposition的调用
  void SurfaceFlinger::doComposition() {
    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (size_t dpy=0 ; dpy
        const sp& hw(mDisplays[dpy]);
        if (hw->canDraw()){
             //这个屏幕是否可以绘制,有可能屏幕关闭了,那就没必要绘制了
            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

            //绘制到硬件抽象层的frametarget中
            doDisplayComposition(hw, dirtyRegion);  
        }
        hw->compositionComplete();
    }

    //硬件抽象composer进行合成
    postFramebuffer();
}

void SurfaceFlinger::postFramebuffer()
{
    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        if (!hwc.supportsFramebufferTarget()) {
            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
        }
       //上面DisplayDevice已经把需要glex合成的图像层,合成到FramebufferTarget中了

       //调用硬件合成,
        hwc.commit();
    }
 }

status_t HWComposer :: commit () {
    if ( mHwc ) {
    //硬件合成到屏幕上
        err = mHwc -> set ( mHwc , mNumDisplays , mLists );
    }
    return ( status_t ) err ;
}


//绘制到bufferqueue
void SurfaceFlinger::doDisplayComposition(const sp& hw,
        const Region& inDirtyRegion)
{

    //绘制到 FrambufferSurface的后台缓冲区中
    doComposeSurfaces(hw, dirtyRegion);

    //opengles 绘制到FrambufferSurface的BufferQueue中
    //反转缓冲区
    hw->swapBuffers(getHwComposer());
}


void SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty)
{
    RenderEngine& engine(getRenderEngine());   

    bool hasGlesComposition = hwc.hasGlesComposition(id);
    if (hasGlesComposition) {
        //把当前屏幕的eglsurface设置未当前表面,以后就绘制到这里面了啊
        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {           
            return;
        }     
    }

    const size_t count = layers.size();
    for (size_t i=0 ; i
         const sp& layer(layers[i]);
     //一层一层的绘制到hw的EglSurface中,硬件合成的层不需要绘制的
         layer->draw(hw, clip);
    }
}


Surfaceflinnger中创建的FramebufferSurface,Bufferqueue的消费者
class FramebufferSurface : public ConsumerBase, public DisplaySurface

//ConsumerBase包装了BufferQueue的消费监听逻辑,只要重载onFrameAvailable,onBuffersReleased
//有数据要消费的时候会主动调用
ConsumerBase::ConsumerBase(const sp& consumer, bool controlledByApp ){
    //监听bufferqueue是否准备好数据了
    wp listener = static_cast(this);
    sp proxy = new BufferQueue::ProxyConsumerListener(listener);
    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
}

void ConsumerBase::onFrameAvailable() {
    sp listener;
    {
        Mutex::Autolock lock(mMutex);
        listener = mFrameAvailableListener.promote();
    }

    //转发到外部通知一下
    if (listener != NULL) {
        listener->onFrameAvailable();
    }
}

void ConsumerBase::onBuffersReleased() {
    Mutex::Autolock lock(mMutex);

    //当buffer消费完成后,会清空本类保存的缓存数据
    uint32_t mask = 0;
    mConsumer->getReleasedBuffers(&mask);
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        if (mask & (1 << i)) {
            freeBufferLocked(i);
        }
    }
}

status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
        nsecs_t presentWhen) {
    //获取准备好的数据     
    status_t err = mConsumer->acquireBuffer(item, presentWhen);
    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;
    return OK;
}

-------------------------------------------------------------------------------
class FramebufferSurface : public ConsumerBase,
                           public DisplaySurface {


 void FramebufferSurface::onFrameAvailable() {//重载了这个方法,
    //获取准备好的buffer
    sp buf;
    sp acquireFence;
    status_t err = nextBuffer(buf, acquireFence);
    if (err != NO_ERROR) {
        return;
    }

    //buffer添加到HWComposer的FrameBufferTagert中
    err = mHwc.fbPost(mDisplayType, acquireFence, buf);   
}

status_t FramebufferSurface::nextBuffer(sp& outBuffer, sp& outFence) {
    Mutex::Autolock lock(mMutex);
    //获取准备好的buffer
    BufferQueue::BufferItem item;
    status_t err = acquireBufferLocked(&item, 0);
    //保存到当前值中,
    mCurrentBufferSlot = item.mBuf;
    mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
    outFence = item.mFence;
    outBuffer = mCurrentBuffer;
    return NO_ERROR;
}


//DisplayDevice数据的生产者
DisplayDevice::DisplayDevice(
        const sp& flinger,
        DisplayType type,
        int32_t hwcId,
        bool isSecure,
        const wp& displayToken,
        const sp& displaySurface,
        const sp& producer,
        EGLConfig config) 
{
    //通过这个producer创建一个本地窗口mNativeWindow
    mNativeWindow = new Surface(producer, false);
    ANativeWindow* const window = mNativeWindow.get();

    int format;
    window->query(window, NATIVE_WINDOW_FORMAT, &format);

    if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
        window->setSwapInterval(window, 0);


    EGLSurface surface;
    EGLint w, h;
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    //本地窗口创建surface,以后操作这个surface会间接填充BufferQueue
    // 需要eglSwapeBuffer(display,surface)
    //
    surface = eglCreateWindowSurface(display, config, window, NULL);
    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);

    mDisplay = display;
    mSurface = surface;
    mFormat  = format;
    mPageFlipCount = 0;
    mViewport.makeInvalid();
    mFrame.makeInvalid();
}

你可能感兴趣的:(android,graphics学习笔记)