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