參考:
【Android6.0 顯示系統(tǒng)(一) Surface創(chuàng)建】
https://blog.csdn.net/kc58236582/article/details/52670528
【Android6.0 顯示系統(tǒng)(二) SurfaceFlinger創(chuàng)建Surface】
https://blog.csdn.net/kc58236582/article/details/52680288
【Android6.0 顯示系統(tǒng)(三) 管理圖像緩沖區(qū)】
https://blog.csdn.net/kc58236582/article/details/52681363
【Android6.0 顯示系統(tǒng)(四) 圖像顯示相關(guān)】
https://blog.csdn.net/kc58236582/article/details/52690130
【Android6.0 顯示系統(tǒng)(五) SurfaceFlinger服務(wù)】
https://blog.csdn.net/kc58236582/article/details/52763534
【Android6.0 顯示系統(tǒng)(六) 圖像的輸出過(guò)程】
https://blog.csdn.net/kc58236582/article/details/52778333
OpenGrok地址:http://androidxref.com/
注:本文部分描述直接摘抄原文。
1 Surface的創(chuàng)建
1.1 應(yīng)用層創(chuàng)建Surface
1.2 WMS創(chuàng)建Surface
1.1 應(yīng)用層創(chuàng)建Surface
一般Activity中的Surface是ViewRootImpl中通過(guò)WMS創(chuàng)建的。當(dāng)然也會(huì)有需要在應(yīng)用中獨(dú)立創(chuàng)建Surface的情況,比如相機(jī),視頻播放器等應(yīng)用。它們是通過(guò)SurfaceView來(lái)使用surface.
- SurfaceVIew中---> new Surface()

- surface的updatewindow函數(shù)
【SurfaceView】updateWindow ---> 【SurfaceView】mSession.relayout()
int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility,
int flags, out Rect outFrame, out Rect outOverscanInsets,
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
out Rect outOutsets, out Configuration outConfig, out Surface outSurface);
mSession, 是一個(gè)IWindowSession, 用于和WMS通信, 在調(diào)用relayout函數(shù)的時(shí)候通過(guò)outSurface從WMS獲得Surface對(duì)象, 這里的outSurface就是傳入的mNewSurface。返回是通過(guò)Parcel的方式
- Surface的獲取流程
【Surface】readFrameParcel——> 【Surface】nativeReadFromParcel(在native層創(chuàng)建一個(gè)surface對(duì)象) ----->【Surface】setNativeObjectLocked(將native層創(chuàng)建的對(duì)象保存在java的本地對(duì)象中)
在調(diào)用nativeReadFromParcel在native層創(chuàng)建surface對(duì)象的時(shí)候會(huì)從binder中讀取進(jìn)程間傳輸?shù)腷inder,并將讀取的binder對(duì)象作為參數(shù)創(chuàng)建一個(gè)IGraphicBufferProducer對(duì)象,然后在以該對(duì)象創(chuàng)建Surface
小結(jié),在應(yīng)用層使用surface最終也是在native層創(chuàng)建一個(gè)surface對(duì)象,并且對(duì)應(yīng)著一個(gè)IGraphicBufferProducer

