首頁 > 軟體

基於Android10渲染Surface的建立過程

2022-08-14 14:02:06

一、Surface 概述

OpenGL ES/Skia定義了一組繪製介面的規範,為什麼能夠跨平臺? 本質上需要與對應平臺上的本地視窗建立連線。也就是說OpenGL ES負責輸入了繪製的命令,但是需要一個 "畫布" 來承載輸出結果,最終展示到螢幕。這個畫布就是本地視窗。

因此,每個平臺的有著不一樣的本地視窗的實現。Android平臺上是 ANativeWindow。

疑問:

  • 那麼如何將OpenGL在地化? 通過 EGL來對OpenGL ES來進行設定。關鍵點就是提供在地化視窗。
  • 在地化視窗的作用是什麼? 本地視窗是OpenGL ES和 物理螢幕之間的橋樑。

1.1 Android本地視窗簡述

Android圖形系統提供的本地視窗,可以分為兩類:

  • FrameBufferNativeWindow

面對SF(SurfaceFlinger)。它通過HAL層的Gralloc系統呼叫(alloc/free)來分配核心中的FrameBuffer幀緩衝區。 這個幀緩衝區就代表了物理螢幕(fb*驅動節點,*表示螢幕數。如fb0主螢幕、fb1等)。 FrameBuffer的數量一般情況下是2,也就是雙緩衝。當然還有三倍緩衝。

  • Surface

面向應用程式。對應的是記憶體中一塊緩衝區,稱為:GraphicBuffer。是由SF來進行分配。app從SF中獲取一塊GraphicBuffer, 通過OpenGL/Skia將圖形資料繪製(軟體/硬體)到GraphicBuffer上。最終SF會把各個應用的GraphicBuffer資料進行合成,最終 通過 FrameBufferNativeWindow 輸出到螢幕上。

有了一個整體的概念,接下來就好理解很多。

二、引出SurfaceSession

2.1 從WindowManagerImpl的addView()說起

app:
WindowManagerImpl.addView()
  WindowManagerGlobal.addView()
    ViewRootImpl的setView()
      IWindowSession.addToDisplay()
      
WMS:
      new WindowState
        WindowState.attach()
          session.windowAddedLocked()
            new SurfaceSession()

view新增到window的過程中, 從WindowManagerImpl 的 addView(),到WindowManagerGlobal(構造方法中會在system server 程序中建立一個Session物件)的addView()。最後會呼叫 ViewRootImplsetView()方法。 內部會呼叫 IWindowSession 的addToDisplay() 方法。IWindowSession是WMS提供的一個binder服務(實現類就是Session)。

2.2 IWindowSession.windowAddedLocked()

內部會建立一個WindowState 物件。 呼叫 WindowState的 attach()方法。最終調到Session中的windowAddedLocked(),會建立 一個SurfaceSession物件。這就是我們要找的的跟SurfaceFlinger建立聯絡的地方。

 SurfaceSession mSurfaceSession;
void windowAddedLocked(String packageName) {
  mPackageName = packageName;
  mRelayoutTag = "relayoutWindow: " + mPackageName;
  if (mSurfaceSession == null) {
  // 一個程序只有一個session,因此也只建立一次 SurfaceSession 物件
      
      // 建立 SurfaceSession 物件
      mSurfaceSession = new SurfaceSession();
      
      // 每個session 都存入WMS中的         
      mService.mSessions.add(this);
      
      if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
          mService.dispatchNewAnimatorScaleLocked(this);
      }
  }
  mNumWindow++; // 程序中所有視窗的數量+1
}

一個應用程序對應一個Session物件,一個Session物件對應一個SurfaceSession。 WMS會把 這個Session 儲存起來。也就是說WMS 會把所有跟SurfaceFlinger保持連線狀態的應用Session儲存起來。

2.3 SurfaceSession 建立過程

這個類的範例代表了和SurfaceFlinger的一個連線。我們可以通過它 建立一個或多個 Surface 物件。

