關於圖形顯示部分能夠參考官網:Graphicsjava
Linux
一般使用Framebuffer
來用做顯示輸出(Framebuffer
知識詳解在這裏),Framebuffer
就是一塊內存區域,它一般是顯示驅動的內部緩衝區在內存中的映射。android
一旦用戶進程把圖像數據複製到Framebuffer
中,顯示驅動會一個像素一個像素地掃描整個Framebuffer
,並根據其中的值更新屏幕上像素點的顏色。api
驅動中這個更新屏幕的動做是固定的,它的週期就是咱們常說的刷新率
數組
Android
關於圖像渲染顯示的架構圖以下:
緩存
結合這張圖,咱們須要重點關注的是:markdown
Native Framework
中的Surface
session
API
,一切內容都會渲染到Surface
上Surface
中會關聯一個BufferQueue
用於提供圖像數據緩存OpenGL ES
或Vulkan
渲染到Surface
Canvas
渲染到Surface
Image Stream Producer
的定義是可以生成圖形緩衝區以供消耗的任何對象。每一個Producer
都會關聯一個Surface
,例如數據結構
Canvas 2D
:Java
層主要是經過View
中建立的Surface
對象來進行操做
Surface
對象會與SurfaceFlinger
進行關聯,並經過lockCanavas()
接口獲取Canvas
對象lockCanvas()
會將CPU渲染程序
鏈接到BufferQueue
的生產方,直到Surface
被銷燬時纔會斷開鏈接mediaserver視頻解碼器
:經過MediaPlayer
的setSurfaceHolder()
接口與SurfaceView
中的Surface
進行綁定對於Image Stream Consumer
來講,主要是SurfaceFlinger
,該系統服務會消耗當前可見的Surface
,並使用WindowManager
中提供的信息將它們合成到顯示部分。架構
SurfaceFlinger
是能夠修改所顯示部份內容的惟一服務。SurfaceFlinger
使用OpenGL
和Hardware Composer
來合成一組Surface
。WindowManager
請求緩衝區。而後,WindowManager
會從SurfaceFlinger
請求layer
。
layer
是surface
(包含BufferQueue
)和SurfaceControl
(包含屏幕框架等層元數據)的組合。SurfaceFlinger
建立layer
並將其發送至WindowManager
。WindowManager
將Surface
發送至應用,但會保留SurfaceControl
來操控應用在屏幕上的外觀。Window Positioning
中的WindowManager
主要是用來控制Window
對象app
Window
對象是用來存放View
對象的容器,每一個Window
對象都會關聯Surface
對象WindowManager
監視Window
對象的生命週期、輸入和焦點事件、屏幕方向、轉換、動畫、位置、變換、z順序等Window
元數據發送給SurfaceFlinger
,SurfaceFlinger
利用這些元數據把本身管理的全部Surface
組合成layer
Hardware Composer
作進一步處理HAL
層中的Hardware Composer(HWC)
會根據當前硬件來進一步進行緩衝區的組合,它的具體實現依賴於特定的顯示設備
HWC
的數據流以下:SurfaceFlinger
做爲client
向HWC
提供一個完整的layer
列表,而後詢問HWC
計劃如何處理HWC
會將這些layer
標記爲client合成
或者device合成
並告知SurfaceFlinger
SurfaceFlinger
將處理標記爲client合成
的layer
,而後經過BufferQueue
傳遞給HWC
layer
由HWC
自行處理網上一篇頗有趣的渲染總結(文中有些錯誤,但瑕不掩瑜):Android渲染原理
前面提到Linux
使用Framebuffer
來用做顯示輸出。可是,若是在屏幕更新到一半時,用戶進程更新了Framebuffer
中的數據,將致使屏幕上畫面的上半部分是前一幀的畫面,下半部分變成了新的畫面。固然這種異常會在下次刷新時糾正過來,可是在用戶感知上畫面會出現閃爍感
雙緩衝機制
,雙緩衝就是提供兩塊Framebuffer
,一塊用於顯示,另外一塊用於數據更新,數據準備好後,經過ioctl
操做告訴顯示設備切換用於顯示的Framebuffer
,這樣圖像就能快速的顯示出來了ioctl
操做完成後緩衝區沒有切換,應用就不能肯定什麼時候能夠再使用緩存區,只能經過ioctl
不停地查詢緩衝區狀態,直到切換完成。這種CPU
主動查詢的方式很低效爲此Android
讓底層固定地發送信號給用戶進程,通知進程切換的時機,這樣就避免了用戶進程主動查詢的操做。而這個信號就是VSYNC
信號
官方傳送門:
VSYNC
官方描述以下:VSYNC
信號用來同步整個顯示流程(Display Pipeline)
。顯示流程
包括app
渲染、SurfaceFlinger
合成、HWC
(硬件渲染)組成
(這部分感受原文更容易理解)VSYNC synchronizes the time apps wake up to start rendering, the time SurfaceFlinger wakes up to composite the screen, and the display refresh cycle.
VSYNC
信號應該由顯示驅動產生,這樣才能達到最佳效果。可是Android
爲了能運行在不支持VSYNC
機制的設備上,也提供了用軟件來模擬產生VSYNC
信號的手段
官網描述:經過
HWC
來產生VSYNC
信號,並經過接口回調將事件進行發送(主要是SurfaceFlinger
進行事件接收)
基礎知識鋪墊完成,咱們先來看看Surface
官網對
Surface
的描述是:A surface is an interface for a producer to exchange buffers with a consumer.
上面描述的是一種生產者-消費者
的模式,而Surface
充當了中間銜接的角色。
以Activity
中UI
顯示爲例:
生產者
的任務就是把圖形繪製在Surface
對象上
SurfaceView
組件了SurfaceFlinger
做爲消費者
會把全部Surface
對應的圖像層混合在一塊兒
最後消費者
將其輸出到FrameBuffer
中,這樣在屏幕上就看到最後合成的圖像了
下面咱們從Java層
開始分析Surface
Surface
的建立過程應用開發中不多直接使用Surface
,由於每一個Activity
中都已經建立好了各自的Surface
對象,一般只有一些特殊的應用才須要在Activity
以外再去建立Surface
,例如相機、視頻播放應用。
不過,一般這些應用也是經過建立SurfaceView
來使用Surface
須要注意的是,在應用中不能直接去建立一個可用的Surface
對象(也能夠說直接建立出的對象沒什麼實際用途),由於這樣建立出的Surface
對象和SurfaceFlinger
之間沒有任何關聯。
該如何創見一個可用的Surface
對象呢?
咱們看下Surface
類的定義:
public class Surface implements Parcelable {
long mNativeObject;
// 一個無參構造,空實現
public Surface() {
}
public Surface(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new IllegalArgumentException("surfaceTexture must not be null");
}
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock) {
mName = surfaceTexture.toString();
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
}
複製代碼
Surface
類對外有兩個構造方法:
一個是無參構造,實現也是空的
readFromParcel()
反序列化用的readFromParcel()
方法public void readFromParcel(Parcel source) {
if (source == null) {
throw new IllegalArgumentException("source must not be null");
}
synchronized (mLock) {
mName = source.readString();
mIsSingleBuffered = source.readInt() != 0;
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
}
}
複製代碼
另外一個須要傳遞SurfaceTexture
對象做爲參數
SurfaceTexture
對象聰明的咱們會發現,readFromParcel()
和new Surface(SurfaceTexture surfaceTexture)
都會執行一個setNativeObjectLocked()
方法,咱們看下方法實現:
private void setNativeObjectLocked(long ptr) {
if (mNativeObject != ptr) {
...
mNativeObject = ptr;
...
}
}
複製代碼
setNativeObjectLocked()
方法很簡單,只是更新了mNativeObject
變量的數值,重點就是參數了:
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
這兩個setNativeObjectLocked()
方法的調用從參數的命名來看是針對不一樣數據來源的處理。
看來要看下native
的實現了,以nativeReadFromParcel()
爲例來看下:
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, jlong nativeObject, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
...
android::view::Surface surfaceShim;
// 解析 Parcel 數據,並填充到 native層 的 Surface對象 surfaceShim
surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
// 將傳入的指針轉換爲 native層 的 Surface對象 self
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
// 比對 surfaceShim 和 self 中的 Binder 對象 IGraphicBufferProducer
if (self != nullptr
&& (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
// 判斷是同一個 IGraphicBufferProducer ,直接返回當前指針
return jlong(self.get());
}
sp<Surface> sur;
if (surfaceShim.graphicBufferProducer != nullptr) {
// IGraphicBufferProducer 不一樣
// 且 surfaceShim 的 IGraphicBufferProducer 不爲空
// 建立一個新的 Surface 對象 sur
sur = new Surface(surfaceShim.graphicBufferProducer, true);
sur->incStrong(&sRefBaseOwner);
}
...
// 將 sur 的指針返回給 Java 層
return jlong(sur.get());
}
複製代碼
到這裏咱們不難看出
Java層
的Surface
對象最重要的數據是mNativeObject
變量
mNativeObject
是一個指針,指向的native
層的Surface
對象native
層在判斷是否新建Surface
對象的邏輯依賴的是IGraphicBufferProducer
對象
IGraphicBufferProducer
對象是一個Binder
引用對象那麼接下來咱們重點就是這個IGraphicBufferProducer
了。
咱們先看下native層
中Surface
類的繼承關係:
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase>
複製代碼
ANativeObjectBase
的定義以下:
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{...}
複製代碼
整理成繼承關係圖就是:
再看下Surface
的構造方法:
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
...
mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
... // 初始化各類成員變量
}
複製代碼
從構造函數的參數能夠看到,native層
的Surface
將IGraphicBufferProducer
對象保存到了mGraphicBufferProducer
變量中。
暫時仍是不清楚mGraphicBufferProducer
哪裏來的,咱們去WMS
中看看
WMS
中Surface
的建立過程此處要從Activity
的onResume()
生命週期提及
onResume()
到WMS.relayoutWindow()
咱們已經知道,當AMS
觸發onResume()
生命週期時會調用到ActivityThread
類的handleResumeActivity()
方法,代碼以下:
public void handleResumeActivity(...) {
...
// 此處會觸發 onResume 聲明週期回調
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
ViewManager wm = a.getWindowManager();
...// 省略不少 Window 處理邏輯
wm.addView(decor, l);
...
}
複製代碼
從方法中能夠看到,執行完onResume()
後調用了ViewManager
的addView(decor, l)
方法
知識點:在
onResume
方法調用後才真正進行View
的添加
ViewManager
是一個接口類,真正的實現類是WindowManagerImpl
,addView()
方法實現也很簡單:
public void addView(...) {
applyDefaultToken(params);
mGlobal.addView(...);
}
複製代碼
調用了mGlobal
的addView()
方法方法,mGlobal
的類型是WindowManagerGlobal
,代碼以下:
public void addView(...) {
...
ViewRootImpl root;
synchronized (mLock) {
...
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
root.setView(view, wparams, panelParentView);
}
...
}
}
複製代碼
WindowManagerGlobal
類的addView()
先是建立了一個新的ViewRootImpl
對象,而後調用了ViewRootImpl
對象的setView()
方法。
ViewRootImpl
類中setView()
調用流程以下:
class ViewRootImpl{
/** * 這裏也是直接 new 出來的對象 Surface * 前面已經介紹過,這個對象須要和 native層進行綁定後才能正常使用 */
public final Surface mSurface = new Surface();
ViewRootImpl(Context context, Display display){
...
// 此方法會建立 Session 對象
mWindowSession = WindowManagerGlobal.getWindowSession();
...
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
// 內部方法調用
requestLayout();
...
// 此方法會建立 SurfaceSession
res = mWindowSession.addToDisplay(...);
...
}
}
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
...
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
...
// 異步執行 mTraversalRunnable
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
...
performTraversals();
...
}
}
private void performTraversals() {
...
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException {
...
// 調用 mWindowSession 的 relayout 方法,並將 mSurface 對象傳遞過去
int relayoutResult = mWindowSession.relayout(..., mSurface);
...
return relayoutResult;
}
}
複製代碼
setView()
方法最後調用的是mWindowSession
的relayout()
方法。
mWindowSession
類型是IWindowSession
,是一個Binder
引用對象。真正的Binder
服務實現是com.android.server.wm.Session
類:
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
public Session(WindowManagerService service, ...) {
mService = service;
...
}
public int relayout(..., Surface outSurface) {
...
int res = mService.relayoutWindow(..., outSurface);
...
return res;
}
}
複製代碼
終於走到了WMS
中,調用的是WMS
的relayoutWindow()
方法
WMS.relayoutWindow()
到SurfaceControl.nativeCreate()
和Surface
相關的調用關係以下:
class WindowManagerService{
public int relayoutWindow(..., Surface outSurface) {
...
result = createSurfaceControl(outSurface, ...);
...
return result;
}
private int createSurfaceControl(Surface outSurface, ...) {
...
WindowSurfaceController surfaceController;
...
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
...
if (surfaceController != null) {
surfaceController.getSurface(outSurface);
} else {
...
outSurface.release();
}
return result;
}
}
class WindowSurfaceController{
public WindowSurfaceController(...) {
...
final SurfaceControl.Builder b = win.makeSurface()
...
.setMetadata(windowType, ownerUid);
mSurfaceControl = b.build();
}
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
}
}
class Surface{
public void copyFrom(SurfaceControl other) {
if (other == null) {
throw new IllegalArgumentException("other must not be null");
}
long surfaceControlPtr = other.mNativeObject;
if (surfaceControlPtr == 0) {
throw new NullPointerException(
"null SurfaceControl native object. Are you using a released SurfaceControl?");
}
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newNativeObject);
}
}
}
複製代碼
在上面的relayoutWindow()
方法中
WMS
先經過winAnimator
的createSurfaceLocked()
方法獲得了一個WindowSurfaceController
對象
WindowSurfaceController
對象封裝了SurfaceControl
對象WMS
調用WindowSurfaceController
對象的getSurface()
方法來對Surface
對象進行填充
getSurface()
對象只是利用自身保存的mSurfaceControl
對象Surface
的copyFrom()
方法對Surface
對象進行填充處理copyFrom()
方法
nativeGetFromSurfaceControl()
方法獲得一個native
層的Surface
對象指針setNativeObjectLocked()
方法將指針保存到成員變量mNativeObject
中關鍵點又回到了native
層的nativeGetFromSurfaceControl()
方法,它的代碼以下:
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
sp<Surface> surface(ctrl->getSurface());
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner);
}
return reinterpret_cast<jlong>(surface.get());
}
複製代碼
nativeGetFromSurfaceControl()
方法是經過native
層的SurfaceControl
的getSurface()
方法來獲取Surface
對象。咱們再看下getSurface()
方法:
sp<Surface> SurfaceControl::getSurface() const {
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
}
sp<Surface> SurfaceControl::generateSurfaceLocked() const {
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
複製代碼
在SurfaceControl
的getSurface()
方法中
mSurfaceData
指針爲空時纔會經過generateSurfaceLocked()
方法建立一個新的Surface
對象
Surface
對象中很關鍵的IGraphicBufferProducer
在這裏傳入的是SurfaceControl
的成員變量mGraphicBufferProducer
mSurfaceData
指針從getSurface()
方法的邏輯中咱們不難看出,SurfaceControl
對象和Surface
對象是關聯在一塊兒的,一對一的關係
更關鍵的是構造Surface
對象的核心參數居然是SurfaceControl
中的成員變量。。。。。。。。
沒辦法,要先搞定SurfaceControl
的建立過程才能夠
前面已經講過,WMS
經過winAnimator.createSurfaceLocked()
方法建立了WindowSurfaceController
對象,WindowSurfaceController
對象初始化時就會建立SurfaceControl
,咱們看下建立過程:
class WindowStateAnimator{
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
...
// mSession 的類型就是前面提到的 Session 類,IWindowSession Binder服務類
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, ...);
...
return mSurfaceController;
}
}
class WindowSurfaceController{
public WindowSurfaceController(SurfaceSession s, ...) {
...
final SurfaceControl.Builder b = win.makeSurface()
...
.setMetadata(windowType, ownerUid);
// 經過 Builder 模式建立的
mSurfaceControl = b.build();
}
}
class SurfaceControl{
public static class Builder {
...
public SurfaceControl build() {
...
// 調用私有構造方法
return new SurfaceControl(mSession, ...);
}
...
}
private SurfaceControl(SurfaceSession session, ...) throws OutOfResourcesException, IllegalArgumentException {
...
mNativeObject = nativeCreate(session, ...);
if (mNativeObject == 0) {
throw new OutOfResourcesException(
"Couldn't allocate SurfaceControl native object");
}
...
}
}
複製代碼
能夠看到
SurfaceControl
對象的全程都攜帶着一個SurfaceSession
對象。SurfaceSession
對象在SurfaceControl
的構造方法中經過nativeCreate()
傳遞到了native層
,用來建立native層
的對象Java層
的Surface
對象同樣,SurfaceControl
對象也會將native層
對象的指針保存到mNativeObject
中關鍵仍是在nativeCreate()
方法,咱們繼續。。
nativeCreate()
方法以下:
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, ...) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
...
sp<SurfaceControl> surface;
status_t err = client->createSurfaceChecked(
String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
...
return reinterpret_cast<jlong>(surface.get());
}
複製代碼
nativeCreate()
方法中又出現了一個新的類型SurfaceComposerClient
,並且native層
的SurfaceControl
對象就是經過它的createSurfaceChecked()
來建立的
耐心、耐心、耐心。。。。 崩潰的時候多說幾回
上面方法中的SurfaceComposerClient
對象是經過android_view_SurfaceSession_getClient()
方法獲得的,看JNI
的命名格式能夠推算它和SurfaceSession
類也有關係,內容以下:
sp<SurfaceComposerClient> android_view_SurfaceSession_getClient( JNIEnv* env, jobject surfaceSessionObj) {
return reinterpret_cast<SurfaceComposerClient*>(
env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
複製代碼
android_view_SurfaceSession_getClient()
方法中的參數surfaceSessionObj
是在Java層
調用nativeCreate()
方法時傳遞的參數,類型是SurfaceSession
。
這裏其實是將
SurfaceSession
對象中成員變量mNativeClient
的值取出來後,轉換爲SurfaceComposerClient
對象返回
這說明SurfaceComposerClient
對象和SurfaceSession
對象也是一塊兒建立出來的,咱們繼續看下SurfaceSession
和SurfaceComposerClient
的建立過程
SurfaceControl.nativeCreate
到ComposerService
須要知道的一個重要前提:每一個用戶進程在
WMS
中都有且只有一個對應的Session
對象,前面已經介紹Session
是一個實現了IWindowSession
接口的Binder
服務類
Session
的成員變量mSurfaceSession
是在Session
對象初始化時建立的,那麼Session
對象在何時建立的呢?
跟蹤代碼發現流程以下:
ViewRootImpl
初始化時會調用WindowManagerGlobal.getWindowSession()
方法WindowManagerGlobal.getWindowSession()
會調用WMS
的openSession()
方法openSession()
方法中便會在WMS
中建立一個新的Session
對象對於SurfaceSession
的初始化,是在Session
對象的windowAddedLocked()
方法中,那麼windowAddedLocked()
方法又是在哪裏調用的呢?
一樣,咱們跟蹤下方法調用:
ViewRootImpl
的setView()
方法中會調用mWindowSession.addToDisplay(...)
方法mWindowSession.addToDisplay(...)
方法會調用WMS
的addWindow()
方法WMS
的addWindow()
方法會調用WindowState
的attach()
方法attach()
方法會調用Session
的windowAddedLocked()
方法這樣就串起來了,如今咱們能夠繼續學習SurfaceSession
的構造方法了:
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}
複製代碼
很簡潔,源碼註釋也很關鍵。咱們看下SurfaceSession
的nativeCreate()
方法:
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
// 請注意此方法的調用
// 該方法會觸發 onFirstRef() 的執行
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
複製代碼
nativeCreate()
直接建立了一個SurfaceComposerClient
對象,也沒有參數。不過SurfaceComposerClient
類是從RefBase
類派生出來的,咱們看下它的構造函數和onFirstRef
函數:
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT)
{
}
// onFirstRef() 是 RefBase 提供的回調接口
// 當首次調用 incStrong() 方法時便會執行此方法
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
// 此處 rootProducer 應該爲 null
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
// 因此在此處執行的是 sf->createConnection() 方法
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
複製代碼
構造方法很簡單,只是將mStatus
設置爲NO_INIT
。
重點是在onFirstRef()
方法中
ComposerService
的getComposerService()
方法來獲得一個ISurfaceComposer
的指針createConnection()
方法建立一個ISurfaceComposerClient
對象mClient
指向這個ISurfaceComposerClient
對象咳咳咳,按照上面的調用流程咱們尚未找到關於
IGraphicBufferProducer
的信息,如今又多出來了一個ISurfaceComposerClient
。。。
好吧好吧,梳理下這部分關係先
WMS
中Surface
關係總結上面介紹的WMS
中涉及和Surface
有關的類關係以下:
看上去就挺複雜的:
SurfaceControl
和Surface
是成對建立的,考慮到繪製等需求,它們的數量會比較多Session
、SurfaceSession
和SurfaceComposerClient
對象是和鏈接WMS
的用戶進程的數量相同SurfaceComposerClient
的做用是建立Surface
SurfaceControl
經過SurfaceComposerClient
來獲取Surface
SurfaceComposerClient
是ComposerService
的具體實現類ComposerService
再到SurfaceFlinger
ComposerService
是一個單例模式的普通類,定義以下:
class ComposerService : public Singleton<ComposerService>
{
sp<ISurfaceComposer> mComposerService;
sp<IBinder::DeathRecipient> mDeathObserver;
Mutex mLock;
ComposerService();
void connectLocked();
void composerServiceDied();
friend class Singleton<ComposerService>;
public:
static sp<ISurfaceComposer> getComposerService();
};
複製代碼
前面的onFirstRef()
方法中調用了ComposerService
類的靜態方法getComposerService()
,咱們看下它的實現:
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
...
}
return instance.mComposerService;
}
複製代碼
getComposerService()
經過調用父類Singleton
的getInstance()
方法來取得實例對象,而後調用ComposerService
的connectLocked()
方法:
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
...
}
複製代碼
connectLocked()
方法中鏈接了SurfaceFlinger
服務對象,而後把對象指針保存到mComposerService
中。
ComposerService
其實只是SurfaceFlinger
的代理,它把SurfaceFlinger
服務接口包裝了起來
getComposerService()
返回的就是mComposerService
對象指針,也就是SurfaceFlinger
的Binder
對象。
前面提到,SurfaceComposerClient
對象的onFirstRef()
方法中
ComposerService::getComposerService()
得到了mComposerService
指針後mComposerService
對象的createConnection()
方法。SurfaceFlinger
服務的相關函數接口。SurfaceFlinger
中接口實現以下:
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this));
}
static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
status_t err = client->initCheck();
if (err == NO_ERROR) {
return client;
}
return nullptr;
}
複製代碼
createConnection()
函數中建立了一個Client
類型對象,而後將其返回給調用者,關於Client
類的定義以下:
class Client : public BnSurfaceComposerClient
複製代碼
Client
是一個Binder
服務類,雖然叫Client
。而mComposerService
保存的也就是這個服務對象的指針
咱們再回到SurfaceControl
的建立過程
nativeCreate()
方法中調用了SurfaceComposerClient
的createSurfaceChecked()
方法status_t SurfaceComposerClient::createSurfaceChecked(...) {
sp<SurfaceControl> sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
}
}
return err;
}
複製代碼
createSurfaceChecked()
方法
SurfaceFlinger::Client
對象的createSurface()
方法去進行建立操做
handle
、gbp
、parentHandle
都是Binder
對象
sp<IGraphicBufferProducer> gbp
就是咱們找尋已久的參數。。。。SurfaceFlinger
中進行設置SurfaceFlinger::Client
對象的createSurface()
執行完成沒有錯誤,建立SurfaceControl
對象SurfaceFlinger
中建立Surface
SurfaceFlinger::Client
對象的createSurface()
方法以下:
status_t Client::createSurface(..., sp<IGraphicBufferProducer>* gbp) {
...
return mFlinger->createLayer(..., gbp, &parent);
}
複製代碼
調用的是SurfaceFlinger
的createLayer()
方法,代碼以下:
status_t SurfaceFlinger::createLayer(..., sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
...
status_t result = NO_ERROR;
sp<Layer> layer;
String8 uniqueName = getUniqueLayerName(name);
// 這裏分紅了兩種建立模式:Normal 和 Color
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal: // normal
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor: // color
result = createColorLayer(client,
uniqueName, w, h, flags,
handle, &layer);
break;
default:
result = BAD_VALUE;
break;
}
...
return result;
}
複製代碼
createLayer()
方法按照兩種模式進行建立
一種是eFXSurfaceNormal
模式,經過createBufferLayer()
方法建立,方法以下:
status_t SurfaceFlinger::createBufferLayer(..., sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) {
// initialize the surfaces
switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
// 透明或半透明設置格式爲 RGBA
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
// 不透明設置格式爲 RGBX
format = PIXEL_FORMAT_RGBX_8888;
break;
}
sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
status_t err = layer->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
*handle = layer->getHandle();
// 咱們關注的 IGraphicBufferProducer 在這裏賦值了
*gbp = layer->getProducer();
*outLayer = layer;
}
return err;
}
複製代碼
BufferLayer
對象,調用對象的setBuffers()
設置寬高和像素格式Surface
中重要的gdp
等參數也會在這裏進行設置一種是eFXSurfaceColor
模式,經過createColorLayer()
方法建立:看參數傳入和gdp
沒啥關係,不用太過關注
status_t SurfaceFlinger::createColorLayer(...,
sp<IBinder>* handle, sp<Layer>* outLayer)
{
*outLayer = new ColorLayer(this, client, name, w, h, flags);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
複製代碼
ColorLayer
對象,也沒有setBuffers()
等操做咱們重點關注eFXSurfaceNormal
模式的建立邏輯
終於,咱們找到了
sp<IGraphicBufferProducer>* gbp
的來源,是經過layer->getProducer()
方法
layer->getProducer()
方法以下:
sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
return mProducer;
}
複製代碼
layer->getProducer()
方法比較簡單,只是返回了一個mProducer
對象的指針
mProducer
對象的建立是在BufferLayer::onFirstRef()
方法中
void BufferLayer::onFirstRef() {
Layer::onFirstRef();
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
// 經過 BufferQueue 的 createBufferQueue 方法建立 producer 和 consumer
BufferQueue::createBufferQueue(&producer, &consumer, true);
// 建立 mProducer
mProducer = new MonitoredProducer(producer, mFlinger, this);
...
}
複製代碼
onFirstRef()
方法中
BufferQueue::createBufferQueue()
方法建立producer
和consumer
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;
}
複製代碼
producer
對象建立MonitoredProducer
對象MonitoredProducer
頭文件定義以下:
class MonitoredProducer : public BnGraphicBufferProducer {
public:
MonitoredProducer(const sp<IGraphicBufferProducer>& producer,
const sp<SurfaceFlinger>& flinger,
const wp<Layer>& layer);
virtual ~MonitoredProducer();
...
private:
// 在 BufferLayer 的 onFirstRef() 中經過 BufferQueue::createBufferQueue() 建立
sp<IGraphicBufferProducer> mProducer;
sp<SurfaceFlinger> mFlinger;
wp<Layer> mLayer;
}
複製代碼
雖然MonitoredProducer
是一個Binder
實體對象,但從業務上來說它僅僅是個代理
真正管理圖像緩衝區的是經過
BufferQueue::createBufferQueue()
方法建立的BufferQueueProducer producer
對象
終於接近IGraphicBufferProducer
的本質了,到這裏咱們其實能夠結束WMS
中Surface
的建立流程了。先回顧下整個建立流程:
上圖分了三部分
Surface
和Session
的初始化ViewRootImpl
的setView()
中執行performTraversals()
SurfaceControl
對象Surface
對象進行填充scheduleTraversals()
調用流程來看,這是一個異步過程ViewRootImpl
的setView()
中執行session.addToDisplay()
SurfaceSession
對象native
層建立SurfaceComposerClient
對象須要注意的一點是SurfaceControl
對象的建立須要SurfaceSession
對象做爲參數。但setView()
方法中SurfaceSession
對象的建立放在了SurfaceControl
對象的後面
一開始其實挺疑惑的,核心仍是在scheduleTraversals()
的異步調用過程,感興趣的同窗能夠參考:scheduleTraversals
到底作了什麼
IGraphicBufferProducer
咱們一直強調Surface
中最重要的對象是IGraphicBufferProducer
,最後咱們也找到了它對應的Binder
實體對象MonitoredProducer
對象
MonitoredProducer
對象來講,它又關聯了一個sp<IGraphicBufferProducer>
對象mProducer
mProducer
對象具體的實現類是BufferQueueProducer
前面說Surface
像一張畫布,那麼Surface
爲何要和BufferQueue
關聯呢?
24幀
畫面才能造成比較真實的動畫效果
CPU
解碼獲得的,準備它們須要時間Surface
中Surface
須要緩衝區來臨時保存數據BufferQueue
操做官方圖解以下:
從前面的BufferQueue::createBufferQueue()
中能夠看出:
MonitoredProducer
對象也只是一個代理,真正的業務處理對象是在createBufferQueue()
方法中建立的BufferQueueProducer
對象BufferQueueCore
和BufferQueueConsumer
對象的建立BufferQueue
-Core|Producer|Consumer
前面已經介紹,在BufferLayer
的onFirstRef()
方法中經過BufferQueue::createBufferQueue()
方法建立了三個對象:BufferQueueCore
、BufferQueueConsumer
和BufferQueueProducer
其中
BufferQueueCore
是核心,把BufferQueueConsumer
和BufferQueueProducer
對象鏈接在了一塊兒
關於BufferQueue
的工做方式,官網有個比較直觀的敘述,翻譯以下:
Consumer
建立並擁有BufferQueue
數據結構,而且可存在於與其Producer
不一樣的進程中Producer
須要緩衝區時,它會經過調用dequeueBuffer()
從BufferQueue
請求一個可用的緩衝區,並指定緩衝區的寬度、高度、像素格式和用法標誌。Producer
填充緩衝區並經過調用queueBuffer()
將緩衝區返回到隊列Consumer
經過acquireBuffer()
獲取該緩衝區並使用該緩衝區的內容Consumer
操做完成後,它會經過調用releaseBuffer()
將該緩衝區返回到隊列流程較爲清晰,咱們從源碼層面再看下,首先是BufferQueueCore
中的關鍵定義:
class BufferQueueCore : public virtual RefBase {
friend class BufferQueueProducer;
friend class BufferQueueConsumer;
...
private:
BufferQueueDefs::SlotsType mSlots;
}
複製代碼
C++
中的friend
在這裏用來使Producer
和Consumer
能夠訪問Core
中的成員變量。mSlots
是一個64
長度的BufferSlot
數組,稍後細講
再看下BufferQueueProducer
類的定義:
class BufferQueueProducer : public BnGraphicBufferProducer,
private IBinder::DeathRecipient {
...
private:
sp<BufferQueueCore> mCore;
}
複製代碼
再看看BufferQueueConsumer
類的定義:
class BufferQueueConsumer : public BnGraphicBufferConsumer {
...
private:
sp<BufferQueueCore> mCore;
}
複製代碼
不難看出,Producer
對象和Consumer
對象經過mCore
對象鏈接在一塊兒,查看Producer
和Consumer
這兩個對象的具體方法咱們就會發現,不少操做都是直接經過mCore
對象的函數來實現的。
Consumer
和Producer
的接口定義繼續看下BufferQueueConsumer
和BufferQueueProducer
的基類,分別是BnGraphicBufferProducer
和BnGraphicBufferConsumer
,定義以下:
class BnGraphicBufferProducer : public BnInterface<IGraphicBufferProducer>
class BnGraphicBufferConsumer : public SafeBnInterface<IGraphicBufferConsumer>
複製代碼
它們主要是實現了兩套IGraphicBufferProducer
和IGraphicBufferConsumer
的Binder
接口,主要都是操做BufferQueue
的相關接口,定義以下:
IGraphicBufferProducer
class IGraphicBufferProducer : public IInterface
{
public:
...
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) = 0;
...
virtual status_t queueBuffer(int slot, const QueueBufferInput& input, QueueBufferOutput* output) = 0;
...
virtual status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;
virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) = 0;
...
};
複製代碼
BufferQueueProducer
類是IGraphicBufferProducer
的實現Producer
相關功能時須要先經過connect()
方法創建鏈接Producer
使用完畢後須要調用disconnect()
斷開鏈接IGraphicBufferConsumer
class IGraphicBufferConsumer : public IInterface {
public:
...
virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen, uint64_t maxFrameNumber = 0) = 0;
virtual status_t detachBuffer(int slot) = 0;
virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) = 0;
virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0;
virtual status_t consumerDisconnect() = 0;
...
};
複製代碼
BufferQueueConsumer
是接口IGraphicBufferConsumer
的實現Consumer
相關功能時,需經過consumerConnect()
方法創建鏈接
IConsumerListener
對象,這是一個回調接口onFrameAvailable()
函數來通知Consumer
來取數據acquireBuffer()
releaseBuffer()
來把緩衝區歸還給BufferQueueCore
BufferQueue
的狀態轉換前面提到BufferQueueCore
類中定義了一個64項
的數組mSlots
:
static constexpr int NUM_BUFFER_SLOTS = 64;
namespace BufferQueueDefs {
typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
}
BufferQueueDefs::SlotsType mSlots;
複製代碼
mSlots
數組元素類型是BufferSlot
,關鍵定義以下:
struct BufferSlot {
...
sp<GraphicBuffer> mGraphicBuffer;
...
BufferState mBufferState;
...
};
複製代碼
mGraphicBuffer
指向圖像緩衝區GraphicBuffer
的指針
GraphicBuffer
對應的即是真正的圖像緩存數據mBufferState
表示圖像緩衝區的狀態BufferState
定義以下:
struct BufferState {
uint32_t mDequeueCount;
uint32_t mQueueCount;
uint32_t mAcquireCount;
bool mShared;
}
複製代碼
BufferState
中4個變量對應的狀態以下:
狀態\變量 | 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 |
狀態之間的轉換關係以下:
結合前面提到的接口,咱們看下整個狀態轉換過程的時序圖:
到這裏,咱們已經大致瞭解了從Surface
到SurfaceFlinger
的數據通道,dequeueBuffer()
等方法的細節就不深刻分析了,其中會涉及GraphicBuffer
的初始化過程,不影響咱們對總體的掌握(主要是太難了。。。。。),不過如下幾點須要注意:
GraphicBuffer
初始化時便會執行Gralloc
模塊的allocate()
方法申請共享內存緩衝區FrameBuffer
緩衝區的狀況下,申請到的就是FrameBuffer
的緩衝區顯示原理和Surface
相關的內容到此結束了,還有不少不完善的地方,後面再來找補吧(又挖一坑)
關於Android
圖形顯示的學習還剩下SurfaceFlinger
和圖像輸出過程兩部分,但願清明節前搞定,(ง •̀_•́)ง