1.2 WMS層創(chuàng)建Surface
在應(yīng)用層通過(guò)relayout調(diào)用后通過(guò)binder的通信最終會(huì)調(diào)用到WMS.relayout,這個(gè)時(shí)候就開始進(jìn)行WMS層的Surface創(chuàng)建過(guò)程了。
【W(wǎng)MS】relayoutWindow --->【W(wǎng)MS】 winAnimator.createSurfaceLocked(獲得SurfaceControl對(duì)象)---.>outSurface.copyFrom ---> 把native層的surfacecontrol對(duì)象中的surface復(fù)制到Surface的mNative中。
SurfaceControl的創(chuàng)建
【W(wǎng)MS】winAnimator.createSurfaceLocked---> 【SurfaceControl】nativeCreate(創(chuàng)建一個(gè)native層的surfacecontrol對(duì)象)
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
sp<SurfaceControl> surface = client->createSurface(
String8(name.c_str()), w, h, format, flags);
if (surface == NULL) {
jniThrowException(env, OutOfResourcesException, NULL);
return 0;
}
surface->incStrong((void *)nativeCreate);
return reinterpret_cast<jlong>(surface.get());
來(lái)看android_view_SurfaceSession_getClient就是獲取SurfaceSession的mNativeObject對(duì)象,也就是SurfaceComposerClient對(duì)象。
這里出現(xiàn)了幾個(gè)對(duì)象:
IWindowSession: 跨進(jìn)程通信的接口,供客戶端使用,服務(wù)端實(shí)現(xiàn)在Session
Session:對(duì)IWindowSession的實(shí)現(xiàn),并封裝了WMS的實(shí)例,可以和WMS交互;同時(shí)在addToDisplay的時(shí)候把客戶端的IWindow對(duì)象傳遞給了WMS,這樣WMS就可以管理客戶端的Window。
SurfaceSession:java層的對(duì)象,對(duì)應(yīng)了natvie層的SurfaceComposerClient
SurfaceComposerClient: 在底層和Surface可以建立通信。
- SurfaceSession的創(chuàng)建
在ViewRootImpl的setView時(shí)候,會(huì)調(diào)用mWindowSession(IWindowSession-->實(shí)現(xiàn)在Session.java中)的addToDisplay函數(shù),在這個(gè)函數(shù)調(diào)用了WMS的addWindow函數(shù),而在addWindow方法,后面會(huì)創(chuàng)建一個(gè)WindowState對(duì)象,然后調(diào)用了其attach方法。
【W(wǎng)indowState】attach--->【Session】windowAddedLocked --->【Session】new SurfaceSession()【創(chuàng)建SurfaceSession,同時(shí)讓wms記錄該條surfacesession】---> 【SurfaceSession】nativeCreate
----> 【android_view_SurfaceSession】nativeCreate(在native層創(chuàng)建SurfaceComposerClient對(duì)象,該對(duì)象可以連接到SurfaceFlinger)
- SurfaceComposerClient連接SurfaceFlinger
負(fù)責(zé)連接到SurfaceFlinger,并獲得SurfaceFinger端為該客戶端創(chuàng)建的client對(duì)象,保存在SurfaceComposerClient中的mClient對(duì)象中。當(dāng)需要?jiǎng)?chuàng)建Surface的時(shí)候會(huì)調(diào)用到SurfaceFlinger中去。
比如在創(chuàng)建Surface的時(shí)候, 是通過(guò)創(chuàng)建java層的SurfaceControl ---> 獲得native層的SurfaceComposerClient對(duì)象--->通過(guò)SurfaceComposerClient對(duì)象來(lái)中和Surfaceflinger連接的mClient對(duì)象調(diào)用到SurfaceFlinger ---> SurfaceFlinger創(chuàng)建gbp(graphicBufferProducer,handle)對(duì)象,然后封裝到native層的SurfaceControl中,返回給客戶端java層,因此后續(xù)通過(guò)java層的SurfaceControl對(duì)象就可以通過(guò)JNI層獲得native層的SurfaceControl對(duì)象,并獲得SurfaceFlinger端創(chuàng)建的gbp

**涉及到的類:SurfaceView, SurfaceControl, SurfaceComposerClient,SurfaceControl, **
2 SurfaceFlinger創(chuàng)建Surface
2.1 創(chuàng)建Layer
2.2 獲取gbp
在第一部分中已知從java層調(diào)用到了SurfaceFlinger層創(chuàng)建Surface,現(xiàn)在就從SurfaceFlinger的createSurface入手。
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, //唯一標(biāo)識(shí), IBinder
sp<IGraphicBufferProducer>* gbp) //圖像緩沖對(duì)象
{
/*
* createSurface must be called from the GL thread so that it can
* have access to the GL context.
*/
class MessageCreateLayer : public MessageBase {
SurfaceFlinger* flinger;
Client* client;
sp<IBinder>* handle;
sp<IGraphicBufferProducer>* gbp;
status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
: flinger(flinger), client(client),
handle(handle), gbp(gbp), result(NO_ERROR),
name(name), w(w), h(h), format(format), flags(flags) {
}
status_t getResult() const { return result; }
virtual bool handler() {
result = flinger->createLayer(name, client, w, h, format, flags,
handle, gbp);
return true;
}
};
sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle, gbp);
mFlinger->postMessageSync(msg);
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}
這個(gè)函數(shù)中定義了一個(gè)消息類MessageCreateLayer,然后把它的對(duì)象通過(guò)postMessageSync方法發(fā)送出去,這個(gè)消息是以同步的方式發(fā)送,因此函數(shù)結(jié)束后可以直接返回結(jié)果。因此就直接到了handler函數(shù),在這個(gè)函數(shù)中調(diào)用了SurfaceFlinger的createLayer函數(shù)。
2.1 創(chuàng)建Layer
【SurfaceFlinger】createLayer ---> 創(chuàng)建不同的Layer ---> 然后從layer中獲得handle, gbp.
2.1 獲取handle
下面我們?cè)賮?lái)看handle的獲取,只是新建一個(gè)Handle,而這個(gè)Handle只是一個(gè)Binder的實(shí)現(xiàn),就是標(biāo)識(shí)Surface的全局唯一性,沒(méi)有什么實(shí)際的內(nèi)容。
/*
* The layer handle is just a BBinder object passed to the client
* (remote process) -- we don't keep any reference on our side such that
* the dtor is called when the remote side let go of its reference.
*
* LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
* this layer when the handle is destroyed.
*/
class Layer::Handle : public BBinder, public LayerCleaner {
public:
Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
: LayerCleaner(flinger, layer), owner(layer) {}
wp<Layer> owner;
};
sp<IBinder> Layer::getHandle() {
Mutex::Autolock _l(mLock);
LOG_ALWAYS_FATAL_IF(mHasSurface,
"Layer::getHandle() has already been called");
mHasSurface = true;
return new Handle(mFlinger, this);
}
2.2 獲取gbp