2.3.1 構造方法

> SurfaceSession.java
private long mNativeClient; // SurfaceComposerClient*

public SurfaceSession() {
    //native 方法
    mNativeClient = nativeCreate();
}

> frameworks/base/core/jni/android_view_SurfaceSession.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
    // 新建一個 SurfaceComposerClient 物件
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
    //返回SurfaceComposerClient物件的參照到java層。
    return reinterpret_cast<jlong>(client);
}

SurfaceComposerClient 是什麼呢?

2.3.2 SurfaceComposerClient

在 SurfaceComposerClient第一次被參照的時候會走onFirstRef()方法。

> frameworks/native/libs/gui/SurfaceComposerClient.cpp
void SurfaceComposerClient::onFirstRef() {
    //建立sf代理binder物件sf,型別為 ISurfaceComposer
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;
        //建立一個 ISurfaceComposerClient 物件,用來跨程序呼叫
        conn = sf->createConnection();
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}
  • ISurfaceComposer 實現類就是 SurfaceFlinger物件。在server程序的代理物件是 ComposerService。This class defines the Binder IPC interface for accessing various SurfaceFlinger features.
  • 通過SF.createConnection(),建立一個 ISurfaceComposerClient 物件 mClient,用來跨程序呼叫。

那麼 ISurfaceComposerClient的實現類是哪個呢? 繼續看看 SF.createConnection()

2.3.3 SurfaceFlinger.createConnection()

注意,此時是在SF程序。

> frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    // new client物件。
    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;
}
> frameworks/native/services/surfaceflinger/Client.h
class Client : public BnSurfaceComposerClient{...
  class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> {...

原來,ISurfaceComposerClient的實現類就是 SF中定義的 Client。也是一個binder服務。 我們回到 SurfaceComposerClient 類,它持有 ISurfaceComposerClient的binder參照 mClient。通過 mClient實現與SF通訊

2.3 小結

  • Session 類中,建立了一個 SurfaceSession 物件,內部參照c++層的 SurfaceComposerClient 物件。
  • SurfaceComposerClient 物件是通過SF建立的另一個binder服務。減輕SF的工作量。
  • SurfaceComposerClient 物件則通過 mClient成員(ISurfaceComposerClient)代理binder,後續用來建立 Surface。

到目前為止,WMS中應用程序對應的Session物件已經建立了與SF的聯絡。

三、Surface的建立

3.1 Java層的Surface

ViewRootImpl 類成員變數 :

ViewRootImpl.java

// 任何執行緒都可以存取這個物件,只需要加鎖就可以了。
public final Surface mSurface = new Surface();

呼叫的是空參構造,因此 此時的Surface只是Java層的空殼而已。

3.2 App端的 relayoutWindow()

當SF收到vsync訊號後,通過Choreographer監聽,分發到app程序。app收到vsync訊號後doFrame(),再到主執行緒呼叫 doTraversal() ->performTraversals():

> ViewRootImpl.java
private void performTraversals() {
    // 呼叫 relayoutWindow 
    relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
    //...
    
    // Ask host how big it wants to be
    // 三大流程
    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    //...
    performLayout(lp, mWidth, mHeight);
    //```
    performDraw();
    //...
}
    > ViewRootImpl.java
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
    boolean insetsPending) throws RemoteException {
    //...
    // 1  mWindowSession是 IWindowSession 物件,呼叫relayout()
     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,
                 // 此處傳入的  mSurfaceControl物件 
                mPendingMergedConfiguration, mSurfaceControl, mTempInsets);
                
        if (mSurfaceControl.isValid()) {
            // 2 從 mSurfaceControl 中複製 surface 
            mSurface.copyFrom(mSurfaceControl);
        } else {
            // 無效,則銷燬
            destroySurface();
        }
        
     //... 
    return relayoutResult;
}
  • relayout() 傳入 mSurfaceControl,跨程序呼叫到了WMS端。
  • copyFrom() ,從 mSurfaceControl 中獲取 Surface。

