Android Surface的創(chuàng)建 已經(jīng)大致說了下Surface在三個進程中創(chuàng)建的過程鸣皂,但是并沒有詳細的說Surface, 那么這個Surface到底是什么呢渣淳? (這里的所指的Surface是Native層的Surface)
先推薦兩篇
Android圖形顯示之硬件抽象層Gralloc族壳,對 Gralloc講得非常非常好
Android顯示系統(tǒng)設計框架介紹 這個寫得很全,也很多茁彭,但是也寫得非常好
前面APP進程已經(jīng)將要繪制的內(nèi)容繪制到了圖形緩沖區(qū)中了,下一步就是SurfaceFlinger進行合成并顯示出來了灭必。
一、Surface到底是什么
1.1 Surface定義
先看下Surface的定義, 如下
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase> {
}
template <typename NATIVE_TYPE, typename TYPE, typename REF>
class ANativeObjectBase : public NATIVE_TYPE, public REF {
}
ANativeObjectBase
是一個模板類乃摹,歸根到底就是Surface繼承于ANativeWindow. 那么ANativeWindow又是什么呢禁漓? 看下ANativeWindow的定義, system/core/include/system/window.h
struct ANativeWindow
{
struct android_native_base_t common;
const uint32_t flags;
const int minSwapInterval;
const float xdpi, ydpi;
int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer, int fenceFd);
int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer, int* fenceFd);
int (*perform)(struct ANativeWindow* window, int operation, ... );
}
每種操作系統(tǒng)都定義了自己的窗口系統(tǒng)湃缎,而EGL是定義跨平臺的接口刹缝,Android中EGL中的窗口類型EGLNativeWindowType
定義在frameworks/native/opengl/include/EGL/eglplatform.h
#elif defined(__ANDROID__) || defined(ANDROID) #Android平臺相關(guān)
struct ANativeWindow;
typedef struct ANativeWindow* EGLNativeWindowType;
EGLNativeWindowType是平臺無關(guān)的牍白,它在Android平臺下被定義成ANativeWindow, 也就是說其實Surface
本質(zhì)上就是一個Android的Native Window.
另外 Surface 中還定義了64個BufferSlot
BufferSlot mSlots[NUM_BUFFER_SLOTS];
每個BufferSlot中有一個GraphicBuffer, 這個GraphicBuffer指向了一塊圖形緩沖區(qū)步咪,其實就是一個ASHmem, 與SurfaceFlinger共同映射到同塊內(nèi)存上。 App所有的繪制都是寫入到該圖形緩沖區(qū)的芋类。
所以Surface還包含本地的圖形緩沖區(qū)用于保存UI繪制的內(nèi)容。這個后面會講
1.2 Surface(APP進程)與SurfaceFlinger進程之間的通信
RenderThread線程并沒有直接操作Surface, 而是通過操作EGLSurface來間接操作Surface.
以 EglManager中的createSurface為例來簡要的說下,createSurface調(diào)用了eglCreateWindowSurface
來創(chuàng)建EGL Surface. 代碼位于 frameworks/native/opengl/libs/EGL/eglApi.cpp
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
NativeWindowType window,
const EGLint *attrib_list)
{
egl_connection_t* cnx = NULL;
egl_display_ptr dp = validate_display_connection(dpy, cnx);
if (dp) {
EGLDisplay iDpy = dp->disp.dpy;
NativeWindowType android_window = NULL;
if (dp->disp.native == EGL_DEFAULT_DISPLAY) {
android_window = window; //獲得Native Window, 也就是ANativeWindow
}
if (android_window) {
//調(diào)用native window connect API
int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
if (format != 0) {
//同樣調(diào)用native window API
int err = native_window_set_buffers_format(window, format);
}
if (dataSpace != 0) {
int err = native_window_set_buffers_data_space(window, dataSpace);
}
ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
anw->setSwapInterval(anw, 1);
}
//OEM 自己的EGL實現(xiàn)磷支, 創(chuàng)建EGLSurface
EGLSurface surface = cnx->egl.eglCreateWindowSurface(iDpy, config, window, attrib_list);
if (surface != EGL_NO_SURFACE) {
//將ANativeWindow封裝到egl_surface_t中,也就是 EGLSurface
egl_surface_t* s = new egl_surface_t(dp.get(), config, android_window,
surface, cnx);
return s;
}
}
}
以native_window_api_connect為例, 代碼位于system/core/include/system/window.h
static inline int native_window_api_connect(
struct ANativeWindow* window, int api)
{
return window->perform(window, NATIVE_WINDOW_API_CONNECT, api);
}
由1.1小節(jié)可知 window->perform 也就是調(diào)用ANativeWindow::hook_perform食寡,也就是Surface::hook_perform
int Surface::hook_perform(ANativeWindow* window, int operation, ...) {
va_list args;
va_start(args, operation);
Surface* c = getSelf(window);
int result = c->perform(operation, args);
va_end(args);
return result;
}
而最終就調(diào)用到 Surface::perform中了雾狈,接著調(diào)用到 Surface::dispatchConnect
-> Surface::connect
int Surface::connect(int api, const sp<IProducerListener>& listener) {
IGraphicBufferProducer::QueueBufferOutput output;
int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
...
}
最后通過 (Binder) BpGraphicBufferProducer 去觸發(fā)SurfaceFlinger執(zhí)行connect
函數(shù)。
上面就是一個具體的API調(diào)用流程抵皱,其它的API可以類推善榛,只不過對于OEM相關(guān)的EGL實現(xiàn)由于沒有源碼辩蛋,就不好分析了,不過如果要與SurfaceFlinger通信移盆,最終都是一樣的, 都是通過Surface實現(xiàn)的悼院。
好了,Surface是什么大概知道了咒循,并且APP進程是怎么與SurfaceFlinger進程通信的也知道了据途,下面就來看BufferQueue相關(guān)概念
二、BufferQueue
2.1 BufferQueue生產(chǎn)者消費者模型
Android Surface創(chuàng)建 中第4小節(jié)已經(jīng)提到過SurfaceFlinger中Surface(Layer)創(chuàng)建了叙甸,接著又為Layer創(chuàng)建了相關(guān)的BufferQueue颖医。BufferQueue像是一個工具類,通createBufferQueue
來建立起B(yǎng)ufferQueue的模型
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;
}
如圖所示, BufferQueue模型是一個典型的生產(chǎn)者/消費者模型裆蒸,主要包含三個重要的類
BufferQueueCore
BufferQueueProducer
生產(chǎn)者BufferQueueConsumer
消費者
2.2 BufferQueueCore重要的變量
BufferQueueCore里有幾個很重要的 set/list定義變量熔萧,用于指明BufferSlot的狀態(tài)
mSlots
定義了64個BufferSlot, BufferSlot直接持有GraphicBufferstd::set<int> mFreeSlots
mFreeSlots里面的slot值表明當前slot的BufferSlot是FREE狀態(tài), 并且沒有GraphicBufferstd::list<int> mUnusedSlots
mSlots的大小是64個,而mUnusedSlots就是除掉mFreeSlots剩下的BufferSlotstd::list<int> mFreeBuffers
mFreeBuffers里面的slot表明當前slot對應的BufferSlot是FREE狀態(tài)僚祷,并且有GraphicBufferstd::set<int> mActiveBuffers
mActiveBuffers里面的slot表明當前slot對應的BufferSlot都有GraphicBuffer佛致,并且是NON FREE狀態(tài)
BufferQueueCore在初始化時就對mFreeSlots/mUnusedSlots初始化了
BufferQueueCore::BufferQueueCore(...)
{
int numStartingBuffers = getMaxBufferCountLocked();
for (int s = 0; s < numStartingBuffers; s++) {
mFreeSlots.insert(s);
}
for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
s++) {
mUnusedSlots.push_front(s);
}
}
getMaxBufferCountLocked
是當前Buffer個數(shù), double-buffers 或 triple buffers 又或是single buffers, 現(xiàn)在一般都是triple buffers.
2.3 GraphicBuffer
看下GraphicBuffer定義
class GraphicBuffer
: public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,
public Flattenable<GraphicBuffer>
和1.1 Surface定義類似久妆,ANativeObjectBase是一個模板類晌杰,這樣GraphicBuffer就間接繼承 ANativeWindowBuffer與Flattenable類,
fd: 指向一個文件描述符筷弦,這個要么是幀緩沖區(qū)設備肋演,要么是指向一塊圖形緩沖區(qū)(ashmem匿名共享內(nèi)存)
flags: 緩沖區(qū)flag
offset: 緩沖區(qū)偏移
base: 緩沖區(qū)實際地址
- 分配圖形緩沖區(qū)
GraphicBuffer::GraphicBuffer
-> initSize
-> GraphicBufferAllocator::alloc
-> alloc_device_t::alloc
-> gralloc_alloc
-> gralloc_alloc_buffer
-> fd = ashmem_create_region("gralloc-buffer", size);
-> mapBuffer -> gralloc_map -> mmap
創(chuàng)建一塊匿名共享內(nèi)存,fd 指向這塊內(nèi)存的文件句柄
- 分配系統(tǒng)幀緩沖區(qū)
先打開 /dev/graphics/fbXX, 然后做mmap, 并且將映射后的地址保存到 private_module_t -> private_handle_t ->base中
fb_device_open() -> mapFrameBuffer -> mapFrameBufferLocked -> mmap
調(diào)用 gralloc_alloc去分配幀緩存, 也就是使用fb_device_open映射好的那個內(nèi)存空間, 并保存到 GraphicBuffer中的private_handle_t中的base中.
此時 GraphicBuffer中private_handle_t中的fd指向 /dev/graphics/fbXX 的文件句柄
GraphicBuffer::GraphicBuffer
-> initSize
-> GraphicBufferAllocator::alloc
-> alloc_device_t::alloc
-> gralloc_alloc
-> gralloc_alloc_framebuffer
-> gralloc_alloc_framebuffer_locked
也就是說應用進程分配一塊圖形緩沖區(qū)烂琴,并且將這塊圖形緩沖區(qū)映射到應用進程的地址空間中爹殊,這樣應用程序就可以往里面寫入繪制畫面的內(nèi)容了。 最后應用程序?qū)蕚浜玫膱D形緩沖區(qū)渲染到幀緩沖區(qū)中(通過fb設備)奸绷, 即將圖形緩沖區(qū)的內(nèi)容繪制到顯示屏中去梗夸。參考Android幀緩沖區(qū)(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現(xiàn)原理分析
另外Android圖形顯示之硬件抽象層Gralloc對Gralloc寫得非常非常好。
下面以gralloc_alloc_buffer為例
static int gralloc_alloc_buffer(alloc_device_t* dev,
size_t size, int /*usage*/, buffer_handle_t* pHandle)
{
int err = 0;
int fd = -1;
size = roundUpToPageSize(size);
fd = ashmem_create_region("gralloc-buffer", size);
if (err == 0) {
private_handle_t* hnd = new private_handle_t(fd, size,0);
gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
dev->common.module);
err = mapBuffer(module, hnd);
if (err == 0) {
*pHandle = hnd;
}
}
return err;
}
在創(chuàng)建好ashmem后号醉,并做好地址映射后反症,輸出明明是GraphicBuffer中的handle,也就是buffer_handle_t的,為何在這里被賦值成private_handle_t的地址了呢畔派?
struct private_handle_t : public native_handle {
enum {
PRIV_FLAGS_FRAMEBUFFER = 0x00000001
};
// file-descriptors
int fd;
// ints
int magic;
int flags;
int size;
int offset;
// FIXME: the attributes below should be out-of-line
uint64_t base __attribute__((aligned(8)));
int pid;
static inline int sNumInts() {
return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds);
}
static const int sNumFds = 1;
static const int sMagic = 0x3141592;
private_handle_t(int fd, int size, int flags) : fd(fd), magic(sMagic), flags(flags), size(size), offset(0),
base(0), pid(getpid())
{
version = sizeof(native_handle);
numInts = sNumInts();
numFds = sNumFds;
}
~private_handle_t() {
magic = 0;
}
...
};
原來private_handle_t繼承于native_handle, 僅僅是將private_handle_t的地址保存到 GraphicBuffer中的handle而已铅碍,但是能反過來通過handle找到private_handle_t么?答案是可以的线椰, 原因是native_handle_t最后定義了一個int data[0],
其中data的地址與fd的地址是一樣的胞谈,這里利用了GCC的一個trick. 而native_handle_t里保存的就是data所指地址的長度。
來看下numInts的賦值
static inline int sNumInts() {
return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds);
}
可以看出numInts被賦值為除去native_handle_t的private_handle_t自己的成員變量的個數(shù),但是這里減1了烦绳,這個在GraphicBuffer的flatten與unflatten會一一對應起來卿捎,(減1是減掉了fd).
由于GraphicBuffer繼承于Flattenable, Flattenable的數(shù)據(jù)類型可以通過Binder傳遞,Parcel中有對Flattenable數(shù)據(jù)的處理.
status_t Parcel::write(const FlattenableHelperInterface& val)
{
status_t err;
// size if needed
const size_t len = val.getFlattenedSize();
const size_t fd_count = val.getFdCount();
...
err = this->writeInt32(len);
err = this->writeInt32(fd_count);
// payload
void* const buf = this->writeInplace(pad_size(len)); //獲得長度為len的buffer
int* fds = NULL;
if (fd_count) {
fds = new (std::nothrow) int[fd_count];
}
err = val.flatten(buf, len, fds, fd_count);
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
err = this->writeDupFileDescriptor( fds[i] );
}
if (fd_count) {
delete [] fds;
}
return err;
}
來看下GraphicBuffer中的getFlattenedSize
size_t GraphicBuffer::getFlattenedSize() const {
return static_cast<size_t>(11 + (handle ? handle->numInts : 0)) * sizeof(int);
}
getFlattenedSize 這里多加了11個字節(jié)径密,也是特定的午阵,這11個字節(jié)用來存放一些width/height, 頭部等等數(shù)據(jù)享扔,然后就是private_handle_t中的變量.
接著來看下GraphicBuffer的flatten函數(shù)
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
if (size < sizeNeeded) return NO_MEMORY;
size_t fdCountNeeded = GraphicBuffer::getFdCount();
if (count < fdCountNeeded) return NO_MEMORY;
int32_t* buf = static_cast<int32_t*>(buffer);
buf[0] = 'GBFR';
buf[1] = width;
buf[2] = height;
buf[3] = stride;
buf[4] = format;
buf[5] = usage;
buf[6] = static_cast<int32_t>(mId >> 32);
buf[7] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
buf[8] = static_cast<int32_t>(mGenerationNumber);
buf[9] = 0;
buf[10] = 0;
if (handle) {
buf[9] = handle->numFds;
buf[10] = handle->numInts;
memcpy(fds, handle->data,
static_cast<size_t>(handle->numFds) * sizeof(int));
memcpy(&buf[11], handle->data + handle->numFds,
static_cast<size_t>(handle->numInts) * sizeof(int));
}
buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
size -= sizeNeeded;
if (handle) {
fds += handle->numFds;
count -= static_cast<size_t>(handle->numFds);
}
return NO_ERROR;
}
flatten函數(shù)是將SurfaceFlinger中的GraphicBuffer中成員變量flatten到Buffer中趟庄,用于 Binder 傳輸?shù)綉眠M程中去。
從flatten可以看出伪很,在獲得flatten size的時間多加的11個int型用于儲存相關(guān)的數(shù)據(jù)戚啥, 然后將private_handle_t中fd的拷到fds中,再將private_handle_t中其它的數(shù)據(jù)拷到buffer+11開始的地址中去, 那么整個buffer的值就是
同理 unflatten 與flatten相反锉试,就是將buffer內(nèi)存塊儲存的值轉(zhuǎn)換到應用進程的GraphicBuffer中
注意猫十,這里面有個非常重要的字段 fd, fd 是 surfacelinger 中的文件描述符,當將GraphicBuffer傳遞給App進程里呆盖, Binder會在內(nèi)核中將SurfaceFlinger進程中的fd所指向的文件描述塊賦值給App進程中的新的fd, 具體可以參考binder ---傳遞文件描述符.
最后還有一個非常非常重要的App進程去映射Ashmem匿名內(nèi)存拖云,具體是在GraphicBuffer的unflatten中完成的
GraphicBuffer::unflatten
-> GraphicBufferMapper::registerBuffer
-> gralloc_module_t::registerBuffer
-> gralloc_register_buffer
-> gralloc_map -> mmap
建立好GraphicBuffer中的private_handle_t結(jié)構(gòu)體,至此应又,App進程就和SurfaceFlinger映射到同一塊內(nèi)存了宙项,App也就可以往這塊內(nèi)存里寫內(nèi)容了。
三株扛、BufferQueue之Producer(由Surface通過Binder線程調(diào)用)
3.1 SurfaceFlinger進程預分配GraphicBuffer
App進程通過Binder線程向SurfaceFlinger進程發(fā)起allocateBuffer請求尤筐,Android硬件渲染環(huán)境初始化中提到了allocateBuffer函數(shù),它的作用是預先分配Buffer, 這樣可以避免在渲染時分配帶來的延時洞就。 allocateBuffer最終會觸發(fā)BufferQueueProducer去allocateBuffer
void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
PixelFormat format, uint32_t usage) {
while (true) {
{
...
//這里 newBufferCount 為 3
newBufferCount = mCore->mFreeSlots.size();
...
mCore->mIsAllocating = true; //bool類型指明當前正在分配GraphicBuffer
}
Vector<sp<GraphicBuffer>> buffers;
for (size_t i = 0; i < newBufferCount; ++i) {
status_t result = NO_ERROR;
//創(chuàng)建GraphicBuffer
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
allocWidth, allocHeight, allocFormat, allocUsage, &result));
buffers.push_back(graphicBuffer);
}
{ // Autolock scope
for (size_t i = 0; i < newBufferCount; ++i) {
if (mCore->mFreeSlots.empty()) {
continue;
}
auto slot = mCore->mFreeSlots.begin();
mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
mSlots[*slot].mGraphicBuffer = buffers[i];
mSlots[*slot].mFence = Fence::NO_FENCE;
//此時分配了GraphicBuffer, 放入mFreeBuffers中
mCore->mFreeBuffers.push_front(*slot);
//已經(jīng)分配了GraphicBuffer, 那么mFreeSlots就不再保存這些slot
mCore->mFreeSlots.erase(slot);
}
mCore->mIsAllocating = false;
} // Autolock scope
}
}
3.2 dequeueBuffer
3.2.1 App進程通過Binder線程向SurfaceFlinger進程發(fā)起dequeueBuffer請求
syncFrameState()
-> eglMakeCurrent
-> eglMakeCurrent(OEM EGL)
-> Surface::hook_dequeueBuffer()
-> Surface::dequeueBuffer()
-> BpGraphicBufferProducer::dequeueBuffer()
-> BpGraphicBufferProducer::requestBuffer()
上述的dequeueBuffer的調(diào)用過程在不同的平臺實現(xiàn)可能不同盆繁,不必太深究
3.2.2 SurfaceFlinger進程中的dequeueBuffer
App進程發(fā)起B(yǎng)pGraphicBufferProducer::dequeueBuffer的請求,在SurfaceFlinger進程會觸發(fā)dequeueBuffer
status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
sp<android::Fence> *outFence, uint32_t interval,
uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
{ // Autolock scope
int found = BufferItem::INVALID_BUFFER_SLOT;
//找到一個BufferSlot
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,&found);
}
if (mCore->mSharedBufferSlot != found) {
//現(xiàn)在的狀態(tài)是DEQUEUE, 所以將slot插入到mActiveBuffers中
mCore->mActiveBuffers.insert(found);
}
*outSlot = found;
attachedByConsumer = mSlots[found].mNeedsReallocation;
mSlots[found].mNeedsReallocation = false;
//設置為DEQUEUE
mSlots[found].mBufferState.dequeue();
//檢查下是否需要重新分配GraphicBuffer
if ((buffer == NULL) ||
buffer->needsReallocation(width, height, format, usage))
{
returnFlags |= BUFFER_NEEDS_REALLOCATION;
} else {
mCore->mBufferAge =
mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
...
} // Autolock scope
//如果需要重新分配的話旬蟋,進入該分支
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
status_t error;
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
width, height, format, usage, &error));
{ // Autolock scope
if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
}
...
mCore->mIsAllocating = false;
mCore->mIsAllocatingCondition.broadcast();
} // Autolock scope
}
return returnFlags;
}
dequeueBuffer
主要做了以下幾件事情
- 獲得一個可用的BufferSlot
通過waitForFreeSlotThenRelock函數(shù)從mFreeBuffers(getFreeBufferLocked)或者從mFreeSlots(getFreeSlotLocked)獲得一個BufferSlot,
- 獲得一個可用的BufferSlot
- 將BufferSlot插入到mActiveBuffers中
- 設置BufferSlot的狀態(tài)為 DEQUEUE
狀態(tài)變化 FREE -> DEQUEUE
- 設置BufferSlot的狀態(tài)為 DEQUEUE
4.檢查是否需要重新分配GraphicBuffer
由于可能是從1中的mFreeBuffers中獲得可用的BufferSlot, 而該BufferSlot已經(jīng)分配過GraphicBuffer了油昂,但是此時dequeueBuffer需要的width/height/format/usage與該BufferSlot不對應,此時就需要重新分配一個新的GraphicBuffer- 將最后的BufferSlot返回給 APP進程中的Surface
如圖所示倾贰,dequeueBuffer找到了第三個BufferSlot.
3.3 requestBuffer
status_t BnGraphicBufferProducer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case REQUEST_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer; //局部變量
int result = requestBuffer(bufferIdx, &buffer);
reply->writeInt32(buffer != 0);
if (buffer != 0) {
reply->write(*buffer);
}
reply->writeInt32(result);
return NO_ERROR;
}
....
}
}
status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf)
{
...
*buf = mSlots[slot].mGraphicBuffer;
return NO_ERROR;
}
requestBuffer很簡單冕碟,App進程請求SurfaceFlinger將slot對應的BufferSlot中的GraphicBuffer傳給App進程,由2,2節(jié)匆浙,當Surface去dequeueBuffer時安寺,找到了Slot2中的BufferSlot,requestBuffer就將該BufferSlot中的GraphicBuffer傳遞給App進程的Surface, 詳細可以參見 2.2.2 GraphicBuffer吞彤。
3.4 queueBuffer
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
//input是Surface傳過來的我衬,input是flattenable的,這個可以看下前面的GraphicBuffer
input.deflate(×tamp, &isAutoTimestamp, &autoTimestamp, &dataSpace, &crop, &scalingMode,
&transform, &interval, &fence, &stickyTransform);
sp<IConsumerListener> frameAvailableListener;
sp<IConsumerListener> frameReplacedListener;
BufferItem item;
{ // Autolock scope
//獲得slot中的GrahicBuffer
const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
mSlots[slot].mFence = fence;
//狀態(tài)從DEQUQUE -> QUEUE
mSlots[slot].mBufferState.queue();
//將slot對應的BufferSlot的數(shù)據(jù)拷貝到BufferItem中
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mSlot = slot;
//mQueue是一個FIFO隊列饰恕,里面保存的queued buffers
if (mCore->mQueue.empty()) {
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
} else {
//當前隊列不為空挠羔,那么說明Consumer還沒消費掉,既然有新的Buffer來埋嵌,那舊的理論上是可以不用再顯示了
const BufferItem& last = mCore->mQueue.itemAt(mCore->mQueue.size() - 1);
if (last.mIsDroppable) { //是否是可以Drop掉
if (!last.mIsStale) {
//如果已經(jīng)過期了破加,則修改一些該BufferSlot的一些狀態(tài),
//比如將它從 mActiveBuffers中移出雹嗦,加入到mFreeBuffers中
...
}
// Overwrite the droppable buffer with the incoming one
//用最新的BufferItem替換最后那個
mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
frameReplacedListener = mCore->mConsumerListener;
} else {
//如果最后那個是不能Drop的范舀,那新來的Buffer也只能放在最后了。
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
}
}
//output是傳給App的
output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
mCore->mTransformHint,
static_cast<uint32_t>(mCore->mQueue.size()));
} // Autolock scope
// Don't send the GraphicBuffer through the callback, and don't send
// the slot number, since the consumer shouldn't need it
//看注釋是說Consumer不會用到slot值了罪,以及GraphicBuffer锭环,???
item.mGraphicBuffer.clear();
item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
{ // scope for the lock
if (frameAvailableListener != NULL) {
frameAvailableListener->onFrameAvailable(item); // 回調(diào) frame available
} else if (frameReplacedListener != NULL) {
frameReplacedListener->onFrameReplaced(item);
}
}
...
}
當新的一幀準備好后(queueBuffer),這時就要通知 Consumer去消費了泊藕,這時調(diào)用的是 BufferQueueCore::mConsumerListener -> onFrameAvailable
如圖所示辅辩,最終會調(diào)用到Layer的onFrameAvailable中
void Layer::onFrameAvailable(const BufferItem& item) {
{ // Autolock scope
//push到 mQueueItems中去
mQueueItems.push_back(item);
android_atomic_inc(&mQueuedFrames);
...
}
mFlinger->signalLayerUpdate();
if (mQueuedFrames>1) { //如果有兩個以上的Frames, 表示已經(jīng)mQueueItems已經(jīng)滿了
queueLengthState = QUEUE_IS_FULL;
}
}
void SurfaceFlinger::signalLayerUpdate() {
mEventQueue.invalidate();
}
mQueuedFrames表示當前已經(jīng)Queued 的 Frame的個數(shù)
接下來看下 MessageQueue::invalidate(),
#define INVALIDATE_ON_VSYNC 1
void MessageQueue::invalidate() {
#if INVALIDATE_ON_VSYNC
mEvents->requestNextVsync();
#else
mHandler->dispatchInvalidate();
#endif
}
從MessageQueue中的invalidate可以看出來,會直接調(diào)用 mEvents的requestNextVsync()
那這個mEvents是什么呢娃圆? 具體參考 Android SurfaceFlinger SW Vsync模型, mEvents也就是SF EventThread里創(chuàng)建的一個EventThread::Connection
鏈接 Android SurfaceFlinger SW Vsync模型里面的 vsync信號產(chǎn)生圖玫锋, 如圖中 1、3讼呢、3_1 所示
requestNextVsync經(jīng)過SF EventThead后撩鹿,最后在MessageQueue中的eventReceiver又會調(diào)用 mHandler->dispatchInvalidate()
mHandler->dispatchInvalidate()
->SurfaceFlinger::onMessageReceived()
-> handleMessageInvalidate()
-> signalRefresh()
看到這里, dispatchInvalidate分為兩個步聚了悦屏,一個是handleMessageInvalidate() 這個是Layer對GraphicBuffer做一些處理节沦,當處理完成后,就通過HWConsumer去合成buffer, 然后顯示了
四础爬、BufferQueue之Consumer (SurfaceFlinger EventThread里消費數(shù)據(jù))
當Layer通過onFrameAvailable回調(diào)并通過requestNextVsync去請求一個VSYNC同步信號去喚醒Consumer去消費掉新數(shù)據(jù)散劫。 最后在SF EventThread里收到INVALDATE信息,處理完INVALIDATE信息后又signalRefresh觸發(fā) REFRESH信息幕帆,將APP要顯示的內(nèi)容刷新到屏幕上
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
if (refreshNeeded) {
// Signal a refresh if a transaction modified the window state,
// a new buffer was latched, or if HWC has requested a full
// repaint
signalRefresh();
}
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
4.1 handleMessageTransaction
SurfaceFlinger和Layer分別處理事務, 分別跟新Drawing State, 這個Drawing 狀態(tài)用在后續(xù)的操作中获搏,作為當前繪制幀的狀態(tài)存在
SurfaceFlinger事務處理
4.2 handleMessageInvalidate
從 QUEUED 的Buffer中找到最合適的Buffer用于后面合成顯示
SurfaceFlinger之handlePageFlip
4.3 handleMessageRefresh
對Layer進行合成,刷新到屏幕上
SurfaceFlinger之Refresh