在這里是直接返回對(duì)象mProducer。

這里出現(xiàn)了三個(gè)新的類:
BufferQueue, 隊(duì)列,連接producer和consumer的核心。
MonitoredProducer, 只是一個(gè)代理類,真正工作的是參數(shù)producer, 表示生產(chǎn)者。
SurfaceFlingerConsumer, 消費(fèi)者代理方,surflinger消耗方。
image.png
在BufferQueue創(chuàng)建生產(chǎn)者和消費(fèi)者的具體實(shí)現(xiàn),是創(chuàng)建了三個(gè)對(duì)象:BufferQueueCore, BufferqueueProducer, BufferQueueConsumer , 這三個(gè)對(duì)象非常重要。

3 管理圖像緩沖區(qū)
3.1 生產(chǎn)者和core的聯(lián)系
3.2 消費(fèi)者和core聯(lián)系
3.3 三者聯(lián)系
3.4 GraphicBuffer對(duì)象的創(chuàng)建
3.5 內(nèi)存緩沖區(qū)的fd傳遞到客戶進(jìn)程
- 最后分析到MonitoredProducer對(duì)象,這個(gè)對(duì)象只是一個(gè)代理,真正實(shí)是BufferQueueProducer類,這個(gè)對(duì)象和BufferQueueCore有關(guān)聯(lián),可以管理最多達(dá)64塊的緩沖區(qū)。Surface可以理解為一張畫布,那么Surface為何要和一個(gè)緩沖區(qū)隊(duì)列相關(guān)呢?在播放動(dòng)畫時(shí),美妙至少要播放24幀畫面才能形成比較真實(shí)的動(dòng)畫效果。而這些數(shù)據(jù)是通過(guò)cpu解碼得到的,準(zhǔn)備他們需要時(shí)間。對(duì)于圖像顯示設(shè)備而言,刷新周期是固定的,我們必須要在它需要數(shù)據(jù)的時(shí)候把數(shù)據(jù)準(zhǔn)備好。視頻播放的每一幀也需要在指定的時(shí)間播放,因此解碼器會(huì)提前準(zhǔn)備好一批數(shù)據(jù),這些數(shù)據(jù)保存在解碼器內(nèi)存的緩沖區(qū)中,當(dāng)時(shí)間到達(dá)是,解碼器會(huì)把內(nèi)部緩沖區(qū)的圖像復(fù)制到Surface中,但是顯示設(shè)備并不是立刻就把數(shù)據(jù)取走的,因此Surface也需要緩沖區(qū)來(lái)臨時(shí)保存數(shù)據(jù)。
3.1 生產(chǎn)者和core的聯(lián)系
BufferQueueProducer是IGraphicBufferProducer的實(shí)現(xiàn)類,IGraphicBufferProducer中定義了使用buffer的一些方法接口。
一般在使用這個(gè)buffer之前會(huì)先connect, 在使用結(jié)束后會(huì)disconnect
在BufferQueueCore類中定義了一個(gè)64項(xiàng)的數(shù)據(jù)mSlots。
BufferQueueDefs::SlotsType mSlots;
每個(gè)緩沖區(qū)的類型是BufferSlot類型。它有兩個(gè)重要的成員變量,mGraphicBuffer是指向圖像緩沖區(qū)GraphicBuffer的指針,mBufferState表示圖像緩沖區(qū)的狀態(tài)。
sp<GraphicBuffer> mGraphicBuffer;
......
BufferState mBufferState;
BufferState的狀態(tài)有下面幾個(gè)
enum BufferState {
FREE = 0,//空閑
DEQUEUED = 1,//生產(chǎn)狀態(tài),被生產(chǎn)者擁有
QUEUED = 2,//保存數(shù)據(jù)狀態(tài),被BufferQueue擁有
ACQUIRED = 3//消費(fèi)狀態(tài),被消費(fèi)者擁有
};
BufferQueueProducer的dequeueBuffer函數(shù)用來(lái)向BufferQueueCore申請(qǐng)一個(gè)空閑的slot,這個(gè)slot可能已經(jīng)有緩沖區(qū),也可能沒(méi)有,如果沒(méi)有緩沖區(qū),dequeueBuffer函數(shù)會(huì)分配一塊新的緩沖區(qū)。得到空閑的slot后,還?需要調(diào)用requestBuffer函數(shù)來(lái)取得一塊緩沖區(qū)??。得到緩沖區(qū),如果不需要了,可以使用cancelBuffer函數(shù)來(lái)釋放這個(gè)slot。調(diào)用dequeueBuffer函數(shù)之后,緩沖區(qū)的擁有者是生產(chǎn)者,緩沖區(qū)處于DEQUEUED狀態(tài)。一旦緩沖區(qū)復(fù)制數(shù)據(jù)完成,通過(guò)queueBuffer函數(shù)把緩沖區(qū)的控制權(quán)交還給BufferQueueCore,這時(shí)候緩沖區(qū)將處于QUEUED狀態(tài)
3.2 消費(fèi)者和core聯(lián)系
IGraphicBufferConsumer定義接口,實(shí)際實(shí)現(xiàn)類是BufferQueueConsumer:
virtual status_t acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;
......
virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay display,
EGLSyncKHR fence);
virtual status_t connect(const sp<IConsumerListener>& consumerListener,
bool controlledByApp);
virtual status_t disconnect()
BufferQueueConsumer類是接口IGraphicBufferComsumer的實(shí)現(xiàn),在使用它之前,先要調(diào)用connect函數(shù)建立聯(lián)系,這里傳遞的參數(shù)是IConsumerListener對(duì)象,是一個(gè)回調(diào)接口,如果BufferQueue中有數(shù)據(jù)準(zhǔn)備好了就會(huì)調(diào)用它的onFrameAvailable函數(shù)來(lái)通知消費(fèi)者取走數(shù)據(jù)。
取走數(shù)據(jù)的時(shí)候,需要調(diào)用acquireBuffer函數(shù),將緩沖區(qū)狀態(tài)變成ACQUIRED,使用完之后調(diào)用releaseBuffer函數(shù)可以吧緩沖區(qū)數(shù)據(jù)歸還給BufferQueueCore,這樣緩沖區(qū)就變成FREE。
3.3 三者聯(lián)系
對(duì)象BufferQueueProducer和BufferQueueConsumer好像沒(méi)有直接聯(lián)系,其實(shí)都是通過(guò)共同的BufferQueueCore對(duì)象連接在一起的,很多操作時(shí)直接使用BufferQueueCore對(duì)象的成員變量而不是函數(shù)來(lái)完成的。
3.4 GraphicBuffer對(duì)象的創(chuàng)建
dequeueBuffer函數(shù)的部分代碼,在從BufferQueueCore中獲取到slot的時(shí)候,如果需要重新分配圖像緩沖區(qū)就會(huì)調(diào)用mCore->mAllocator->createGraphicBuffer函數(shù)來(lái)重新創(chuàng)建一個(gè)圖像緩沖區(qū)。
......
*outSlot = found;//found復(fù)制到outslot
ATRACE_BUFFER_INDEX(found);
attachedByConsumer = mSlots[found].mAttachedByConsumer;
mSlots[found].mBufferState = BufferSlot::DEQUEUED;//slot的狀態(tài)修改變成生產(chǎn)狀態(tài)
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if ((buffer == NULL) ||//為空,或者需要重新分配
buffer->needsReallocation(width, height, format, usage))
{
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
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;
returnFlags |= BUFFER_NEEDS_REALLOCATION;//需要重啟分配緩沖區(qū)
} else {
// We add 1 because that will be the frame number when this buffer
// is queued
mCore->mBufferAge =
mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
mCore->mBufferAge);
if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
"slot=%d w=%d h=%d format=%u",
found, buffer->width, buffer->height, buffer->format);
}
eglDisplay = mSlots[found].mEglDisplay;
eglFence = mSlots[found].mEglFence;
*outFence = mSlots[found].mFence;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
mCore->validateConsistencyLocked();
} // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {//如果需要重啟分配圖像緩沖區(qū)
status_t error;
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(//創(chuàng)建圖像緩沖區(qū)
width, height, format, usage, &error));
if (graphicBuffer == NULL) {
BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
return error;
}
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
if (mCore->mIsAbandoned) {
BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
return NO_INIT;
}
graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
} // Autolock scope
}
......
其中(mCore->mAllocator->createGraphicBuffer是調(diào)用到了SurfaceFlinger中創(chuàng)建的GraphicBufferAlloc類中,通過(guò)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;
......//錯(cuò)誤處理
return graphicBuffer;
}
創(chuàng)建一個(gè)GraphicBuffer, 在這里創(chuàng)建了一個(gè)graphicBuffer,在GraphicBuffer的構(gòu)造函數(shù)中會(huì)通過(guò)GraphicBufferAllocator進(jìn)行實(shí)際內(nèi)存的分配。
GraphicBufferAllocator實(shí)際是裝載了Gralloc模塊,實(shí)際通過(guò)Gralloc模塊進(jìn)行分配,這個(gè)模塊是在GraphicBufferAllocator的構(gòu)造函數(shù)中裝載。
調(diào)用alloc分配了一塊共享的內(nèi)存緩沖區(qū),alloc函數(shù)將返回共享區(qū)的fd和緩沖區(qū)的指針。既然GraphicBuffer中的緩沖區(qū)是共享內(nèi)存,我們知道使用共享內(nèi)存需要傳遞共享內(nèi)存的句柄fd。下面我們看看是如何傳到客戶進(jìn)程的。
3.5 內(nèi)存緩沖區(qū)的fd傳遞到客戶進(jìn)程(暫時(shí)略過(guò))
通過(guò)序列化的方式傳遞
GraphicBuffer類從模板類Flattenable派生,這個(gè)派生類可以通過(guò)Parcel傳遞,通常派生類需要重載flatten和unflatten方法,用于對(duì)象的序列化和反序列化。
class GraphicBuffer
: public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,
public Flattenable<GraphicBuffer>
通過(guò)flatten函數(shù),中fds用來(lái)傳遞文件句柄,函數(shù)把handle中的句柄復(fù)制到fds中,然后這些句柄就可以在通過(guò)binder傳遞到目標(biāo)進(jìn)程中去。
然后在unflatten函數(shù)調(diào)用時(shí)候,共享文件句柄已經(jīng)準(zhǔn)備好了,但是內(nèi)存還沒(méi)有進(jìn)行映射;調(diào)用mBufferMapper.registerBuffer函數(shù)進(jìn)行內(nèi)存映射,實(shí)際調(diào)用到了Gralloc模塊的gralloc_register_buffer函數(shù),這個(gè)函數(shù)就調(diào)用了mmap進(jìn)行共享內(nèi)存映射。
在硬件設(shè)備支持Framebuffer緩沖區(qū)的情況下,Surface中繪制圖形的緩沖區(qū)就是Framebuffer的緩沖區(qū),繪制完成后,如果不需要進(jìn)行圖像合成,只需要flip操作就能完成圖像的輸出,中間完全不用復(fù)制的過(guò)程,很高效。