SurfaceControl 是啥?

SurfaceControl 可以控制一個被合成系統管理的、正在螢幕上顯示的surface。它是Buffer資料和視窗的metadata的連結器。 通過這個 SurfaceControl構造的surface,app可以直接提交buffer資料到合成系統進行合成。此外還可以通過SurfaceControl.Transaction 來修改buffer的被顯示的屬性。如旋轉、平移、裁剪。

3.3 SurfaceControl空參構造

是 ViewRootImpl 類成員變數:

private final SurfaceControl mSurfaceControl = new SurfaceControl();

SurfaceControl 的空參構造方法,啥都沒幹!目前也是個空殼。

3.4 小結

目前可以看出,在開始繪製時,呼叫了WMS的session.relayout(SurfaceControl mSurfaceControl)方法之後。就可以從SurfaceControl中得到 Surface物件。

那 session.relayout() 內部是如何做到的呢? 繼續看 Session.relayout()

3.5 WMS端 Session.relayout()

>Session.java
@Override
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
        Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
        Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
        DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
        SurfaceControl outSurfaceControl, InsetsState outInsetsState) {
        
    // 繼續呼叫 WMS的 relayoutWindow()
    int res = mService.relayoutWindow(this, window, seq, attrs,
            requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
            outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
            outStableInsets, outsets, outBackdropFrame, cutout,
            mergedConfiguration, outSurfaceControl, outInsetsState);
    return res;
}
 > WMS.java
outSurfaceControl 從app程序傳遞到了WMS程序。 表示結果接收。它實現了parcelable介面,跨程序傳遞到了WMS中。
public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,
        int requestedWidth, int requestedHeight, int viewVisibility, int flags,
        long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
        Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
        DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
        SurfaceControl outSurfaceControl, InsetsState outInsetsState) {
        //...
        try {
            //呼叫 createSurfaceControl
            result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
        } catch (Exception e) {
            ...
        }
        //...
        
}           
> WMS.java
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win,
        WindowStateAnimator winAnimator) {
    if (!win.mHasSurface) {
        result |= RELAYOUT_RES_SURFACE_CHANGED;
    }
    // 宣告一個 WindowSurfaceController
    WindowSurfaceController surfaceController;
    
    try {
        //1  建立 WindowSurfaceController 物件
        surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
    } finally {
    }
    if (surfaceController != null) {
        // 2 從得到 WindowSurfaceController 物件中,獲取 SurfaceController
        surfaceController.getSurfaceControl(outSurfaceControl);
    } else {
        // For some reason there isn't a surface.  Clear the
        // caller's object so they see the same state.
        Slog.w(TAG_WM, "Failed to create surface control for " + win);
        outSurfaceControl.release();
    }

    return result;
}

最終:

  • winAnimator.createSurfaceLocked()得到WindowSurfaceController物件
  • 從得到 WindowSurfaceController 物件中,獲取 SurfaceController返回給outSurfaceControl

winAnimator 是 WindowStateAnimator型別。

3.5.1 winAnimator.createSurfaceLocked()

> WindowStateAnimator.java
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
    final WindowState w = mWin;

    if (mSurfaceController != null) {
        // 如果有,則返回
        return mSurfaceController;
    }
    //...
    // Set up surface control with initial size.
    try {
        // 否則建立一個 WindowSurfaceController
        mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
                attrs.getTitle().toString(), width, height, format, flags, this,
                windowType, ownerUid);
        // ...
    } catch (OutOfResourcesException e) {
     //...
     }
    return mSurfaceController;
}

createSurfaceLocked() 就是建立了一個 WindowSurfaceController 物件。WindowSurfaceController的構造方法中會建立一個SurfaceControl物件。

3.5.2 WindowSurfaceController構造方法

