一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Android 圖形顯示框架

 mynotebook 2022-10-09 發(fā)布于湖南

本篇對Android圖形顯示框架做一個(gè)概述,內(nèi)容主要包含:SurfaceSession創(chuàng)建和銷毀(添加/刪除窗口),Surface創(chuàng)建和銷毀,BufferQueue創(chuàng)建,以及BufferQueue的dequeueBuffer和queueBuffer、acquire和release大致流程梳理。

顯示框架概述

Android與用戶進(jìn)行圖形界面的交互,例如各個(gè)應(yīng)用程序,他們的對話框、按鈕、菜單等圖形窗口。

這些窗口的管理都是由WindowManager負(fù)責(zé),窗口管理位于Java層,真正的實(shí)現(xiàn)者是運(yùn)行在System_server進(jìn)程空間中的WindowManagerService

frameworks/base/services/java/com/android/server/SystemServer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices() {
.......
traceBeginAndSlog('StartWindowManagerService');
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
traceEnd();
......
}

應(yīng)用程序負(fù)責(zé)修改繪制窗口中的內(nèi)容,而WindowManager負(fù)責(zé)窗口的生命周期、幾何屬性、坐標(biāo)變換信息、用戶輸入焦點(diǎn)、動畫等功能

他還管理著窗口狀態(tài)的變化,如窗口位置、大小、透明度以及Z-order(前后遮蓋順序)等一系列的邏輯判斷。

這些WindowManager功能由一系列接口或類構(gòu)成,包括ViewManager、WindowManager、WindowManagerImpl、WindowManagerService等。

SurfaceFlinger負(fù)責(zé)分配應(yīng)用程序所需的圖形緩沖區(qū),并對系統(tǒng)中的整個(gè)圖形窗口進(jìn)行composition(合成)。

最終,圖形窗口會更新顯示到Display顯示器上。

圖片


顯示過程的三個(gè)進(jìn)程

Android顯示的整個(gè)過程由 App 進(jìn)程、System_server 進(jìn)程、SurfaceFlinger進(jìn)程一起配合完成。

  1. App進(jìn)程:App需要將自己的內(nèi)容顯示在屏幕上,所以需要負(fù)責(zé)發(fā)起Surface創(chuàng)建的請求。同時(shí)觸發(fā)對控件的測量、布局、繪制以及輸入事件的派發(fā)處理,這些主要在ViewRootImpl中觸發(fā);

  2. System_server進(jìn)程:主要是WindowManagerService,負(fù)責(zé)接收App請求,同時(shí)和SurfaceFlinger建立連接,向SurfaceFlinger發(fā)起具體請求創(chuàng)建Surface,并且創(chuàng)建Surace的輔助管理類SurfaceControl(和window一一對應(yīng))(AMS作用是統(tǒng)一調(diào)度所有App的Activity);

  3. SurfaceFlinger:為App創(chuàng)建具體的Surface,在SurfaceFLinger對應(yīng)成Layer,然后負(fù)責(zé)管理、合成所有圖層,最終顯示。

圖片


Activity、Window、PhoneWindow、DecorView、View的對應(yīng)關(guān)系

  1. Window:每一個(gè)Activity都包含一個(gè)Window對象(抽象類,提供了繪制窗口的一組通用API),通常由PhoneWindow實(shí)現(xiàn)。

在Activity.java中定義:private Window mWindow;

  • 一個(gè)Activity對應(yīng)創(chuàng)建一個(gè)Surface

  1. PhoneWindow:繼承于Window,是Window類的具體實(shí)現(xiàn)。該類內(nèi)部包含了一個(gè)DecorView對象,該DecorView對象是所有應(yīng)用窗口(Activity界面)的根View。

簡而言之,PhoneWindow類是把一個(gè)FrameLayout類,即DecorView對象進(jìn)行一定的包裝,將他作為應(yīng)用窗口的根View,并提供一組通用的窗口操作接口。

PhoneWindow是Android中最基本的窗口系統(tǒng),每個(gè)Activity都會創(chuàng)建一個(gè)PhoneWindow對象,是Activity和整個(gè)View系統(tǒng)交互的接口。