小結(jié): 這部分作者kc專欄主要講解了在surface端申請(qǐng)的緩沖是如何管理的。以及graphicbuffer的分配和傳遞方式。
4 圖像顯示相關(guān)內(nèi)容
概念:刷新率,幀率,幀緩沖(framebuffer),雙緩沖技術(shù),Vsync信號(hào),三重緩沖技術(shù)。
VSync是一個(gè)硬件信號(hào),一般是顯示器刷新周期到了會(huì)發(fā)送。
HWComposer: 表示顯示的硬件設(shè)備。
HwComposer----> loadFbHalModule(裝載Framebuffer的硬件模塊) -----> loadHwcModule(裝載HWComposer的硬件模塊) ---->根據(jù)方式不同產(chǎn)生不同的vsync來(lái)源(軟件模擬或硬件產(chǎn)生)

4.1 Framebuffer原理
這里的講解流程比較簡(jiǎn)單,主要是通過(guò)gralloc模塊打開kernel提供過(guò)的fb節(jié)點(diǎn)。直接根據(jù)kc專欄的分析畫個(gè)流程圖便于自己今后快速查看。

分配緩沖圖像緩沖區(qū)內(nèi)存: 最終實(shí)現(xiàn)是通過(guò)galloc模塊的gralloc_alloc
小結(jié):這節(jié)主要清楚圖像是怎么顯示,什么是framebuffer,雙緩沖,以及vsync即可。
5 SurfaceFlinger
surfaceflinger服務(wù)是一個(gè)native服務(wù),是圖像系統(tǒng)非常重要的一個(gè)服務(wù),負(fù)責(zé)圖層的合成,vsync的分發(fā),以及和hal層的交互到圖像的渲染。
surfaceflinger怎么啟動(dòng)的就不用多看(通過(guò).rc配置在Init階段啟動(dòng),很多native層服務(wù)都是,native層的守護(hù)進(jìn)程同樣如此比如vold,healthd,netd等)。啟動(dòng)過(guò)后surfaceflinger干了什么事情是需要重點(diǎn)關(guān)注。
5.1 服務(wù)啟動(dòng)
在啟動(dòng)的時(shí)候調(diào)用到了main_surfaceflinger.cpp中的main函數(shù),在這里干了幾件事:
- 配置binder線程池最大線程數(shù)量
- 創(chuàng)建surfaceflinger對(duì)象
- 調(diào)用surfaceflinger的init函數(shù),然后想servicemanager注冊(cè)
- 開始run
surfaceflinger的init函數(shù)工作:
- 初始化opengles
- 創(chuàng)建顯示設(shè)備抽象HWComposer,和顯示設(shè)備打交道
- 創(chuàng)建顯示設(shè)備對(duì)象DisplayDevice
- 啟動(dòng)EventThread,監(jiān)聽和處理SurfaceFlinger中的事件
- 設(shè)置Vsync信號(hào)周期(在沒(méi)有HWComposer支持的情況下)
- 初始化顯示設(shè)備,調(diào)用initializeDisplays完成
- 啟動(dòng)開機(jī)動(dòng)畫
5.2 surfaceflinger中的消息和事件分發(fā)
MessageQueue:用于消息和事件的分發(fā)
EventThread:用來(lái)分析vsync信號(hào)
在SurfaceFlinger對(duì)象會(huì)有一個(gè)成員變量mEventQueue,在SurfaceFlinger的onFirstRef的時(shí)候會(huì)對(duì)mEventQueue進(jìn)行init,創(chuàng)建handler和looper。
handler是MessageQueue的內(nèi)部類,主要用來(lái)處理三個(gè)消息。

