前情提要
我們上回說到的 Producer 跟 Consumer 是一個很重要的結構,
這裡的 Producer 跟 Consumer 有時候不一定是單純扮演生產者的角色.
為什麼這麼說呢?
晚點你就會知道了 σ ゚∀ ゚) ゚∀゚)σ
我們先看看這整段在幹嘛:
void Layer::onFirstRef() { // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); mProducer = new MonitoredProducer(producer, mFlinger); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName); mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mSurfaceFlingerConsumer->setContentsChangedListener(this); mSurfaceFlingerConsumer->setName(mName); mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); }
好的, 看起來很正常
不就是個生產者跟消費者嗎?
我們先從第三行展開看看:
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, const sp<IGraphicBufferAlloc>& allocator) { sp<BufferQueueCore> core(new BufferQueueCore(allocator)); sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core)); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); *outProducer = producer; *outConsumer = consumer; }
因為沒有帶入 allocator, 預設會是 null
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, const sp<IGraphicBufferAlloc>& allocator = NULL);
在BufferQueueCore裡面會再自動生成 allocator
BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : mAllocator(allocator), mMutex(), mIsAbandoned(false), mConsumerControlledByApp(false), mConsumerName(getUniqueName()), mConsumerListener(), mConsumerUsageBits(0), mConnectedApi(NO_CONNECTED_API), mConnectedProducerListener(), mSlots(), mQueue(), mFreeSlots(), mFreeBuffers(), mOverrideMaxBufferCount(0), mDequeueCondition(), mUseAsyncBuffer(true), mDequeueBufferCannotBlock(false), mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888), mDefaultWidth(1), mDefaultHeight(1), mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN), mDefaultMaxBufferCount(2), mMaxAcquiredBufferCount(1), mBufferHasBeenQueued(false), mFrameCounter(0), mTransformHint(0), mIsAllocating(false), mIsAllocatingCondition(), mAllowAllocation(true), mBufferAge(0), mGenerationNumber(0) { if (allocator == NULL) { sp<ISurfaceComposer> composer(ComposerService::getComposerService()); mAllocator = composer->createGraphicBufferAlloc(); if (mAllocator == NULL) { BQ_LOGE("createGraphicBufferAlloc failed"); } } for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { mFreeSlots.insert(slot); } }
還記得 ComposerSerivce::getComposerService() 會取得的對象是 SurfaceFlinger 吧?
sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc() { sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc()); return gba; }
這個GraphicBufferAlloc現在不會做事, 不過它只有一個Function叫做createGraphicBuffer, 我們先貼出來看看:
GraphicBufferAlloc::GraphicBufferAlloc() { } GraphicBufferAlloc::~GraphicBufferAlloc() { } sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage, status_t* error) { sp<GraphicBuffer> graphicBuffer( new GraphicBuffer(width, height, format, usage)); status_t err = graphicBuffer->initCheck(); *error = err; if (err != 0 || graphicBuffer->handle == 0) { if (err == NO_MEMORY) { GraphicBuffer::dumpAllocationsToSystemLog(); } ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " "failed (%s), handle=%p", width, height, strerror(-err), graphicBuffer->handle); return 0; } return graphicBuffer; }
這裡會 new 出一個 GraphicBuffer 結構,
負責敘述長寬, 然後又透過了 GraphicBufferAllocator 來 alloc 一塊 buffer
(注意, 不是GraphicBufferAlloc, 是Allocator)
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inUsage) : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()), mInitCheck(NO_ERROR), mId(getUniqueId()) { width = height = stride = format = usage = 0; handle = NULL; mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage); } status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inUsage) { GraphicBufferAllocator& allocator = GraphicBufferAllocator::get(); uint32_t outStride = 0; status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage, &handle, &outStride); if (err == NO_ERROR) { width = static_cast<int>(inWidth); height = static_cast<int>(inHeight); format = inFormat; usage = static_cast<int>(inUsage); stride = static_cast<int>(outStride); } return err; }
前面都沒有真的去生成一塊 buffer, 現在總該是它了吧?
我們看一下 GraphicBufferAllocator 在幹嘛:
GraphicBufferAllocator::GraphicBufferAllocator() : mAllocDev(0) { hw_module_t const* module; int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); if (err == 0) { gralloc_open(module, &mAllocDev); } } status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage, buffer_handle_t* handle, uint32_t* stride) { ATRACE_CALL(); // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!width || !height) width = height = 1; // we have a h/w allocator and h/w buffer is requested status_t err; // Filter out any usage bits that should not be passed to the gralloc module usage &= GRALLOC_USAGE_ALLOC_MASK; int outStride = 0; err = mAllocDev->alloc(mAllocDev, static_cast<int>(width), static_cast<int>(height), format, static_cast<int>(usage), handle, &outStride); *stride = static_cast<uint32_t>(outStride); ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", width, height, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); uint32_t bpp = bytesPerPixel(format); alloc_rec_t rec; rec.width = width; rec.height = height; rec.stride = *stride; rec.format = format; rec.usage = usage; rec.size = static_cast<size_t>(height * (*stride) * bpp); list.add(*handle, rec); } return err; }
呀...終於跟 HW 牽扯上了一些關係,
這裡去開啟了你的 Gralloc HW module, 這個 module 會負責去獲取 vendor拿來處理影像 的buffer
這是因為處理影像使用到的硬件通常是跟 vendor 具有非常強的相關性,
且獲取到的 memory 並不一定是可以被 user space access 到的.
在獲取 memory 時, 我們帶入的 usage flags 會包含下列幾點:
- 這塊 Memory 有多常會被 Software (CPU) 存取
- 這塊 Memory 有多常會被 Hardware (GPU) 存取
- 這塊 Memory 會被作為 OpenGL ES(GLES) 的紋理 (texture) 使用嗎?
- 這塊 Memory 會被 Video Encoder 使用嗎?
舉例來說, 我們帶入 format 為 RBGA 8888, 並且表明這塊 buffer 會被 Software (ex. 你的Application) 使用,
那麼你的 Allocator 就一定要生出一塊 buffer, 提供 4 bytes per pixels in R-G-B-A order.
反過來說, 假設你表明這塊 buffer 只會被 Hardware 並且作為 GLES texture 使用, 那麼 allocator 就可以做任何 GLES driver 想要的 ...
例如把 順序改為 BGRA ordering, non-linear swizzled layout, 或者是支援更多的 color formats.
(讓 Hardware 使用它 preferred 的格式通常可以帶來更高的 performance)
好, 有點扯遠了. 我們先回到前面的 BufferQueueCore, 才剛講到
mAllocator = composer->createGraphicBufferAlloc();
這裡生出了一個 gba, 但它甚至還沒有去獲取 buffer
下面的 mFreeSlots 目前不知道做甚麼的, 不過看起來就是做一下初始化,
這個 mFreeSlots 是一個 set, 先把每一個 Slots (0~63) 都先塞入了 mFreeSlots
應該是表示目前的 Queue 都是空的.
再回到上一層的 BufferQueue::createBufferQueue(), 接下來要處理 producer & consumer
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core)); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
這個 sp 指標可以想成是 IGraphicBufferProducer *producer, 只是多了智慧管理memory來防止memory leak
BufferQueueProducer & BufferQueueConsumer 的建構子如下:
BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) : mCore(core), mSlots(core->mSlots), mConsumerName(), mStickyTransform(0), mLastQueueBufferFence(Fence::NO_FENCE), mCallbackMutex(), mNextCallbackTicket(0), mCurrentCallbackTicket(0), mCallbackCondition() {} BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) : mCore(core), mSlots(core->mSlots), mConsumerName() {}
看得出來比較重要的應該是 mCore 跟 mSlots 對象
查找一下 mSlots 的說明如下:
BufferQueueDefs::SlotsType mSlots;
它是一個 buffer slots 的陣列, 是 producer side 的鏡象.這邊的 requestBuffer 當然是 BufferQueueProducer 呼叫到的, 稍後我們會看到.
這個陣列使得 producer 跟 consumer 可以切換 buffer 的所有權,
不需要透過 Binder 來交換 GraphicBuffer.
一開始全部的 array 會被初始化成 NULL,
並且會在呼叫 requestBuffer 的時候根據 slot index 生成.
這裡 createBufferQueue 的工作就結束了, 這裡我們先回顧一下:
上一篇的最後, BootAnimation 透過 SurfaceComposerClient 對 SurfaceFlinger 說:
之後一路呼叫到了 SurfaceFlinger::createNormalLayer.幫我生個孩子吧
嗯抱歉, 是幫我生塊 Surface 吧 (createSurface)
對 Layer (Application) 來說, 它並不是那麼在意 buffer 是怎麼生成的,
對它來說最終拿到的會是 producer & consumer.
接下來, Layer 又把 producer 跟 consumer 分別丟給了兩位社畜
void Layer::onFirstRef() { // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); mProducer = new MonitoredProducer(producer, mFlinger); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName); mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mSurfaceFlingerConsumer->setContentsChangedListener(this); mSurfaceFlingerConsumer->setName(mName); mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); }
MonitoredProducer 看起來只是封裝了一層介面去呼叫 producer,
最大的差別應該是他在 destructure 裡面封裝了一個 Message 去通知 SurfaceFlinger 清除掉 mProducer
MonitoredProducer::MonitoredProducer(const sp<IGraphicBufferProducer>& producer, const sp<SurfaceFlinger>& flinger) : mProducer(producer), mFlinger(flinger) {} MonitoredProducer::~MonitoredProducer() { // Remove ourselves from SurfaceFlinger's list. We do this asynchronously // because we don't know where this destructor is called from. It could be // called with the mStateLock held, leading to a dead-lock (it actually // happens). class MessageCleanUpList : public MessageBase { public: MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& producer) : mFlinger(flinger), mProducer(producer) {} virtual ~MessageCleanUpList() {} virtual bool handler() { Mutex::Autolock _l(mFlinger->mStateLock); mFlinger->mGraphicBufferProducerList.remove(mProducer); return true; } private: sp<SurfaceFlinger> mFlinger; wp<IBinder> mProducer; }; mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(this))); }
另外一邊, SurfaceFlingerConsumer 看起來就有點料了.
它是一個繼承自 GLConsumer 的 class
GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t texTarget, bool useFenceSync, bool isControlledByApp) : ConsumerBase(bq, isControlledByApp), mCurrentTransform(0), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentFence(Fence::NO_FENCE), mCurrentTimestamp(0), mCurrentFrameNumber(0), mDefaultWidth(1), mDefaultHeight(1), mFilteringEnabled(true), mTexName(tex), mUseFenceSync(useFenceSync), mTexTarget(texTarget), mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT), mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), mAttached(true) { GLC_LOGV("GLConsumer"); memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix)); mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); }
GLConsumer 又繼承自 ConsumerBase
ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) : mAbandoned(false), mConsumer(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<ConsumerListener> listener = static_cast<ConsumerListener*>(this); sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener); status_t err = mConsumer->consumerConnect(proxy, controlledByApp); if (err != NO_ERROR) { CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)", strerror(-err), err); } else { mConsumer->setConsumerName(mName); } }
在 ConsumerBase 裡面, 實作了一個 listener 的機制
這裡會再跟 BufferQueue 牽扯上關係, 呼叫的是 ProxyConsumerListener,
並將自己轉化為 listener 對象作為參數帶入.
我們看一下 ProxyConsumerListener 是做甚麼用的:
BufferQueue::ProxyConsumerListener::ProxyConsumerListener( const wp<ConsumerListener>& consumerListener): mConsumerListener(consumerListener) {} void BufferQueue::ProxyConsumerListener::onFrameAvailable( const BufferItem& item) { sp<ConsumerListener> listener(mConsumerListener.promote()); if (listener != NULL) { listener->onFrameAvailable(item); } }
看起來只是呼叫了 ConsumerBase, 這裡我們列出來
void ConsumerBase::onFrameAvailable(const BufferItem& item) { CB_LOGV("onFrameAvailable"); sp<FrameAvailableListener> listener; { // scope for the lock Mutex::Autolock lock(mMutex); listener = mFrameAvailableListener.promote(); } if (listener != NULL) { CB_LOGV("actually calling onFrameAvailable"); listener->onFrameAvailable(item); } } // mListener 是 setFrameAvailableListener 帶入的 void ConsumerBase::setFrameAvailableListener( const wp<FrameAvailableListener>& listener) { CB_LOGV("setFrameAvailableListener"); Mutex::Autolock lock(mMutex); mFrameAvailableListener = listener; }
那麼 ProxyComuserListener 又是怎麼觸發的呢?
我們先回到 ConsumerBase, 這裡呼叫的是
status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
而 mConsumer 是誰呢?
就是我們一開始透過 BufferQueue::createBufferQueue(&producer, &consumer); 所生成 consumer 啦 (BufferQueueConsumer)
回頭看一下 BufferQueueConsumer
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) { return connect(consumer, controlledByApp); } status_t BufferQueueConsumer::connect( const sp<IConsumerListener>& consumerListener, bool controlledByApp) { ATRACE_CALL(); if (consumerListener == NULL) { BQ_LOGE("connect(C): consumerListener may not be NULL"); return BAD_VALUE; } BQ_LOGV("connect(C): controlledByApp=%s", controlledByApp ? "true" : "false"); Mutex::Autolock lock(mCore->mMutex); if (mCore->mIsAbandoned) { BQ_LOGE("connect(C): BufferQueue has been abandoned"); return NO_INIT; } mCore->mConsumerListener = consumerListener; mCore->mConsumerControlledByApp = controlledByApp; return NO_ERROR; }
只是把 mCore->mConsumerListener 設置成了 consumerListener
那應該會有人來呼叫 consumerListener 對吧?
到底是誰呢?
聰明的你, 一定猜到了對吧 (*ˇωˇ*人)
沒錯, 就是 BufferQueueProducer 啦
回頭搜尋一下, 你會看到在 status_t BufferQueueProducer::queueBuffer() 這個函數裡面 (我們先不管到底是誰去呼叫它的)
// 抱歉這函數真的超長, 容我先列出一小段 status_t BufferQueueProducer::queueBuffer(int slot, const QueueBufferInput &input, QueueBufferOutput *output) { ... { frameAvailableListener = mCore->mConsumerListener; } ... { ... if (frameAvailableListener != NULL) { frameAvailableListener->onFrameAvailable(item); } else if (frameReplacedListener != NULL) { frameReplacedListener->onFrameReplaced(item); } ... } }
這裡的 frameAvailableListener, 實際上是 proxy 對象喔 (BufferQueue::ProxyConsumerListener)
接著 proxy 對象會呼叫它自己的 mConsumerListener, 也就是 ConsumerBase
ConsumerBase::onFrameAvailable() 又呼叫了 mFrameAvailableListener->onFrameAvailable()
mFrameAvailableListener 對象是透過 setFrameAvailableListener 帶進來的
在我們的案例裡就是 SurfaceFlingerConsumer::setContentsChangedListener
void SurfaceFlingerConsumer::setContentsChangedListener( const wp<ContentsChangedListener>& listener) { setFrameAvailableListener(listener); Mutex::Autolock lock(mMutex); mContentsChangedListener = listener; }
往上看一下 Layer::onFirstRef(), 這裡的 listener, 實際上就是 Layer 自己
收到了 onFrameAvailable 之後, Layer 會通知 SurfaceFlinger 說要更新啦
void Layer::onFrameAvailable(const BufferItem& item) { // Add this buffer from our internal queue tracker { // Autolock scope Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after // a frame number reset if (item.mFrameNumber == 1) { mLastFrameNumberReceived = 0; } // Ensure that callbacks are handled in order while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { ALOGE("[%s] Timed out waiting on callback", mName.string()); } } mQueueItems.push_back(item); android_atomic_inc(&mQueuedFrames); // Wake up any pending callbacks mLastFrameNumberReceived = item.mFrameNumber; mQueueItemCondition.broadcast(); } mFlinger->signalLayerUpdate(); }
...所以這些人到底在幹嘛?
(」・ω・)」SAN値!(/・ω・)/ピンチ!
再來回顧一下, 差不多該喝杯茶了
Layer:
1.) 透過 BufferQueue 生成了 producer (BufferQueueProducer) 跟 consumer (BufferQueueConsumer)
2.) 把 producer 交給 MonitoredProducer, 它自己的 mProducer 是 MonitoredProducer
3.) 把 consumer 交給 SurfaceFlingerConsumer
4.) 把自己作為 listener 設給 SurfaceFlingerConsumer
BufferQueueCore:
負責跟 Gralloc HW Module 要 buffer, 作為 Producer 跟 Consumer 的橋樑
BufferQueueProducer:
目前只知道他會透過 mSlots 跟 BufferQueueConsumer 溝通
MonitoredProducer:
在解構子封裝一層移除 Producer 的功能, 沒惹
SurfaceFlingerConsumer:
繼承了 GLConsumer, 帶入 consumer
GLConsumer:
繼承了 ConsumerBase, 帶入 consumer
ConsumerBase:
1.) 生成一個 BufferQueue::ProxyConsumerListener, 並把 this (SurfaceFlingerConsumer) 帶入
2.) 將 proxy 交給 BufferQueueConsumer 作為它的 mListener
3.) 收到 onFrameAvailable 時, 通知自己的 mFrameAvailableListner 對象 (Layer)
BufferQueueConsumer:
當 BufferQueueProducer::queueBuffer 時, 通知它的 mConsumerListener
(BufferQueue::ProxyConsumerListener)
BufferQueue::ProxyConsumerListener:
收到 onFrameAvailable 時, 通知自己的 mConsumerListener 對象
(SurfaceFlingerConsumer)
(備註, 其實我不太懂為什麼要多一層 ProxyConsumerListener, 感覺可以直接把 ConsumerBase 的 this 丟給 BufferQueueConsumer 就好...)
下一篇, 我們再來看看 BufferQueueProducer 是怎麼推動的
(¦3[▓▓]
(BufferQueue::ProxyConsumerListener)
BufferQueue::ProxyConsumerListener:
收到 onFrameAvailable 時, 通知自己的 mConsumerListener 對象
(SurfaceFlingerConsumer)
(備註, 其實我不太懂為什麼要多一層 ProxyConsumerListener, 感覺可以直接把 ConsumerBase 的 this 丟給 BufferQueueConsumer 就好...)
下一篇, 我們再來看看 BufferQueueProducer 是怎麼推動的
(¦3[▓▓]
沒有留言:
張貼留言