在Activity.java的attach函數(shù)實(shí)例化:mWindow = new PhoneWindow(this, window, activityConfigCallback);

  1. DecorView:PhoneWindow構(gòu)造函數(shù)中定義,繼承FrameLayout類,是所有應(yīng)用窗口的根View。

在PhoneWindow.java中定義,構(gòu)造函數(shù)中初始化:private DecorView mDecor;

相關(guān)debug方法:

  • adb shell dumpsys activity

  • adb shell dumpsys window

![window包含關(guān)系]](phonewindow.png)


Activity生命周期

Activity onResume添加窗口

onCreate方法中調(diào)用setContentView來設(shè)置布局,此時(shí)只是完成了View Tree的創(chuàng)建。此處參考HWUI繪制文章

真正通知WMS添加窗口,是在回調(diào)onResume完成的。

調(diào)用onResume的方法在ActivityThread.java中是handleResumeActivity。之后調(diào)用到WMS.java的addWindow。

圖片


App進(jìn)程中完成添加窗口操作

  1. 當(dāng)一個(gè)新窗口(Window)被創(chuàng)建的時(shí)候,在ActivityThread.java的handleResumeActivity中調(diào)用addView(),然后調(diào)用到WindowManagerImpl的addView()函數(shù)。

frameworks/base/core/java/android/view/WindowManagerImpl.java
1
2
3
4
5
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
  1. 這個(gè)函數(shù)將實(shí)際操作委托給mGlobal成員完成,這個(gè)成員隨著WindowManagerImpl的創(chuàng)建而被初始化:private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

WindowManagerGlobal是一個(gè)單例模式,即一個(gè)進(jìn)程中最多僅有一個(gè)WindowManagerGlobal實(shí)例。

  1. 調(diào)用mGlobal的addView函數(shù)后,將會創(chuàng)建一個(gè)ViewRootImpl對象,并且將窗口的控件、布局參數(shù)、ViewRootImpl對象入?yún)⒌絪etView函數(shù)中,這個(gè)動作將導(dǎo)致ViewRootImpl向WMS添加新的窗口、申請Surface創(chuàng)建、繪制動作等。這才真正意義的完成了窗口的添加操作。

frameworks/base/core/java/android/view/WindowManagerGlobal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
......
root = new ViewRootImpl(view.getContext(), display);

view.setLayoutParams(wparams);

mViews.add(view);
mRoots.add(root);
mParams.add(wparams);

// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}


窗口移除序列圖(Activity destroy)

窗口被刪除,Activity執(zhí)行了handleDestroyActivity函數(shù):

圖片

Surface Destroy(Activity pause或者stop狀態(tài))

可以結(jié)合以下Surface創(chuàng)建部分一起梳理,針對的情況是Surface被destroy,從framework/base到SurfaceFlinger模塊Layer析構(gòu)的流程。


但是就Activity而言,并沒有被銷毀,而是類似按了home鍵返回桌面,或者在后臺運(yùn)行的狀態(tài),具體可以通過日志觀察。

SurfaceSession創(chuàng)建

此處是接著上面添加窗口的流程,分為以下兩部分。

mGlobal.addView中創(chuàng)建ViewRootImpl對象

  1. 新建ViewRootImpl對象的時(shí)候,調(diào)用構(gòu)造函數(shù),會從WindowManagerGlobal中獲取一個(gè)窗口session。

mWindowSession = WindowManagerGlobal.getWindowSession();

  1. 在WindowManagerGlobal中會通過Binder IPC跨進(jìn)程創(chuàng)建一個(gè)session。

Session主要用于進(jìn)程間通信,其他應(yīng)用程序想要和WMS通信就需要經(jīng)過Session,每個(gè)應(yīng)用程序進(jìn)程都會對應(yīng)一個(gè)Session,WMS保存這些Session用來記錄所有向WMS提出窗口管理服務(wù)的客戶端。