最后在SurfaceFlinger調(diào)用run函數(shù),這個(gè)函數(shù)最后會(huì)調(diào)用mEventQueue.waitMessage().

看下waitMessage方法,flushCommands主要是清理工作的,和Binder驅(qū)動(dòng)的交互關(guān)了。而pollOnce是消息機(jī)制,主要調(diào)用了epoll_wait函數(shù),會(huì)阻塞,阻塞完了會(huì)分發(fā)消息隊(duì)列中的消息。這里的消息只有自己在Handler中發(fā)的消息,還有在setEventThread中自己添加的fd。

這里是handler的分發(fā)消息。
接下來(lái)在surfaceflinger創(chuàng)建的時(shí)候會(huì)設(shè)置mSFEventThread線程用來(lái)分發(fā)Vsync消息。

5.3 顯示設(shè)備類DisplayDevice
DisplayDevice是顯示設(shè)備的抽象,定義了三種類型的設(shè)備:
- DISPLAY_PRIMARY 主顯示設(shè)備,通常是LCD屏幕
- DISPLAY_EXTERNAL 擴(kuò)展顯示設(shè)備,通過(guò)HDMI輸出顯示信號(hào)
- DISPLAY_VIRTUAL 虛擬顯示設(shè)備,通過(guò)WIFI輸出信號(hào)
surfaceFlinger中需要顯示的圖層(layer)將通過(guò)DisplayDevice對(duì)象傳遞到OpenGLES中進(jìn)行合成,合成之后的圖像再通過(guò)HWComposer對(duì)象傳遞到Framebuffer中顯示。DisplayDevice對(duì)象中的成員變量mVisibleLayersSortedByZ保存了所有需要顯示在本顯示設(shè)備中顯示的Layer對(duì)象,同時(shí)DisplayDevice對(duì)象也保存了和顯示設(shè)備相關(guān)的顯示方向、顯示區(qū)域坐標(biāo)等信息。
所有顯示設(shè)備的輸出都要通過(guò)HWComposer對(duì)象完成,因此上面這段代碼先調(diào)用了HWComposer的isConnected來(lái)檢查顯示設(shè)備是否已連接,只有和顯示設(shè)備連接的DisplayDevice對(duì)象才會(huì)被創(chuàng)建出來(lái)。即使沒(méi)有任何物理顯示設(shè)備被檢測(cè)到,SurfaceFlinger都需要一個(gè)DisplayDevice對(duì)象才能正常工作,因此,DISPLAY_PRIMARY類型的DisplayDevice對(duì)象總是會(huì)被創(chuàng)建出來(lái)。
然后會(huì)調(diào)用createBufferQueue函數(shù)創(chuàng)建一個(gè)producer和consumer,這個(gè)之前分析過(guò)。然后又創(chuàng)建了一個(gè)FramebufferSurface對(duì)象。這里我們看到在新建FramebufferSurface對(duì)象時(shí)把consumer參數(shù)傳入了代表是一個(gè)消費(fèi)者。而在DisplayDevice的構(gòu)造函數(shù)中,會(huì)創(chuàng)建一個(gè)Surface對(duì)象傳遞給底層的OpenGL ES使用,而這個(gè)Surface是一個(gè)生產(chǎn)者。在OpenGl ES中合成好了圖像之后會(huì)將圖像數(shù)據(jù)寫到Surface對(duì)象中,這將觸發(fā)consumer對(duì)象的onFrameAvailable函數(shù)被調(diào)用:
這就是Surface數(shù)據(jù)好了就通知消費(fèi)者來(lái)拿數(shù)據(jù)做顯示用,在onFrameAvailable函數(shù)匯總,通過(guò)nextBuffer獲得圖像數(shù)據(jù),然后調(diào)用HWComposer對(duì)象mHwc的fbPost函數(shù)輸出。 fbPost最后調(diào)用gralloc模塊的post函數(shù)進(jìn)行輸出。
DisplayDevice內(nèi)部, DisplayDevice構(gòu)造函數(shù)主要功能是創(chuàng)建了一個(gè)Surface對(duì)象mNativeWindow,同時(shí)用它作為參數(shù)創(chuàng)建EGLSurface對(duì)象,這個(gè)EGLSurface對(duì)象是OpenGL ES中繪圖需要的。
這樣,在DisplayDevice中就建立了一個(gè)通向Framebuffer的通道,只要向DisplayDevice的mSurface寫入數(shù)據(jù)。就會(huì)到消費(fèi)者FrameBufferSurface的onFrameAvailable函數(shù),然后到HWComposer在到Gralloc模塊,最后輸出到顯示設(shè)備。
swapBuffers函數(shù)將內(nèi)部緩沖區(qū)的圖像數(shù)據(jù)刷新到顯示設(shè)備的Framebuffer中,它通過(guò)調(diào)用eglSwapBuffers函數(shù)來(lái)完成緩沖區(qū)刷新工作。但是注意調(diào)用swapBuffers輸出圖像是在顯示設(shè)備不支持硬件composer的情況下。
5.4 VSYNC信號(hào)的分發(fā)(重要)
Vsync信號(hào)非常重要,決定這cpu什么時(shí)候開始準(zhǔn)備數(shù)據(jù),所以理解vsync信號(hào)的轉(zhuǎn)發(fā)過(guò)程有利于理解屏幕的刷新機(jī)制。
android 屏幕刷新機(jī)制參考:https://www.cnblogs.com/dasusu/p/8311324.html

