題外話
Covid-19疫情的強烈反彈,小區里檢測出了無症狀感染者。小區封閉管理,我也不得不居家辦公了。既然這么大把的時間可以光明正大的宅家里,自然要好好利用,八個字 == 努力工作,好好學習
一、前言
這篇文章中,將詳細講解 生產者 -- 圖形緩沖隊列 -- 消費者 這個模型的的具體工作流程。我們還是從我們的demo運行流程着手。
可以再回頭看看 Android 12(S) 圖像顯示系統 - 示例應用(二)
在demo示例中,我們獲取buffer --> 填充數據 --> 送出顯示的代碼如下所示(做了簡化):
// 9. dequeue a buffer
ANativeWindowBuffer *nativeBuffer = nullptr;
int hwcFD = -1;
err = nativeWindow->dequeueBuffer(nativeWindow, &nativeBuffer, &hwcFD);
// 10. make sure really control the dequeued buffer
sp<Fence> hwcFence(new Fence(hwcFD));
int waitResult = hwcFence->waitForever("dequeueBuffer_EmptyNative");
// 11. fill buffer
sp<GraphicBuffer> buf(GraphicBuffer::from(nativeBuffer));
uint8_t* img = nullptr;
err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
fillRGBA8Buffer(img);
err = buf->unlock();
// 13. queue the buffer to display
int gpuFD = -1;
err = nativeWindow->queueBuffer(nativeWindow, buf->getNativeBuffer(), gpuFD);
獲取圖形緩沖區調用流程:
==> ANativeWindow::dequeueBuffer
==> Surface::hook_dequeueBuffer
==> Surface::dequeueBuffer
==> BufferQueueProducer::dequeueBuffer
填充數據后返還圖形緩沖區的調用流程:
==> ANativeWindow::queueBuffer
==> Surface::hook_queueBuffer
==> Surface::queueBuffer
==> BufferQueueProducer::queueBuffer
前面文章講解中提到,BLASTBufferQueue中創建Surface對象時,初始化其成員mGraphicBufferProducer,這個就是指向了一個GraphicBufferProducer對象。
當然,demo作為客戶端僅僅是展示了生產者的工作,那消費者的工作又是如何的呢?
先用一張流程圖概述一下:
上圖基本展示了BufferQueue的工作邏輯以及Buffer的流轉過程和狀態變化情況。
上圖描述的流程我再重復嘮叨一遍:
- Producer准備繪圖時,調用dequeueBuffer向BufferQueue請求一塊buffer;
- BufferQueue收到dequeueBuffer的請求后會去自己的BufferSlot隊列中尋找一個FREE狀態的,然后返回它的index;
- Producer拿到可用的buffer后就可以准備填充數據了;
- Producer填充數據完畢,調用queueBuffer將bffer再返還給BufferQueue;
- BufferQueue收到queueBuffer請求后,將指定的buffer包裝為BufferItem對象,放入mQueue,並通知Consumer來消費;
- Consumer收到 frame available的通知后,調用acquireBuffer,獲取一個buffer;
- Consumer拿到buffer進行消費,一般是指SurfaceFlinger做渲染顯示;
- Consumer完成處理,調用releaseBuffer把buffer返還給BufferQueue,這個buffer之后就可以再次在新的循環中使用了。
另外一點請留意各個函數調用后,對應的BufferSlot(GraphicBuffer)的狀態變化。一般是這樣的:
FREE -> DEQUEUED -> QUEUED -> ACQUIRED -> FREE
二、生產者-Producer的相關邏輯
代碼位置 :/frameworks/native/libs/gui/BufferQueueProducer.cpp