frameworks/base/core/java/android/view/WindowManagerGlobal.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@UnsupportedAppUsage
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
// Emulate the legacy behavior. The global instance of InputMethodManager
// was instantiated here.
// TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
//獲取WMS對象
IWindowManager windowManager = getWindowManagerService();
//創(chuàng)建Session
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
});
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}

  1. WMS繼承IWindowManager.Stub,調(diào)用到openSessio函數(shù),創(chuàng)建一個(gè)新的session對象, 返回值是IWindowSession類型。用于在APP進(jìn)程和WMS之間建立聯(lián)系。

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
1
2
3
4
5
6
7

final class H extends android.os.Handler {
@Override
public IWindowSession openSession(IWindowSessionCallback callback) {
return new Session(this, callback);
}
}

mGlobal.addView中調(diào)用ViewRootImpl.setView

在前面mGlobal創(chuàng)建ViewRootImpl對象之后,會調(diào)用ViewRootImpl對象的setView,然后通知到WMS創(chuàng)建一個(gè)SurfaceSession,建立WindowManagerService和Surfacelinger的連接。

一個(gè)SurfaceSession代表著一個(gè)到SurfaceFlinger的連接會話,在這個(gè)連接會話里,可以創(chuàng)建一個(gè)或多個(gè)surface,最后這些surface被合成送到Display上顯示。

大致過程:(查看下面的序列圖)

  1. 在setView()中調(diào)用mWindowSession.addToDisplay, mWindowSession是IWindowSession接口類型,而Session.java實(shí)現(xiàn)了該接口;

  2. Session.java 中調(diào)用mService.addWindow(…), mService是WMS類型;

  3. WMS.java的addWindow()創(chuàng)建WindowState對象win,調(diào)用win.attach()

  4. frameworks/base/services/core/java/com/android/server/wm/WindowState.java 調(diào)用attach

  5. frameworks/base/services/core/java/com/android/server/wm/Session.java 調(diào)用windowAddedocked,創(chuàng)建SurfaceSession類型的mSurfaceSession

  6. frameworks/base/core/java/android/view/SurfaceSession.java 構(gòu)造函數(shù)調(diào)用JNI,然后在android_view_SurfaceSession.cpp中的nativeCreate創(chuàng)建SurfaceComposerClient, 調(diào)用Refase的incStrong然后實(shí)現(xiàn)onFirstRef,通過調(diào)用CreateConnection()建立和SF的連接;

  7. SF.cpp 調(diào)用CreateConnection()返回SF的Client類的Binder代理BpSurfaceComposerClient;


Surface創(chuàng)建

App進(jìn)程請求創(chuàng)建Surface

Surface是Android圖形系統(tǒng)的核心部分,圖形界面上的一個(gè)窗口或?qū)υ捒虻榷紝?yīng)著一個(gè)Surface。

而這個(gè)Surface是一塊繪制區(qū)域的抽象,它對應(yīng)著Server服務(wù)端Surfacelinger中的一個(gè)圖層Layer,這個(gè)圖層的背后是一塊圖形緩沖區(qū)GraphicBuffer,Client客戶端的應(yīng)用程序的UI使用軟件繪制、硬件繪制在Surface上各種渲染操作時(shí),繪制操作的結(jié)果其實(shí)也就是在該圖形緩沖區(qū)中。

這部分的內(nèi)容是梳理Surface創(chuàng)建的過程。

  1. 在ViewRootImpl對象中,setView到requestLayout函數(shù)請求布局,到調(diào)用scheduleTraversals,該函數(shù)里面在Choreographer.java層層調(diào)用到Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);

此處的action即是新的線程啟動。

  1. 啟動ViewRootImp中單獨(dú)的線程TraversalRunnable,然后調(diào)用到關(guān)鍵函數(shù)performTraversals()。

這個(gè)關(guān)鍵函數(shù)有兩個(gè)主要的函數(shù):

  • relayoutWindow() ->布局窗口

  • performDraw() ->繪制渲染

請求創(chuàng)建Surface就從relayoutWindow函數(shù)開始。

在這個(gè)方法中調(diào)用IWindowSession的relayout,會調(diào)用到Session.java,然后調(diào)用到WMS的relayoutWindow從而達(dá)到跨進(jìn)程:(流程圖查看下面單獨(dú)章節(jié)的序列圖)