流程一 vsync到來(lái)的時(shí)候:
HWComposer::vsync------> mEventHandler.onVSyncReceived------->mPrimaryDispSync.addResyncSample(timestamp)------->updateModeLocked() ------->mThread->updateModel(mThread是DispSyncThread類)----> mCond.signal()發(fā)送信號(hào)喚醒其他阻塞的等待。
流程二 喚醒:
----> DispSyncThread::threadLoop()---->fireCallbackInvocations(callbackInvocations)回調(diào)注冊(cè)的監(jiān)聽器-----> callbacks[i].mCallback->onDispSyncEvent()
流程三 流程二的喚醒回調(diào)去了哪里?
- 回調(diào)監(jiān)聽注冊(cè): 在EventThread的Threadloop函數(shù)中會(huì)根據(jù)waitForEvent函數(shù)判斷是否需要注冊(cè)監(jiān)聽---> 如果沒(méi)有客戶端和EventThread建立連接就不注冊(cè)監(jiān)聽vsync信號(hào)的回調(diào)(流程2中的回調(diào))-----> 通過(guò)mVSyncSource->setCallback函數(shù)注冊(cè)回調(diào)監(jiān)聽。
mVSyncSource來(lái)源如下圖所示。
image.png
- 回調(diào) 調(diào)用到EventThread::onVSyncEvent---> 把mVSyncEvent放到數(shù)組第一個(gè),然后調(diào)用Condition的broadcast,----> 喚醒EventThread::threadLoop的等待-----> 調(diào)用conn->postEvent來(lái)發(fā)送Event事件。
---->將事件發(fā)送到了MessageQueue
接下來(lái)
MessageQueue分發(fā)Vsync