> WindowSurfaceController.java
public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
        int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
    mAnimator = animator;
    mSurfaceW = w;
    mSurfaceH = h;

    title = name;
    mService = animator.mService;
    final WindowState win = animator.mWin;
    mWindowType = windowType;
    mWindowSession = win.mSession;

    Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
    // 1 呼叫的是 WindowState的 makeSurface()方法
    final SurfaceControl.Builder b = win.makeSurface()
            .setParent(win.getSurfaceControl())
            .setName(name)
            .setBufferSize(w, h)
            .setFormat(format)
            .setFlags(flags)
            .setMetadata(METADATA_WINDOW_TYPE, windowType)
            .setMetadata(METADATA_OWNER_UID, ownerUid);
            // 2 建立SurfaceControl物件 
    mSurfaceControl = b.build();
    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
  >SurfaceControl.java 
  public SurfaceControl build() {
            if (mWidth < 0 || mHeight < 0) {
                throw new IllegalStateException(
                        "width and height must be positive or unset");
            }
            if ((mWidth > 0 || mHeight > 0) && (isColorLayerSet() || isContainerLayerSet())) {
                throw new IllegalStateException(
                        "Only buffer layers can set a valid buffer size.");
            }
            // 建立物件 ,呼叫了 SurfaceControl的有參構造方法。
            return new SurfaceControl(
                    mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);
        }

呼叫SurfaceControl的有參構造方法,構造了一個SurfaceControl物件。 還記得在3. 3,ViewRootImpl的成員變數mSurfaceControl,呼叫的是空參構造,啥都沒做。

但是,現在SurfaceControl的有參構造做了什麼呢? 我們深入看看。

SurfaceControl的有參構造:

long mNativeObject; // package visibility only for Surface.java access
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
        SurfaceControl parent, SparseIntArray metadata)
                throws OutOfResourcesException, IllegalArgumentException {
                //... 
                
                //注意這裡第一個引數是  SurfaceSession
        mNativeObject = nativeCreate(session, name, w, h, format, flags,
                            parent != null ? parent.mNativeObject : 0, metaParcel);
}

>frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
        jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
        jobject metadataParcel) {
    ScopedUtfChars name(env, nameStr);
    //這個就是之前建立 SurfaceSession建立時候的 SurfaceComposerClient物件。SF的代理服務。
    sp<SurfaceComposerClient> client;
    if (sessionObj != NULL) {
        // 之前建立的 mClient
        client = android_view_SurfaceSession_getClient(env, sessionObj);
    } else {
        
        client = SurfaceComposerClient::getDefault();
    }
    // 父 SurfaceControl
    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    // 宣告 SurfaceControl
    sp<SurfaceControl> surface;
    // 視窗的 metadata。 因為SurfaceControl 本身就是 surface和 metadata的接合器。
    LayerMetadata metadata;
    
    Parcel* parcel = parcelForJavaObject(env, metadataParcel);
    if (parcel && !parcel->objectsCount()) {
        status_t err = metadata.readFromParcel(parcel);
        if (err != NO_ERROR) {
          jniThrowException(env, "java/lang/IllegalArgumentException",
                            "Metadata parcel has wrong format");
        }
    }
    // 呼叫SF程序的 createSurfaceChecked(),建立surface物件 
    status_t err = client->createSurfaceChecked(
            String8(name.c_str()), w, h, format, &surface, flags, parent, std::move(metadata));
    if (err == NAME_NOT_FOUND) {
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return 0;
    } else if (err != NO_ERROR) {
        jniThrowException(env, OutOfResourcesException, NULL);
        return 0;
    }

    surface->incStrong((void *)nativeCreate);
    // 返回 SurfaceControl的 jlong 參照 
    return reinterpret_cast<jlong>(surface.get());
}