frameworks/base/core/java/android/view/ViewRootImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
......
//此處relayout會調(diào)用到WMS的relayoutWindow
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
mPendingMergedConfiguration, mSurfaceControl, mTempInsets);
if (mSurfaceControl.isValid()) {
mSurface.copyFrom(mSurfaceControl);
} else {
destroySurface();
}
}

System_server進(jìn)程 —— WMS

  1. 跨進(jìn)程到WMS后,從relayoutWindow函數(shù)調(diào)用到createSurfaceControl(outSurfaceControl)。

(1)然后先是在WindowStateAnimator創(chuàng)建一個(gè)WindowSurfaceController對象,作為調(diào)用到WindowStateAnimator.java的createSurfaceLocked函數(shù)的返回值。

在createSurfaceLocked函數(shù)中,會new一個(gè)WindowSurfaceController對象,從而調(diào)用他的構(gòu)造函數(shù)。

在他的構(gòu)造函數(shù)中會創(chuàng)建一個(gè)SurfaceControl內(nèi)部類Builder對象,調(diào)用該對象的build函數(shù);

(2) WMS.java中調(diào)用WindowStateAnimator.java的createSurfaceLocked函數(shù)之后,會執(zhí)行以下邏輯:

a. 如果surfaceController不為空,調(diào)用WindowSurfaceController的getSurfaceControl;

b. WindowSurfaceController.java調(diào)用

getSurfaceControl, outSurfaceControl.copyFrom(mSurfaceControl);,而mSurfaceControl就是之前的構(gòu)造函數(shù)創(chuàng)建的。此處的copyFrom會經(jīng)過JNI調(diào)用到Native層, 然后讀取SurfaeControl。

  1. 在Builder內(nèi)部類的build函數(shù)中創(chuàng)建Java層的SurfaceControl對象,在SurfaceControl的構(gòu)造函數(shù)中調(diào)用JNI層的nativeCreate函數(shù);

  2. android_view_SurfaceControl.cpp的nativeCreate函數(shù)會調(diào)用SurfaceComposerClient.cpp的createSurfaceChecked函數(shù),創(chuàng)建一個(gè)surface(實(shí)際上是SurfaceControl),然后將surface返回。

圖片


SurfaceFlinger進(jìn)程

SurfaceComposerClinet.cpp位于frameworks/native/libs/gui模塊。

libgui庫主要被JNI層中的代碼調(diào)用,從而和Surfacelinger進(jìn)程進(jìn)行交互,可以看做是Java層的Bn端,是SurfaceFlinger的Bp端。

比如此處的SurfaceComposerClinet通過Binder IPC(ISurfaceComposerClinet.cpp),跨進(jìn)程到SurfaceFlinger進(jìn)程。

  1. SurfaceComposerClinet作為Bp客戶端調(diào)用:

frameworks/native/libs/gui/SurfaceComposerClient.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
PixelFormat format,
sp<SurfaceControl>* outSurface, uint32_t flags,
SurfaceControl* parent,
LayerMetadata metadata) {
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, std::move(metadata),
&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;
}
  1. Bn服務(wù)端是surfaceflinger模塊的Client.cpp,此時(shí)跨進(jìn)程到SurfaceFlinger進(jìn)程,調(diào)用createSurface,從而請求到SurfaceFlinger創(chuàng)建Surface:

frameworks/native/services/surfaceflinger/Client.cpp
1
2
3
4
5
6
7
8
status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags, const sp<IBinder>& parentHandle,
LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) {
// We rely on createLayer to check permissions.
return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
parentHandle);
}
  1. 在SurfaceFlinger::createLayer中創(chuàng)建Layer(創(chuàng)建surface的請求到SurfaceFlinger進(jìn)程中就是創(chuàng)建Layer),創(chuàng)建的Layer有四種:

(1)createBufferQueueLayer
(2)createBufferStateLayer
(3)createColorLayer
(4)createContainerLayer