MessageQueue::cb_eventReceiver() ----> MessageQueue::eventReceiver-----> MessageQueue::Handler::dispatchRefresh()-------> SurfaceFlinger::onMessageReceiver------> handleMessageRefresh。開始負(fù)責(zé)刷新系統(tǒng)顯示。
這樣就從底層到了SurfaceFlinger的接收vsync并刷新顯示
Vsync小結(jié):我們回顧下整個(gè)流程,VSync信號(hào)從底層產(chǎn)生后,經(jīng)過(guò)幾個(gè)函數(shù),保存到了SurfaceFlinger的mPrimaryDispSync變量(DisySync類)的數(shù)組中,這樣設(shè)計(jì)的目的讓底層的調(diào)用盡快結(jié)束,否則會(huì)耽擱下次VSync信號(hào)的發(fā)送。然后在mPrimaryDispSync變量關(guān)聯(lián)的線程開始分發(fā)數(shù)組中的VSync信號(hào),分發(fā)的過(guò)程也調(diào)用了幾個(gè)回調(diào)函數(shù),最終結(jié)果是放在EventThread對(duì)象的數(shù)組中。EventThread是轉(zhuǎn)發(fā)VSync信號(hào)的中心。不但會(huì)把VSync信號(hào)發(fā)給SurfaceFlinger,還會(huì)把信號(hào)發(fā)送到用戶進(jìn)程中去。EventThread的工作比較重,因此SurfaceFlinger中使用了兩個(gè)EventThread對(duì)象來(lái)轉(zhuǎn)發(fā)VSync信號(hào)。確保能及時(shí)轉(zhuǎn)發(fā)。SurfaceFlinger中的MessageQueue收到Event后,會(huì)將Event轉(zhuǎn)化成消息發(fā)送,這樣最終就能在主線程調(diào)用SurfaceFlinger的函數(shù)處理VSync信號(hào)了。
接下來(lái)vsync信號(hào)是怎么樣轉(zhuǎn)發(fā)到用戶進(jìn)程去?
6 圖像的輸出過(guò)程
在五部分的時(shí)候通過(guò)vsync信號(hào)調(diào)用到了surfaceflinger的handleMessageRefresh函數(shù)