>frameworks/native/libs/gui/SurfaceComposerClient.cpp
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
                                                     PixelFormat format,
                                                     sp<SurfaceControl>* outSurface, uint32_t flags,
                                                     const sp<IBinder>& parentHandle,
                                                     LayerMetadata metadata,
                                                     uint32_t* outTransformHint) {
    sp<SurfaceControl> sur;
    status_t err = mStatus;

    if (mStatus == NO_ERROR) {
        // 
        sp<IBinder> handle;
        // gpb,buffer資料的生產者
        sp<IGraphicBufferProducer> gbp;

        uint32_t transformHint = 0;
        int32_t id = -1;
        // mClient 具體實現類是 SF的Client服務 。來建立surface
        err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
                                     &handle, &gbp, &id, &transformHint);

        if (outTransformHint) {
            *outTransformHint = transformHint;
        }
        ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
        if (err == NO_ERROR) {
            // 終於建立了一個native層的 SurfaceControl物件。注意,此時是native層的有參構造!!
            *outSurface =
                    new SurfaceControl(this, handle, gbp, id, w, h, format, transformHint, flags);
        }
    }
    return err;
}
繼續看native層的有參構造: 
>frameworks/native/libs/gui/SurfaceControl.cpp
SurfaceControl::SurfaceControl(
        const sp<SurfaceComposerClient>& client,
        const sp<IBinder>& handle,
        const sp<IGraphicBufferProducer>& gbp,
        bool owned)
    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
    //賦值了一些成員變數
{
}

總結:

  • WMS 的relayout() 通過 WindowSurfaceControl物件來建立 SurfaceControl 物件。此時的 SurfaceControl物件,不僅僅存在java層,也會在native層建立一個SurfaceControl物件。
  • native層中,內部會通過之前建立連線surfaceSession來向SF請求buffer、metadata等資訊,給SurfaceControl物件賦值。

注意,以上的邏輯還是在WMS的native層。 而跨程序的 createSurface()呼叫到底幹了啥?

3.6 SF端 ISurfaceComposerClient.createSurface()

此時進入SF程序。 Client 就是 ISurfaceComposerClient 的實現類。

frameworks/native/services/surfaceflinger/Client.cpp
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.
    // 終於呼叫了SF。 建立一個layer
    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
                                 parentHandle);
}
> frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp 
status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
                                     uint32_t h, PixelFormat format, uint32_t flags,
                                     LayerMetadata metadata, sp<IBinder>* handle,
                                     sp<IGraphicBufferProducer>* gbp,
                                     const sp<IBinder>& parentHandle,
                                     const sp<Layer>& parentLayer) {
    if (int32_t(w|h) < 0) {
       // 寬高不能為負數
        return BAD_VALUE;
    }
    status_t result = NO_ERROR;
    // 宣告一個 layer物件
    sp<Layer> layer; 

    String8 uniqueName = getUniqueLayerName(name);
    // metadata
    if (metadata.has(METADATA_WINDOW_TYPE)) {
        int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0);
        if (windowType == 441731) {
            metadata.setInt32(METADATA_WINDOW_TYPE, InputWindowInfo::TYPE_NAVIGATION_BAR_PANEL);
            primaryDisplayOnly = true;
        }
    }
    // 根據flag 建立不同的layer物件。
    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
        case ISurfaceComposerClient::eFXSurfaceBufferQueue:
            // 1 建立bufferQueue,只看這一種
            result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),
                                            format, handle, gbp, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceBufferState:
            result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata),
                                            handle, &layer);
            break;
        case ISurfaceComposerClient::eFXSurfaceColor:
        case ISurfaceComposerClient::eFXSurfaceContainer:
           ...
        default:
            result = BAD_VALUE;
            break;
    }
   ...
    // 2 繼續呼叫 addClientLayer
    result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer,
                            addToCurrentState);
    ...
    return result;
}
  • 建立了 BufferQueueLayer 物件,裡面持有 sp<BufferLayerConsumer> mConsumer和 sp<IGraphicBufferProducer> mProducer,也就是GraphicBuffer的生產者和消費者物件。
  • 加入到 layers 全域性的集合中。

