Android開發(fā)graphics?bufferqueue整體流程
一、引言
1、bufferqueue 的四大流程;
2、簡要介紹四大流程的調(diào)用過程;
本文主要講解安卓圖形繪制中的buffer queue
頁面數(shù)據(jù)通過canvas/Open GL ES/vulkan繪制后,形成一幀buffer,交給buffer queue,buffer queue再把數(shù)據(jù)送到屏幕上顯示。所以buffer queue是圖形繪制中很核心的一環(huán),它本身就是一個緩沖區(qū)池與隊列相結(jié)合的數(shù)據(jù)結(jié)構(gòu)。
Buffer queue:
圖像緩沖區(qū),系統(tǒng)中絕大部分圖形數(shù)據(jù)都會緩沖于此。等待surfaceflinger組織進(jìn)一步的合成和顯示
備注:本文摘錄的代碼只摘錄關(guān)鍵代碼和路徑,需讀者自行結(jié)合閱讀.由于本文的重點在bufferqueue,其它和bufferqueue相關(guān)的流程提到的時候會精簡列出,作為輔助理解。
二、Buffer queue
2.1、buffer queue的創(chuàng)建
bufferquque構(gòu)建
//BufferQueue.cpp frameworks\native\libs\gui void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger) { sp<BufferQueueCore> core(new BufferQueueCore()); sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger)); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); *outProducer = producer; *outConsumer = consumer; }
構(gòu)建調(diào)用流程
下面堆棧表示了底層surface創(chuàng)建bufferqueue的一個過程
04-20 11:45:54.739 674 707 E createBufferQueue: #00 pc 0004ca33 /system/lib/libgui.so (android::BufferQueue::createBufferQueue(android::sp<android::IGraphicBufferProducer>*, android::sp<android::IGraphicBufferConsumer>*, bool)+74) 04-20 11:45:54.739 674 707 E createBufferQueue: #01 pc 00068539 /system/lib/libsurfaceflinger.so (android::BufferQueueLayer::onFirstRef()+40) 04-20 11:45:54.739 674 707 E createBufferQueue: #02 pc 000d5ad1 /system/lib/libsurfaceflinger.so (android::surfaceflinger::DefaultFactory::createBufferQueueLayer(android::LayerCreationArgs const&)+52) 04-20 11:45:54.739 674 707 E createBufferQueue: #03 pc 000c11d5 /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::createLayer(android::String8 const&, android::sp<android::Client> const&, unsigned int, unsigned int, int, unsigned int, android::LayerMetadata, android::sp<android::IBinder>*, android::sp<android::IGraphicBufferProducer>*, android::sp<android::IBinder> const&, android::sp<android::Layer> const&, unsigned int*)+1056) 04-20 11:45:54.739 674 707 E createBufferQueue: #04 pc 0006e197 /system/lib/libsurfaceflinger.so (android::Client::createSurface(android::String8 const&, unsigned int, unsigned int, int, unsigned int, android::sp<android::IBinder> const&, android::LayerMetadata, android::sp<android::IBinder>*, android::sp<android::IGraphicBufferProducer>*, unsigned int*)+122) 04-20 11:45:54.739 674 707 E createBufferQueue: #05 pc 0007b34f /system/lib/libgui.so (int android::SafeBnInterface<android::ISurfaceComposerClient>::MethodCaller<std::__1::tuple<android::String8 const&, unsigned int, unsigned int, int, unsigned int, android::sp<android::IGraphicBufferProducer> const&, android::LayerMetadata, android::sp<android::IBinder>*, android::sp<android::IGraphicBufferProducer>*, unsigned int*> >::callHelper<android::SafeBnInterface<android::ISurfaceComposerClient>, int (android::ISurfaceComposerClient::*)(android::String8 const&, unsigned int, unsigned int, int, unsigned int, android::sp<android::IGraphicBufferProducer> const&, android::LayerMetadata, android::sp<android::IBinder>*, android::sp<android::IGraphicBufferProducer>*, unsigned int*), std::__1::tuple<android::String8, unsigned int, unsigned int, int, unsigned int, android::sp<android::IGraphicBufferProducer>, android::LayerMetadata, android::sp<android::IBinder>, android::sp<android::IGraphicBufferProducer>, unsigned int>, 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u>(android 04-20 11:45:54.739 674 707 E createBufferQueue: #06 pc 00079e2f /system/lib/libgui.so (int android::SafeBnInterface<android::ISurfaceComposerClient>::callLocal<int (android::ISurfaceComposerClient::*)(android::String8 const&, unsigned int, unsigned int, int, unsigned int, android::sp<android::IBinder> const&, android::LayerMetadata, android::sp<android::IBinder>*, android::sp<android::IGraphicBufferProducer>*, unsigned int*)>(android::Parcel const&, android::Parcel*, int (android::ISurfaceComposerClient::*)(android::String8 const&, unsigned int, unsigned int, int, unsigned int, android::sp<android::IBinder> const&, android::LayerMetadata, android::sp<android::IBinder>*, android::sp<android::IGraphicBufferProducer>*, unsigned int*))+158) 04-20 11:45:54.739 674 707 E createBufferQueue: #07 pc 00079d3f /system/lib/libgui.so (android::BnSurfaceComposerClient::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+46)
BufferQueueCore:bufferqueue的實際實例,由他來銜接生產(chǎn)者和消費者
BufferQueueProducer:bufferqueue工廠模式的接口,生產(chǎn)者
BufferQueueConsumer:bufferqueue消費接口,消費者
BufferQueueCore 負(fù)責(zé)維護(hù) BufferQueue 的基本數(shù)據(jù)結(jié)構(gòu),而 BufferQueueProducer 和 BufferQueueConsumer 則負(fù)責(zé)提供操作 BufferQueue 的基本接口。
2.2、buffer queue整體流程
2.2.1、流程概要
image.png
這張圖片清晰的表述的buffer queue的工作方式,兩大功能:生產(chǎn)buffer、消費buffer。
dequeueBuffer:向buffer queue請求一個緩沖區(qū),并指定緩沖區(qū)的寬度、高度、像素格式和用法標(biāo)志
queueBuffer:把緩沖區(qū)返回到隊列
acquireBuffer:獲取緩沖區(qū)內(nèi)容
releaseBuffer:把數(shù)據(jù)返回到隊列
這里有兩次返回隊列,其實都是返回buffer queue的數(shù)據(jù)結(jié)構(gòu)中。簡述兩個流程
- 1、dequeue、queue等于先申請緩沖區(qū),并告訴producer申請成功,producer就把數(shù)據(jù)queue給buffer queue數(shù)據(jù)結(jié)構(gòu)中
- 2、當(dāng)consumer要的時候先去acquere獲取緩沖區(qū)內(nèi)容,獲取后進(jìn)行合成,合成完了需要釋放,就給回buffer queue來釋放
- 3、buffer queue操作數(shù)據(jù)時不會復(fù)制一份數(shù)據(jù),只會操作數(shù)據(jù)本身。
通篇文章,我們就在理解BufferQueueProducer 和 BufferQueueConsumer如何操作上面這四個流程requestBuffer
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight, reqFormat, reqUsage, &mBufferAge, enableFrameTimestamps ? &frameTimestamps : nullptr); ... if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) { if (mReportRemovedBuffers && (gbuf != nullptr)) { mRemovedBuffers.push_back(gbuf); } result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
requestBuffer單獨提一下這個流程,當(dāng)我們首次dequeueBuffer過后,surface會調(diào)用requestBuffer,requestBuffer的主要作用就是把GraphicBuffer傳給應(yīng)用側(cè),
這個動作只需要做一次,應(yīng)用側(cè)拿到GraphicBuffer過后就可以把共享內(nèi)存mmap到應(yīng)用側(cè)的內(nèi)存空間,然后才可以繪制圖像。
2.2.2、bufferqueue被調(diào)用流程
本小結(jié)主要目的是,在我們認(rèn)識bufferqueu的是如何工作的同時,不脫離surfaceflinger整體框架。簡單提一下它是如果調(diào)用來的。以便我們更深入理解。
1、dequeueBuffer&&queueBuffe
r當(dāng)app創(chuàng)建window的時候,會創(chuàng)建surface來顯示。實則會創(chuàng)建底層的surface。底層surface創(chuàng)建時會hook住dequeueBuffer和queueBuffer方法。
surface持有mGraphicBufferProducer對象來創(chuàng)建bufferqueue
dequeueBuffer方法位置:BufferQueueProducer::dequeueBuffer
04-20 09:48:38.909 6053 6263 E graphic dequeueBuffer: #00 pc 0006dea5 /system/lib/libgui.so (android::BpGraphicBufferProducer::dequeueBuffer(int*, android::sp<android::Fence>*, unsigned int, unsigned int, int, unsigned long long, unsigned long long*, android::FrameEventHistoryDelta*)+136) 04-20 09:48:38.909 6053 6263 E graphic dequeueBuffer: #01 pc 000842ed /system/lib/libgui.so (android::Surface::dequeueBuffer(ANativeWindowBuffer**, int*)+316) 04-20 09:48:38.909 6053 6263 E graphic dequeueBuffer: #02 pc 0015004b /system/lib/libhwui.so (android::uirenderer::renderthread::ReliableSurface::hook_dequeueBuffer(ANativeWindow*, int (*)(ANativeWindow*, ANativeWindowBuffer**, int*), void*, ANativeWindowBuffer**, int*)+42) 04-20 09:48:38.909 6053 6263 E graphic dequeueBuffer: #03 pc 00083181 /system/lib/libgui.so (android::Surface::hook_dequeueBuffer(ANativeWindow*, ANativeWindowBuffer**, int*)+60) //接上面,binder調(diào)用到BufferQueueProducer 04-20 09:48:38.946 668 697 E dequeueBuffer: #00 pc 00052653 /system/lib/libgui.so (android::BufferQueueProducer::dequeueBuffer(int*, android::sp<android::Fence>*, unsigned int, unsigned int, int, unsigned long long, unsigned long long*, android::FrameEventHistoryDelta*)+250) 04-20 09:48:38.946 668 697 E dequeueBuffer: #01 pc 0006d117 /system/lib/libgui.so (android::BnGraphicBufferProducer::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+374)
queueBuffer方法位置:BufferQueueProducer::queueBuffer
04-20 09:48:38.987 6053 6263 E queueBuffer: #00 pc 0006e4e1 /system/lib/libgui.so (android::BpGraphicBufferProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+128) 04-20 09:48:38.987 6053 6263 E queueBuffer: #01 pc 00084d83 /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+722) 04-20 09:48:38.987 6053 6263 E queueBuffer: #02 pc 00083259 /system/lib/libgui.so (android::Surface::hook_queueBuffer(ANativeWindow*, ANativeWindowBuffer*, int)+60) //接上面,binder調(diào)用到BufferQueueProducer 04-20 09:48:39.017 668 697 E queueBuffer: #00 pc 00053877 /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+266) 04-20 09:48:39.017 668 697 E queueBuffer: #01 pc 0006d345 /system/lib/libgui.so (android::BnGraphicBufferProducer::onTransact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+932)
2、acquireBuffer&&releaseBuffer
- 1、我們知道系統(tǒng)的刷新由Vsync信號控制,一個Vsync信號來時。surfaceflinger代碼會走INVALIDATE/REFRESH,最終都是走refresh
- 2、下面接收vsync的MessageQueue隊列,實際就是surfaceflinger初始化時創(chuàng)建的mEventQueue。
- 3、EventThread通過Connection通知VSYNC信號到達(dá)時可以觸發(fā)回調(diào)通知MessageQueue
- 4、vsync這個流程對應(yīng)bufferqueue流程中的acquireBuffer、releaseBuffer,調(diào)用流程堆棧下面已列出。
//SurfaceFlinger.cpp void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { onMessageInvalidate(expectedVSyncTime); break; } case MessageQueue::REFRESH: { onMessageRefresh(); break; } } }
acquireBuffer方法位置:BufferQueueConsumer::acquireBuffer
04-19 19:33:38.926 666 666 E acquireBuffer: #00 pc 0004d34f /system/lib/libgui.so (android::BufferQueueConsumer::acquireBuffer(android::BufferItem*, long long, unsigned long long)+74) 04-19 19:33:38.926 666 666 E acquireBuffer: #01 pc 000645cf /system/lib/libgui.so (android::ConsumerBase::acquireBufferLocked(android::BufferItem*, long long, unsigned long long)+62) 04-19 19:33:38.926 666 666 E acquireBuffer: #02 pc 0007a7a1 /system/lib/libsurfaceflinger.so (android::FramebufferSurface::advanceFrame(bool)+112) 04-19 19:33:38.926 666 666 E acquireBuffer: #03 pc 000edf1f /system/lib/libsurfaceflinger.so (android::compositionengine::impl::RenderSurface::queueBuffer(android::base::unique_fd_impl<android::base::DefaultCloser>, bool)+358) 04-19 19:33:38.926 666 666 E acquireBuffer: #04 pc 000e46e7 /system/lib/libsurfaceflinger.so (android::compositionengine::impl::Output::finishFrame(android::compositionengine::CompositionRefreshArgs const&)+454) 04-19 19:33:38.926 666 666 E acquireBuffer: #05 pc 000de3e5 /system/lib/libsurfaceflinger.so (android::compositionengine::impl::Display::finishFrame(android::compositionengine::CompositionRefreshArgs const&)+72) 04-19 19:33:38.926 666 666 E acquireBuffer: #06 pc 000e3011 /system/lib/libsurfaceflinger.so (android::compositionengine::impl::Output::present(android::compositionengine::CompositionRefreshArgs const&)+92) 04-19 19:33:38.926 666 666 E acquireBuffer: #07 pc 000dcfa1 /system/lib/libsurfaceflinger.so (android::compositionengine::impl::CompositionEngine::present(android::compositionengine::CompositionRefreshArgs&)+144) 04-19 19:33:38.926 666 666 E acquireBuffer: #08 pc 000baf81 /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::onMessageRefresh()+1280) 04-19 19:33:38.926 666 666 E acquireBuffer: #09 pc 000b8b1d /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::onMessageReceived(int, long long)+52)
releaseBuffer方法位置:BufferQueueConsumer::releaseBuffer
04-19 19:33:38.996 666 666 E releaseBuffer: #00 pc 0004e429 /system/lib/libgui.so (android::BufferQueueConsumer::releaseBuffer(int, unsigned long long, android::sp<android::Fence> const&, void*, void*)+72) 04-19 19:33:38.996 666 666 E releaseBuffer: #01 pc 0004f3af /system/lib/libgui.so (android::BufferQueueConsumer::releaseBuffer(int, unsigned long long, void*, void*, android::sp<android::Fence> const&)+36) 04-19 19:33:38.996 666 666 E releaseBuffer: #02 pc 0006498d /system/lib/libgui.so (android::ConsumerBase::releaseBufferLocked(int, android::sp<android::GraphicBuffer>, void*, void*)+140) 04-19 19:33:38.996 666 666 E releaseBuffer: #03 pc 00066cab /system/lib/libsurfaceflinger.so (android::BufferLayerConsumer::releasePendingBuffer()+78) 04-19 19:33:38.996 666 666 E releaseBuffer: #04 pc 00067b1d /system/lib/libsurfaceflinger.so (android::BufferQueueLayer::releasePendingBuffer(long long)+28) 04-19 19:33:38.996 666 666 E releaseBuffer: #05 pc 000bb0bb /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::onMessageRefresh()+1594) 04-19 19:33:38.996 666 666 E releaseBuffer: #06 pc 000b8b1d /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::onMessageReceived(int, long long)+52)
2.2.3、認(rèn)識BufferQueueCore
BufferQueueCore是bufferqueue實現(xiàn)的具體類。BufferQueueCore管理了幾個數(shù)據(jù)結(jié)構(gòu)。操作這幾個數(shù)據(jù)結(jié)構(gòu),來實現(xiàn)bufferqueue的dequebuffer等方法。
以dequeueBuffer過程來講,它就是向bufferqueue申請一個GraphicBuffer,用GraphicBuffer來繪制圖像。
BufferQueueCore中六個對象比較重要:mQueue、mSlot、FreeSlots、FreeBuffers、ActiveBuffers、UnusedBuffers 下面我會一一介紹
namespace android { class IConsumerListener; class IProducerListener; class BufferQueueCore : public virtual RefBase { private: BufferQueueDefs::SlotsType mSlots; Fifo mQueue; std::set<int> mFreeSlots; std::list<int> mFreeBuffers; std::list<int> mUnusedSlots; std::set<int> mActiveBuffers;
1、mQueue&&mSlot我們先認(rèn)識這兩個最核心的數(shù)據(jù)結(jié)構(gòu)。
class BufferItem { public: enum { INVALID_BUFFER_SLOT = -1 }; BufferItem() : mGraphicBuffer(nullptr), mFence(Fence::NO_FENCE) {} ~BufferItem() {} sp<GraphicBuffer> mGraphicBuffer; sp<Fence> mFence; Rect mCrop; typedef Vector<BufferItem> Fifo; Fifo mQueue; namespace BufferQueueDefs { typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS]; } BufferQueueDefs::SlotsType mSlots;
我們平時說的bufferqueue隊列其實就是說的BufferItem這個mQueue數(shù)據(jù)容器。BufferItem擁有GraphicBuffer對象
而mSlot是一個BufferSlot大小為NUM_BUFFER_SLOTS(等于64)的數(shù)組,BufferSlot主要用來綁定GraphicBuffer,BufferSlot和GraphicBuffer一一對應(yīng)。
BufferSlot中有一個BufferState對象,它專門用來表示GraphicBuffer的狀態(tài)
struct BufferSlot { BufferState mBufferState; // BufferState tracks the states in which a buffer slot can be. struct BufferState { // All slots are initially FREE (not dequeued, queued, acquired, or shared). BufferState() : mDequeueCount(0), mQueueCount(0), mAcquireCount(0), mShared(false) { } uint32_t mDequeueCount; uint32_t mQueueCount; uint32_t mAcquireCount; bool mShared; // A buffer can be in one of five states, represented as below: // // | mShared | mDequeueCount | mQueueCount | mAcquireCount | // --------|---------|---------------|-------------|---------------| // FREE | false | 0 | 0 | 0 | // DEQUEUED| false | 1 | 0 | 0 | // QUEUED | false | 0 | 1 | 0 | // ACQUIRED| false | 0 | 0 | 1 | // SHARED | true | any | any | any |
2、FreeSlots、FreeBuffers、ActiveBuffers、UnusedBuffers
知道了mQueue&&mSlot作用后,我們再來認(rèn)識他們四個容易了,首先成立這樣一個等式
mSlots = mFreeSlots + mFreeBuffers + mActiveBuffers + mUnusedSlots
mSlots是所有BufferSlot,而其它四個BufferSlot,則表示不同的狀態(tài)的BufferSlot。
mFreeSlots:BufferSlot狀態(tài)為FREE,且沒有GraphicBuffer與之相綁定的slot集合
mFreeBuffers:BufferSlot狀態(tài)為FREE,且有GraphicBuffer與之相綁定的slot集合
mActiveBuffers:BufferSlot狀態(tài)不為FREE(即DEQUEUED、QUEUED、ACQUIRED、SHARED)的slot集合。既然狀態(tài)不是FREE,那么該BufferSlot必然有一個GraphicBuffer與之相綁定
mUnusedSlots:未參與使用的slot集合,由 mMaxBufferCount 決定
2.2.4、BufferQueueProducer生產(chǎn)者
生產(chǎn)者這邊,在bufferqueue流程中,主要負(fù)責(zé)dequeueBuffer、queueBuffer等流程
class BufferQueueProducer : public BnGraphicBufferProducer { public: friend class BufferQueue; // Needed to access binderDied explicit BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false); ~BufferQueueProducer() override; virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf); virtual status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width, uint32_t height, PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) override; virtual status_t queueBuffer(int slot, const QueueBufferInput& input, QueueBufferOutput* output); ...//等方法
1、dequeueBuffer
status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence, uint32_t width, uint32_t height, PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) { // 獲取下一個buffer slot,如果有freeSlot直接拿來用 while (found == BufferItem::INVALID_BUFFER_SLOT) { status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found); if (status != NO_ERROR) { return status; } ... // IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION 和IGraphicBufferProducer::RELEASE_ALL_BUFFERS標(biāo)記會走 requestBuffer流程來獲取graphicBuffer對應(yīng)的slot if ((buffer == nullptr) || buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) { mSlots[found].mAcquireCalled = false; mSlots[found].mGraphicBuffer = nullptr; mSlots[found].mRequestBufferCalled = false; mSlots[found].mEglDisplay = EGL_NO_DISPLAY; mSlots[found].mEglFence = EGL_NO_SYNC_KHR; mSlots[found].mFence = Fence::NO_FENCE; mCore->mBufferAge = 0; mCore->mIsAllocating = true; returnFlags |= BUFFER_NEEDS_REALLOCATION; }
上面摘抄了dequebuffer流程主要的兩件事情
- 1、獲取下一個buffer slot,如果有freeSlot直接拿來用
- 2、IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION 和IGraphicBufferProducer::RELEASE_ALL_BUFFERS標(biāo)記會走 requestBuffer流程來獲取graphicBuffer對應(yīng)的slot
2、queueBuffer
queueBuffer將已填充的緩沖區(qū)返回給BufferQueue,即把bufferslot封裝成BufferItem返回到BufferItem隊列mQueue。
status_t BufferQueueProducer::queueBuffer(int slot, const QueueBufferInput &input, QueueBufferOutput *output) { // 構(gòu)建bufferitem并賦值 BufferItem item; item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; ... item.mSlot = slot; item.mFence = acquireFence; item.mFenceTime = acquireFenceTime; //bufferItem 入隊 if (mCore->mQueue.empty()) { // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer mCore->mQueue.push_back(item); frameAvailableListener = mCore->mConsumerListener; } else { // When the queue is not empty, we need to look at the last buffer // in the queue to see if we need to replace it const BufferItem& last = mCore->mQueue.itemAt( mCore->mQueue.size() - 1); if (last.mIsDroppable) { if (!last.mIsStale) { mSlots[last.mSlot].mBufferState.freeQueued();
queueBuffer比較簡單,主要兩步
1、構(gòu)建bufferItem,賦值等
2、把bufferItem返回到mQueue隊列中
2.2.4、BufferQueueConsumer消費者
1、acquireBuffer
acquireBuffer方法從緩沖隊列中嘗試取下一個掛起的BufferItem有這些情況:
隊列為空直接返回;如果緩沖已被獲取,返回之前獲取的緩沖項;如果expectedPresent標(biāo)記為非0,緩沖會即將顯示;如果緩沖時間戳在將來,不會被獲?。?/p>
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, nsecs_t expectedPresent, uint64_t maxFrameNumber) { // 新舊緩沖區(qū)顯示邏輯,決定顯示的buffer if (expectedPresent != 0 && !mCore->mQueue.empty()) { while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) { const BufferItem& bufferItem(mCore->mQueue[1]); ...
此段邏輯比較簡單,就是拿緩存,邏輯主要是怎么拿,最后回調(diào)
2、releaseBuffer
releaseBuffer將bufferslot返回到bufferqueue隊列。可以在bufferqueue任在訪問時進(jìn)行,當(dāng)buffer不再可用,fence機制會發(fā)出信號。
如果releaseBuffer收到STALE_BUFFER_SLOT信號,那么consumer必須直接放棄所有引用。直接釋放。
代碼就是release為主
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, const sp<Fence>& releaseFence, EGLDisplay eglDisplay, EGLSyncKHR eglFence) { sp<IProducerListener> listener; { // Autolock scope std::lock_guard<std::mutex> lock(mCore->mMutex); if (frameNumber != mSlots[slot].mFrameNumber && !mSlots[slot].mBufferState.isShared()) { return STALE_BUFFER_SLOT; } if (!mSlots[slot].mBufferState.isAcquired()) { BQ_LOGE("releaseBuffer: attempted to release buffer slot %d " "but its state was %s", slot, mSlots[slot].mBufferState.string()); return BAD_VALUE; } mSlots[slot].mEglDisplay = eglDisplay; mSlots[slot].mEglFence = eglFence; mSlots[slot].mFence = releaseFence; mSlots[slot].mBufferState.release();
三、bufferqueue總結(jié)
bufferqueue是整個安卓圖形處理的核心,把數(shù)據(jù)生產(chǎn)者和數(shù)據(jù)消費者連接起來。
生產(chǎn)者dequeuebuffer申請一個緩沖區(qū),并指定寬高等。填充緩沖區(qū)數(shù)據(jù)后用queueBuffer返回到隊列。隨后aquirebuffer獲取緩沖區(qū),消費者處理完后。則返回到隊列release
以上就是Android開發(fā)graphics bufferqueue整體流程的詳細(xì)內(nèi)容,更多關(guān)于Android graphics bufferqueue的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android FTP 多線程斷點續(xù)傳下載\上傳的實例
本篇文章主要介紹了Android FTP 多線程斷點續(xù)傳下載\上傳的實例,具有一定的參考價值,有興趣的可以了解一下2017-08-08android自定義gradle插件并且發(fā)布到本地倉庫詳細(xì)教程
這篇文章主要介紹了android自定義gradle插件并且發(fā)布到本地倉庫詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下2023-07-07Android游戲開發(fā):實現(xiàn)手勢操作切換圖片的實例
本文主要介紹 Android游戲開發(fā)實現(xiàn)手勢操作切換圖片的實例,這里整理了詳細(xì)的資料和示例代碼,有開發(fā)Android游戲應(yīng)用的小伙伴可以參考下2016-08-08Android SwipeRefreshLayout仿抖音app靜態(tài)刷新
這篇文章主要為大家詳細(xì)介紹了Android SwipeRefreshLayout仿抖音app靜態(tài)刷新,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03