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从应用层到底层的整个绘图,显示的大致流程。

 

 

 


 


 


 


 


 

Android4.2.2 SurfaceFlinger本地的FramebufferSurface实现真正的显示,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。