通常情況下創(chuàng)建的是第一種Layer——BufferQueueLayer(在P中是BufferLayer),會創(chuàng)建一個(gè)<sp>BufferQueueLayer強(qiáng)指針對象。

SF.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, PixelFormat& format,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp,
sp<Layer>* outLayer) {
.....
sp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(
LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
status_t err = layer->setDefaultBufferProperties(w, h, format);
if (err == NO_ERROR) {
*handle = layer->getHandle();
*gbp = layer->getProducer();
*outLayer = layer;
}

ALOGE_IF(err, 'createBufferQueueLayer() failed (%s)', strerror(-err));
}

序列圖

該序列圖包含上面部分的流程,包含APP進(jìn)程和WMS進(jìn)程之間的Session創(chuàng)建、SurfaceSession創(chuàng)建、Surface創(chuàng)建。

圖片


BufferQueue

關(guān)于BufferQueue只大致梳理他的創(chuàng)建流程,以及在渲染過程中的dequeuebuffer和queuebuffer流程、在合成過程中的acquire和release流程。

關(guān)于和GraphicsBuffer和再底層的邏輯,暫時(shí)不梳理。

BufferQueue概述

創(chuàng)建BuffeQueueLayer對象的onFirstRef中會創(chuàng)建一個(gè)BufferQueue。

BufferQueue是buffer流轉(zhuǎn)的中轉(zhuǎn)站。具體分成四個(gè)步驟:

  1. 生產(chǎn)者dequeue一塊buffer,buffer狀態(tài)->DEQUEUED,持有者->Producer,之后生產(chǎn)者可以填充數(shù)據(jù)(渲染繪制)。在dequeueBuffer之前,buffer狀態(tài)是free,持有者是BufferQueue;

  2. 生產(chǎn)者填充完數(shù)據(jù)后,進(jìn)行queue操作,buffer->QUEUED,持有者->BufferQueue。操作后producer會回調(diào)BufferQueue的onFrameAvailable函數(shù),通知消費(fèi)者有可用的buffer;

  3. 消費(fèi)者進(jìn)行acquire取出Buffer,buffer->ACQUIRED,持有者->Consumer;

  4. 消費(fèi)者消費(fèi)完這塊buffer(已經(jīng)合成),進(jìn)行release操作釋放,歸還給BufferQueue


BufferQueue狀態(tài)

  • DEQUEUED 狀態(tài):

Producer dequeue一個(gè)Buffer后,這個(gè)Buffer就變?yōu)?DEQUEUED 狀態(tài),release Fence發(fā)信號后,Producer就可以修改Buffer的內(nèi)容,我們稱為release Fence。

此時(shí)Buffer被Producer占用。

DEQUEUED狀態(tài)的Buffer可以遷移到 QUEUED 狀態(tài),通過queueBuffer或attachBuffer流程。也可以遷移到FREE裝,通過cancelBuffer或detachBuffer流程。

  • QUEUED 狀態(tài):

Buffer繪制完后,queue到BufferQueue中,給Consumer進(jìn)行消費(fèi)。此時(shí)Buffer可能還沒有真正繪制完成,必現(xiàn)要等對應(yīng)的Fence發(fā)信號出來后,才真正完成。

此時(shí)Buffer是BufferQueue持有,可以遷移到ACQUIRED狀態(tài),通過acquireBuffer流程。而且可以遷移到FREE狀態(tài),如果另外一個(gè)Buffer被異步的queue進(jìn)來。

  • ACQUIRED 狀態(tài):

Buffer已經(jīng)被Consumer獲取,但是也必須要等對應(yīng)的Fence發(fā)信號才能被Consumer讀寫,找個(gè)Fence是從Producer那邊,queueBuffer的時(shí)候傳過來的。

我們將其稱為acquire fence。此時(shí),Buffer被Consumer持有。狀態(tài)可以遷移到FREE狀態(tài),通過releaseBuffer或detachBuffer流程。

除了從acquireBuffer流程可以遷移到ACQUIRED狀態(tài),attachBuffer流程也可以遷移到ACQUIRED狀態(tài)。

  • FREE 狀態(tài):