3.6.1 SF.createBufferQueueLayer()

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

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) {
    // initialize the surfaces
    // 格式
    switch (format) {
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
        format = PIXEL_FORMAT_RGBX_8888;
        break;
    }
    // 建立layer
    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) {
        // 賦值 gbp生產者 
        *handle = layer->getHandle();
        *gbp = layer->getProducer();
        *outLayer = layer;
    }
    ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err));
    return err;
}

3.6.2 SurfaceFlingerFactory.createBufferQueueLayer

frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp

sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override {
            return new BufferQueueLayer(args);
        }

3.6.3 BufferQueueLayer 構造方法

繼承關係:

class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener 
{...
class BufferLayer : public Layer {...

3.6.4 BufferQueueLayer.onFirstRef()

void BufferQueueLayer::onFirstRef() {
    BufferLayer::onFirstRef();

    // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
    // 宣告生產者和消費者 
    sp<IGraphicBufferProducer> producer;
    sp<IGraphicBufferConsumer> consumer;
    // BufferQueue 初始化
    BufferQueue::createBufferQueue(&producer, &consumer, true);
    // MonitoredProducer分裝了 producer,方便SF監聽
    mProducer = new MonitoredProducer(producer, mFlinger, this);
    {
        // Grab the SF state lock during this since it's the only safe way to access RenderEngine
        Mutex::Autolock lock(mFlinger->mStateLock);
        // 封裝了BufferLayerConsumer封裝了 consumer
        mConsumer =
           new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
    }
    mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
    mConsumer->setContentsChangedListener(this);
    mConsumer->setName(mName);

    // BufferQueueCore::mMaxDequeuedBufferCount is default to 1
    if (!mFlinger->isLayerTripleBufferingDisabled()) {
      //設定為2
        mProducer->setMaxDequeuedBufferCount(2);
    }

    if (const auto display = mFlinger->getDefaultDisplayDevice()) {
        updateTransformHint(display);
    }
}

重點:

  • 宣告了 sp<IGraphicBufferProducer> producersp<IGraphicBufferConsumer> consumer;
  • 呼叫 BufferQueue::createBufferQueue(&producer, &consumer, true);來建立這兩個物件。

3.6.5 BufferQueue::createBufferQueue()

frameworks/native/libs/gui/BufferQueue.cpp

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        bool consumerIsSurfaceFlinger) {
    // BufferQueueCore 物件
    sp<BufferQueueCore> core(new BufferQueueCore());
    //BufferQueueProducer 生產物件
    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
    // BufferQueueConsumer 消費物件
    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));

    *outProducer = producer;
    *outConsumer = consumer;
}
 static constexpr int NUM_BUFFER_SLOTS = 64;

因此,producer和consumer 真正的實現者就是 BufferQueueProducer 和 BufferQueueConsumer

3.7 Client.attachLayer()

最終,加入全域性的mLayers中。

>frameworks/native/services/surfaceflinger/Client.cpp
void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer)
{
Mutex::Autolock _l(mLock);
mLayers.add(handle, layer);
}

至此,SF建立了 layer 物件,並且加入了Client服務的 mLayers列表中。layer中持有 sp<IGraphicBufferProducer> producer和 sp<IGraphicBufferConsumer> consumer;兩個物件。具體的實現者就是 BufferQueueProducer 和 BufferQueueConsumer

3.6 小結

在回顧下總體流程:

  • App端 呼叫WMS的 relayoutWindow(MSurfaceControl),傳入的是一個空SurfaceControl物件-A(空參構造)。
  • WMS端生成了java層的另一個SurfaceControl物件-B(有參構造)。同時在native層也生成了一個SurfaceControl物件。 內部通過IComposerClient物件,呼叫了SF的createSurface()方法。同時持有 IGraphicBufferProducer gbp的參照。
  • SF端生成了Layer物件,同時生成了buffer生產者sp<IGraphicBufferProducer>和buffer消費者的sp<IGraphicBufferConsumer>

接下來,從app端傳過來的 SurfaceControl-A如何跟 SurfaceControl-B關聯起來呢?當然是通過getSurfaceControl()方法了。

3.7 WindowSurfaceController.getSurfaceControl()