其中比較重要的幾個(gè)函數(shù)如下:
preComposition()
rebuildLayerStacks();
setUpHWComposer()
doDebugFlashRegions();
doComposition();
postComposition();
這里的幾個(gè)函數(shù)可以結(jié)合systrace的surfaceflinger部分查看流程。
----> 開始

上面函數(shù)先是調(diào)用了mDrawingState的layersSortedByZ來(lái)得到上次繪圖的Layer層列表。并不是所有的Layer都會(huì)參與屏幕圖像的繪制,因此SurfaceFlinger用state對(duì)象來(lái)記錄參與繪制的Layer對(duì)象。
然后遍歷所有圖層檢查是否有變化,有變化就調(diào)用signalLayerUpdate()通知這種變化
----> 自然引出怎么判斷圖層是否有變化? 根據(jù)以下三個(gè)變量

通過(guò)之前的部分的流程,知道了在Layer層發(fā)生變化的時(shí)候會(huì)調(diào)用圖層的onFrameAvailable來(lái)通知這種變化,
設(shè)置監(jiān)聽器: SurfaceFlingerConsumer::setContentChangedListener
BufferQueue::ProxyConsumerListener::onFrameAvailable ------> ConsumerBase::onFrameAvailable ----> Layer::onFrameAvailable(主要目的將mQueueFrames加1,然后調(diào)用了SurfaceFlinger的signalLayerUpdate) -----> ........----> SurfaceFlinger::onMessageReceived----->handleMessageTransaction和handleMessageInvalidate
handleMessageInvalidate函數(shù)中調(diào)用了handlePageFlip函數(shù),這個(gè)函數(shù)將會(huì)處理Layer中的緩沖區(qū),把更新過(guò)的圖像緩沖區(qū)切換到前臺(tái),等待VSync信號(hào)更新到FrameBuffer。

用戶進(jìn)程更新Surface圖像,將導(dǎo)致SurfaceFlinger中的Layer發(fā)送invalidate消息,處理該消息會(huì)調(diào)用handleTransaction函數(shù)和handlePageFilp函數(shù)來(lái)更新Layer對(duì)象。一旦VSync信號(hào)到來(lái),再調(diào)用rebuildlayerStacks setUpHWComposer doComposition postComposition函數(shù)將所有Layer的圖像混合后更新到顯示設(shè)備上去。
rebuildLayerStacks函數(shù)的作用是重建每個(gè)顯示設(shè)備的可見layer對(duì)象列表.
setUpHWComposer函數(shù)的作用是更新HWComposer對(duì)象中圖層對(duì)象列表以及圖層屬性。
doComposition函數(shù)是合成所有層的圖像。 doComposition函數(shù)針對(duì)每種顯示設(shè)備調(diào)用doDisplayComposition函數(shù)來(lái)合成,合成后調(diào)用postFramebuffer函數(shù)
doDisplayComposition函數(shù)根據(jù)顯示設(shè)備支持的更新方式,重新設(shè)置需要更新區(qū)域的大小。
真正的合成工作是在doComposerSurfaces函數(shù)中完成,這個(gè)函數(shù)在layer的類型為HWC_FRAMEBUFFER,或者不支持硬件的composer的情況下,調(diào)用layer的draw函數(shù)來(lái)一層一層低合成最后的圖像。
合成完后,doDisplayComposition函數(shù)調(diào)用了hw的swapBuffers函數(shù),這個(gè)函數(shù)前面介紹過(guò)了,它將在系統(tǒng)不支持硬件的composer情況下調(diào)用eglSwapBuffers來(lái)輸出圖像到顯示設(shè)備。
postFramebuffer
postFramebuffer先判斷系統(tǒng)是否支持composer,如果不支持,我們知道圖像已經(jīng)在doComposition函數(shù)時(shí)調(diào)用hw->swapBuffers輸出了,就返回了。如果支持硬件composer,postFramebuffer函數(shù)將調(diào)用HWComposer的commit函數(shù)繼續(xù)執(zhí)行。commit函數(shù)又調(diào)用了composer模塊的set接口來(lái)完成工作,這就到HAL層的代碼了,最后輸出到顯示屏上。
這些函數(shù)更具體的信息還是需要參考閱讀原文或者源碼。https://blog.csdn.net/kc58236582/article/details/52778333