FREE狀態(tài),說明Buffer被BufferQueue持有,可以被Producer dequeue,它將遷移到DEQUEUED狀態(tài),通過dequeueBuffer流程。

  • SHARED狀態(tài):

SHARED狀態(tài)是一個(gè)特殊的狀態(tài),SHARED的Buffer并不參與前面所說的狀態(tài)遷移。它說明Buffer被用與共享Buffer模式。

除了FREE狀態(tài),它可以是其他的任何狀態(tài)。它可以被多次dequeued, queued, 或者 acquired。這中共享Buffer的模式,主要用于VR等低延遲要求的場合。


BufferQueue創(chuàng)建以及創(chuàng)建一個(gè)監(jiān)聽

BufferQueueLayer::onFirstRef調(diào)用BufferQueue::createBufferQueue()創(chuàng)建了bufferQueue、生產(chǎn)者、消費(fèi)者,在創(chuàng)建生產(chǎn)者和消費(fèi)者的過程中,將他們綁定到同一個(gè)BufferQueue上。

之后會創(chuàng)建一個(gè)BufferLayerConsumer對象mConsumer,這個(gè)對象繼承了ConsumerBase類,所以會回調(diào)基類的構(gòu)造函數(shù),注冊一個(gè)監(jiān)聽對象到BufferQueue(空對象)。

真正的監(jiān)聽是在mConsumer->setContentsChangedListener(this)基類構(gòu)造函數(shù)中還會調(diào)用consumerConnect將消費(fèi)者關(guān)聯(lián)到BufferQueue中。

此時(shí)監(jiān)聽對象就賦給了BufferQueue的mConsumerListener成員(調(diào)用BufferQueueConsumer的connect函數(shù))。

這個(gè)監(jiān)聽對象會在queueBuffer是觸發(fā),由生產(chǎn)者回調(diào)注冊到BufferQueue的幀可用通知。

圖片


DequeuBuffer

BufferQueue創(chuàng)建后,首先由生產(chǎn)者執(zhí)行 dequeueBuffer 請求一塊Buffer。

Dequeue和Queue的操作都是在硬件渲染(軟件繪制暫不考慮)的過程中,在ThreadedRenderer::draw函數(shù)中,updateRootDisplayList創(chuàng)建好一個(gè)RootDisplayList后,開始渲染一幀,在這時(shí)調(diào)用父類的syncAndDrawFrame函數(shù),這個(gè)函數(shù)層層調(diào)到CanvasContext::draw函數(shù),然后依次調(diào)用三個(gè)函數(shù):

  1. mRenderPipeline->getFrame 執(zhí)行dequeueBuffer請求一塊buffer

  2. draw 填充buffer

  3. mRenderPipeline->swapBuffers 執(zhí)行queueBuffer送到BufferQueue

在此處dequeuBuffer和queueBuffer兩個(gè)操作調(diào)到gui/Surface.cpp的兩個(gè)對應(yīng)函數(shù),這個(gè)流程基本一樣。

大致都從SkiaOpenPipeline.cpp -> EglManager.cpp -> eglApi.cpp -> ANativeWindow.cpp,之后到Bp客戶端libgui庫的Surface.cpp,執(zhí)行具體操作。

Surface::dequeueBuffer中調(diào)用IGraphicBufferProducer::dequeueBuffer。然后remote()->transact(DEQUEUE_BUFFER,data,&reply)調(diào)用到Bn端BufferQueueProducer::dequeueBuffer函數(shù)。

  1. 首先查找mSlots[found]的序列號found,mSlots是存放Buffer的地方,他的數(shù)量是64。即至多存放64個(gè)buffer。

  2. found是從waitForFreeSlotThenRelock中獲取:

  • 從非Free的buffer中統(tǒng)計(jì)dequeue和acquire的數(shù)量;

  • 判斷dequeueBufferCount數(shù)量不能大于最大允許dequeueBuffer的數(shù)量;

  • slot的獲取主要來自兩個(gè)集合,mFreeSlots和mFreeBuffers;兩者包含的所有狀態(tài)都是free,區(qū)別在于前者沒有attached,后者以及attached;如果調(diào)用來自dequeueBuffer優(yōu)先選擇前者,如果調(diào)用來自attachBuffer,優(yōu)先選擇后者;

  • 如果沒找到符合要求的buffer或者queue的buffer還有太多沒有完成,就要等待這個(gè)buffer被acquired或者released,或者修改最大的buffer數(shù)量。

  1. 找到可用的slot,還要判斷是否重新分配空間:如果Buffer(本質(zhì)上是GraphicBuffer)是空,并且需要重新分配空間,則對這個(gè)mSlots[found]初始化;

  2. new GraphicBuffer為mSlots分配一個(gè)GraphicBuffer,賦值給BufferQueueCore中的變量mSlots[]的mGraphicBuffer;