WindowSurfaceController.java

void getSurfaceControl(SurfaceControl outSurfaceControl) {
    outSurfaceControl.copyFrom(mSurfaceControl);
}

mSurfaceControl 就是 WindowSurfaceController 中持有之前建立的 SurfaceControl-B物件。 當前的 outSurfaceControl 是app傳遞過來的。 繼續看 copyFrom():

3.8 SurfaceControl.copyFrom()

>SurfaceControl.java
public void copyFrom(SurfaceControl other) {
    mName = other.mName;
    mWidth = other.mWidth;
    mHeight = other.mHeight;
    assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject));
}

3.8.1 nativeCopyFromSurfaceControl()

>frameworks/base/core/jni/android_view_SurfaceControl.cpp
static jlong nativeCopyFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
    // 根據參照值,得到native層的 SurfaceControl。此時是WMS的SurfaceControl物件-B
    sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    if (surface == nullptr) {
        return 0;
    }
    // 建立一個新的native的SurfaceControl物件C,呼叫的是有參構造方法
    sp<SurfaceControl> newSurface = new SurfaceControl(surface);
    newSurface->incStrong((void *)nativeCreate);
    return reinterpret_cast<jlong>(newSurface.get());
}

// 有參構造
SurfaceControl::SurfaceControl(const sp<SurfaceControl>& other) {
    mClient = other->mClient;
    mHandle = other->mHandle;
    mGraphicBufferProducer = other->mGraphicBufferProducer;
    mTransformHint = other->mTransformHint;
    mLayerId = other->mLayerId;
    mWidth = other->mWidth;
    mHeight = other->mHeight;
    mCreateFlags = other->mCreateFlags;
}

native層建立了一個新的SurfaceControl物件。

3.8.2 assignNativeObject()

SurfaceControl.java

private void assignNativeObject(long nativeObject) {
// 傳入的是 上一步新建立的native層的 SurfaceControl物件C。
    if (mNativeObject != 0) {
        // 釋放之前的 
        release();
    }
    // 持有參照。
    mNativeObject = nativeObject;
}

至此,app端的Java層的SurfaceControl物件就與native層的SurfaceControl物件聯絡了起來。建立完成後,返回到app端 ViewRootImpl 的relayoutWindow()方法中。

3.9 mSurface.copyFrom()

Surface.java

public void copyFrom(SurfaceControl other) {
    // 從surfaceControl 拷貝
    if (other == null) {
        throw new IllegalArgumentException("other must not be null");
    }
    // 獲取 SurfaceControl的 native物件參照
    long surfaceControlPtr = other.mNativeObject;
    if (surfaceControlPtr == 0) {
        throw new NullPointerException(
                "null SurfaceControl native object. Are you using a released SurfaceControl?");
    }
    // 從native層獲取surface物件的參照 
    long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
    
    //上鎖
    synchronized (mLock) {
        // 同一個物件,則不做操作
        if (newNativeObject == mNativeObject) {
            return;
        }
        if (mNativeObject != 0) {
            // 釋放之前的
            nativeRelease(mNativeObject);
        }
        // 設定新的參照
        setNativeObjectLocked(newNativeObject);
    }
}

3.9.1 nativeGetFromSurfaceControl()

frameworks/base/core/jni/android_view_Surface.cpp

static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
        jlong nativeObject,
        jlong surfaceControlNativeObj) {
    //拿到 java層參照的c++ surface物件
    Surface* self(reinterpret_cast<Surface *>(nativeObject));
    // 獲取c++層的 SurfaceControl物件
    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));

    // If the underlying IGBP's are the same, we don't need to do anything.
    // 如果 surface物件和 SurfaceControl物件的 gbp一樣,則不需要重新設值。
    if (self != nullptr &&
            IInterface::asBinder(self->getIGraphicBufferProducer()) ==
            IInterface::asBinder(ctrl->getIGraphicBufferProducer())) {
            // 返回即可
        return nativeObject;
    }
    // 如果gbp不一樣,在重新構造一個
    sp<Surface> surface(ctrl->getSurface());
    if (surface != NULL) {
        surface->incStrong(&sRefBaseOwner);
    }
    // 返回參照
    return reinterpret_cast<jlong>(surface.get());
}

