当前位置: 代码迷 >> Android >> Android4.2.2 SurfaceFlinger当地的FramebufferSurface实现真正的显示
  详细解决方案

Android4.2.2 SurfaceFlinger当地的FramebufferSurface实现真正的显示

热度:63   发布时间:2016-04-28 06:26:52.0
Android4.2.2 SurfaceFlinger本地的FramebufferSurface实现真正的显示

 

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。

欢迎和大家交流。qq:1037701636 email:[email protected]

Android源码版本Version:4.2.2; 硬件平台 全志A31

 

FrameBufferSurface类,SurfaceFlinger处的本地的帧缓存,实际意义上的显存

FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :    ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())),//本地的BufferQueue以及分配器    mDisplayType(disp),    mCurrentBufferSlot(-1),    mCurrentBuffer(0),    mHwc(hwc){    mName = "FramebufferSurface";    mBufferQueue->setConsumerName(mName);    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |                                       GRALLOC_USAGE_HW_RENDER |                                       GRALLOC_USAGE_HW_COMPOSER);    mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(disp));    mBufferQueue->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));    mBufferQueue->setSynchronousMode(true);    mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);}

FrameBufferSurface看上去很类似于SurfaceTexture(伴随着一个Layer的创建,供应用程序在SF处创建),两者都继承了ConsumerBase,故都为消费者。

SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),{  ...... }

区别在于SurfaceFLinger本地的这个FrameBufferSurface拥有自己的BufferQueue,以及一个GraphicBufferAlloc图形缓存分配类。

 

step2: 继续来看ConsumerBase类:

ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) :        mAbandoned(false),        mBufferQueue(bufferQueue) {    // Choose a name using the PID and a process-unique ID.    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());    // Note that we can't create an sp<...>(this) in a ctor that will not keep a    // reference once the ctor ends, as that would cause the refcount of 'this'    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>    // that's what we create.    wp<BufferQueue::ConsumerListener> listener;    sp<BufferQueue::ConsumerListener> proxy;    listener = static_cast<BufferQueue::ConsumerListener*>(this);    proxy = new BufferQueue::ProxyConsumerListener(listener);//新建一个监听代理    status_t err = mBufferQueue->consumerConnect(proxy);//创建一个ConsumerListener代理    if (err != NO_ERROR) {        CB_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)",                strerror(-err), err);    } else {        mBufferQueue->setConsumerName(mName);    }}

这里将proxy这个代理设置到mBufferQueue中去,使得mBufferQueue中的mConsumerListener = ProxyConsumerListener对象,而该对象中的mConsumerListener对象即为传入的this对象FrameBufferSurface。

 

step3: 本地的FrameBufferSurface在queueBuffer中的使用

在文章Android4.2.2 SurfaceFlinger之图形渲染queueBuffer实现和VSYNC的存在感 里面提到最后会调用

    // call back without lock held    if (listener != 0) {        listener->onFrameAvailable();//发布当前帧可以给消费者    }

故依次调用为ProxyConsumerListener->onFrameAvailable, 在到FramebufferSurface::onFrameAvailable()函数。

 

而在SurfaceTexture的处理中,是这样的:

故依次调用为ProxyConsumerListener->onFrameAvailable, 在到ConsumerBase::onFrameAvailable()函数,因为SurfaceTexture没有override ConsumerBase类的onFrameAvailable()成员函数。但是最终还是会提交给SurfaceTexture,原因如下:ConsumerBase自己的一个mFrameAvailableListener成员变量被初始化为了Layer的一个内部类FrameQueuedListener。使得最终的处理复杂化。

void ConsumerBase::onFrameAvailable() {    CB_LOGV("onFrameAvailable");    sp<FrameAvailableListener> listener;    { // scope for the lock        Mutex::Autolock lock(mMutex);        listener = mFrameAvailableListener;    }    if (listener != NULL) {        CB_LOGV("actually calling onFrameAvailable");        listener->onFrameAvailable();    }}
void Layer::onFirstRef(){    LayerBaseClient::onFirstRef();//基类LayerBaseClient    struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {//内部类继承FrameAvailableListener        FrameQueuedListener(Layer* layer) : mLayer(layer) { }    private:        wp<Layer> mLayer;        virtual void onFrameAvailable() {            sp<Layer> that(mLayer.promote());            if (that != 0) {                that->onFrameQueued();//调用Layer的onFrameQueued            }        }    };    mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));//新建立一个帧队列监听

最终是回调到layer的onFrameQueued.故这里说明了应用层的queueBuffer只是通知了SurfaceFlinger当前的Layer图层有图形缓存一帧入列了。请求SF他来做最终的显示。

 

step4: SurfaceFLinger在处理好所有的应用层的layer函数后就要准备送显,而送显的buffer也是通过OpenGl Es的queueBuffer来触发的,只是这里直接调用了step3中说明的流程。

void FramebufferSurface::onFrameAvailable() {    sp<GraphicBuffer> buf;    sp<Fence> acquireFence;    status_t err = nextBuffer(buf, acquireFence);    if (err != NO_ERROR) {        ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",                strerror(-err), err);        return;    }    err = mHwc.fbPost(mDisplayType, acquireFence, buf);//实现buffer的渲染    if (err != NO_ERROR) {        ALOGE("error posting framebuffer: %d", err);    }}

 

setp5: nextBuffer应该是获取一个最终要显示的图形缓存去,看到fbPost函数应该是送显,先来看看nextBuffer()函数:

status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {    Mutex::Autolock lock(mMutex);    BufferQueue::BufferItem item;    status_t err = acquireBufferLocked(&item);    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {        outBuffer = mCurrentBuffer;        return NO_ERROR;    } else if (err != NO_ERROR) {        ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);        return err;    }   .............       if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&        item.mBuf != mCurrentBufferSlot) {        // Release the previous buffer.        err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY,                EGL_NO_SYNC_KHR);        if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) {            ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);            return err;        }    }    mCurrentBufferSlot = item.mBuf;    mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;    outFence = item.mFence;    outBuffer = mCurrentBuffer;    return NO_ERROR;}

函数首先调用acquireBufferLocked来获取本地最终BufferQueue中的图形缓存并保存到item.

status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item) {    status_t err = mBufferQueue->acquireBuffer(item);    if (err != NO_ERROR) {        return err;    }    if (item->mGraphicBuffer != NULL) {        mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;    }    mSlots[item->mBuf].mFence = item->mFence;    CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);    return OK;}

 

setp6:fbpost()函数

int HWComposer::fbPost(int32_t id,        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {        return setFramebufferTarget(id, acquireFence, buffer);    } else {        if (acquireFence != NULL) {            acquireFence->waitForever(1000, "HWComposer::fbPost");        }        return mFbDev->post(mFbDev, buffer->handle);//framebuffer的正在渲染    }}

调用framebuffer的帧缓存设备的psot,完成这个buffer的显示。在gralloc模块中对应于fb_post()函数,由于不同的硬件对显示的底层机制由所区别,故fb_post()的显示也会有差别,但基本的原理就是触发当前的图像帧缓存送显而已。

 

step7:最后用一图来解释SurfaceFlinger从应用层到底层的整个绘图,显示的大致流程。

 

 

 


 


 


 


 


 

  相关解决方案