mSlots[*outSlot].mGraphicBuffer = graphicBuffer;

Surface::dequeueBuffer從服務(wù)端申請到Buffer后,通過requestBuffer將客戶端的buffer和服務(wù)端的buffer指向同一塊物理內(nèi)存。

具體是IGraphicBufferPruducer代理中通過REQUEST_BUFFER狀態(tài),在onTransact中將申請的GraphicBuffer,即mSlots[slot].mGraphicBuffer。將其寫入reply,等待客戶端讀取。


QueueBuffer

queueBuffer是在渲染一幀后通過mRenderPipeline->swapBuffers調(diào)用到Surface::queueBuffer。將填充完數(shù)據(jù)的buffer放入BufferQueue,并且通過監(jiān)聽者通知消費(fèi)者對象開始消費(fèi)。

在Bn端BufferQueueProducer::queueBuffer L977中調(diào)用:frameAvailableListener->onFrameAvailable(item);

通知消費(fèi)者,在BufferQueueLayer::onFrameAvailable中調(diào)用:mFlinger->signalLayerUpdate();

觸發(fā)SurfaceFlinger的消息循環(huán)機(jī)制,開始處理SurfaceFlinger合成事件。


序列圖

圖片

acquire & release

消費(fèi)者SurfaceFlinger通過acquire從BufferQueue取出一塊buffer消費(fèi)。消費(fèi)(合成)之后釋放。

序列圖

圖片

本文作者 : sunwengang 
本文使用 署名-非商業(yè)性使用-相同方式共享 4.0 國際 (CC BY-NC-SA 4.0) 協(xié)議 
本文鏈接 : https://alonealive./Blog/2020/07/30/2020/200730_android_GraphicsFramework/

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    好吊日在线观看免费视频| 午夜久久精品福利视频| 亚洲国产性生活高潮免费视频| 麻豆视频传媒入口在线看| 亚洲a级一区二区不卡| 午夜视频免费观看成人| 日韩高清一区二区三区四区| 国产欧美精品对白性色| 丝袜人妻夜夜爽一区二区三区| 色丁香之五月婷婷开心| 国产精品偷拍视频一区| 我要看日本黄色小视频| 日本黄色高清视频久久| 亚洲国产精品av在线观看| 伊人国产精选免费观看在线视频| 国产永久免费高清在线精品| 加勒比东京热拍拍一区二区| 日本高清一道一二三区四五区| 91精品国产综合久久福利| 国产亚州欧美一区二区| 人妻少妇系列中文字幕| 亚洲最新中文字幕一区| 日韩不卡一区二区三区色图 | 国产精品伦一区二区三区四季| 91亚洲精品亚洲国产| 美女激情免费在线观看| 免费观看一级欧美大片| 中文字幕人妻av不卡| 深夜福利亚洲高清性感| 午夜精品久久久免费视频| 在线免费观看黄色美女| 午夜精品国产精品久久久| 国产肥妇一区二区熟女精品| 欧美黄色黑人一区二区| 国产精品蜜桃久久一区二区| 国产肥妇一区二区熟女精品 | 欧洲精品一区二区三区四区| 日本在线不卡高清欧美| 日本高清中文精品在线不卡| 国产亚洲精品一二三区| 亚洲国产av一二三区|