邏輯已經註釋清楚了。問題是 SurfaceControl 的getSurface()如何工作的?

3.9.2 native層 SurfaceControl::getSurface()

frameworks/native/libs/gui/SurfaceControl.cpp

sp<Surface> SurfaceControl::getSurface()
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == nullptr) {
        // 建立一個Surface
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}
mutable sp<SurfaceControl> mBbqChild;
sp<Surface> SurfaceControl::generateSurfaceLocked()
{
    uint32_t ignore;
    auto flags = mCreateFlags & (ISurfaceComposerClient::eCursorWindow |
                                 ISurfaceComposerClient::eOpaque);
     // 通過 ISurfaceComposerClient,呼叫到SF程序中                            
    mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat,
                                       flags, mHandle, {}, &ignore);
     // mbbq是 SurfaceControl                                  
    mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);

    // This surface is always consumed by SurfaceFlinger, so the
    // producerControlledByApp value doesn't matter; using false.
    // 建立 surface
    mSurfaceData = mBbq->getSurface(true);
    return mSurfaceData;
}

3.9.3 Surface.getSurface()

frameworks/native/libs/gui/BLASTBufferQueue.cpp

sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
    std::unique_lock _lock{mMutex};
    sp<IBinder> scHandle = nullptr;
    if (includeSurfaceControlHandle && mSurfaceControl) {
        scHandle = mSurfaceControl->getHandle();
    }
    return new BBQSurface(mProducer, true, scHandle, this);
}

3.9.4 BBQSurface

// 繼承了surface 
class BBQSurface : public Surface {
private:
    std::mutex mMutex;
    sp<BLASTBufferQueue> mBbq;
    bool mDestroyed = false;
public:
    BBQSurface(const sp<IGraphicBufferProducer>& igbp, bool controlledByApp,
               const sp<IBinder>& scHandle, const sp<BLASTBufferQueue>& bbq)
          : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}

    void allocateBuffers() override {
        uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
        uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
        auto gbp = getIGraphicBufferProducer();
        std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
                      reqFormat=mReqFormat, reqUsage=mReqUsage] () {
            // 請求 allocateBuffers          
            gbp->allocateBuffers(reqWidth, reqHeight,
                                 reqFormat, reqUsage);

        }).detach();
    }

3.10 小結

在app端的SurfaceControl與native層的 SurfaceControl物件建立聯絡後。 app端Java層的Surface通過 copyFrom()方法,從native層的 SurfaceControl中拿到了 native層的 Surface物件,內部持有 IGraphicProducer gbp物件。可以和SF通訊。

四、總結

  • App端 呼叫WMS的 relayoutWindow(MSurfaceControl),傳入的是一個空SurfaceControl物件-A(空參構造)
  • WMS端生成了java層的另一個SurfaceControl物件-B(有參構造)。同時在native層也生成了一個 SurfaceControl 物件。內部通過IComposerClient物件,呼叫了SF的createSurface()方法。同時持有 IGraphicBufferProducer gbp的參照
  • SF端生成了Layer物件,同時生成了buffer生產者sp<IGraphicBufferProducer>和buffer消費者的sp<IGraphicBufferConsumer>
  • WMS端通過copy()方法讓 App端傳遞過來的 SurfaceControl-A物件也參照到了SF的 IGraphicBufferProducer
  • 在App端的 SurfaceControl-A物件唄賦值後,再通過Surface物件的copyFrom()方法,讓 JavaSurfaceNative層的Surface建立聯絡。最終,也就是和SFIGraphicBufferProducer 建立了聯絡。

到此這篇關於基於Android10渲染Surface的建立過程的文章就介紹到這了,更多相關Android Surface內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com