基于Android10渲染Surface的創(chuàng)建過程
一、Surface 概述
OpenGL ES/Skia
定義了一組繪制接口的規(guī)范,為什么能夠跨平臺? 本質上需要與對應平臺上的本地窗口建立連接。也就是說OpenGL ES負責輸入了繪制的命令,但是需要一個 "畫布" 來承載輸出結果,最終展示到屏幕。這個畫布就是本地窗口。
因此,每個平臺的有著不一樣的本地窗口的實現(xiàn)。Android平臺上是 ANativeWindow。
疑問:
- 那么如何將OpenGL本地化? 通過 EGL來對OpenGL ES來進行配置。關鍵點就是提供本地化窗口。
- 本地化窗口的作用是什么? 本地窗口是OpenGL ES和 物理屏幕之間的橋梁。
1.1 Android本地窗口簡述
Android圖形系統(tǒng)提供的本地窗口,可以分為兩類:
FrameBufferNativeWindow
面對SF(SurfaceFlinger)。它通過HAL層的Gralloc系統(tǒng)調用(alloc/free)來分配內核中的FrameBuffer幀緩沖區(qū)
。 這個幀緩沖區(qū)就代表了物理屏幕(fb*驅動節(jié)點,*表示屏幕數(shù)。如fb0主屏幕、fb1等)。 FrameBuffer的數(shù)量一般情況下是2,也就是雙緩沖。當然還有三倍緩沖。
Surface
面向應用程序。對應的是內存中一塊緩沖區(qū)
,稱為:GraphicBuffer。是由SF來進行分配。app從SF中獲取一塊GraphicBuffer
, 通過OpenGL/Skia將圖形數(shù)據(jù)繪制(軟件/硬件)到GraphicBuffer上。最終SF會把各個應用的GraphicBuffer數(shù)據(jù)進行合成,最終 通過 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 進程中創(chuàng)建一個Session對象)的addView()
。最后會調用 ViewRootImpl
的setView()
方法。 內部會調用 IWindowSession
的addToDisplay()
方法。IWindowSession是WMS提供的一個binder服務(實現(xiàn)類就是Session)。
2.2 IWindowSession.windowAddedLocked()
內部會創(chuàng)建一個WindowState
對象。 調用 WindowState的 attach()
方法。最終調到Session中的windowAddedLocked()
,會創(chuàng)建 一個SurfaceSession
對象。這就是我們要找的的跟SurfaceFlinger
建立聯(lián)系的地方。
SurfaceSession mSurfaceSession; void windowAddedLocked(String packageName) { mPackageName = packageName; mRelayoutTag = "relayoutWindow: " + mPackageName; if (mSurfaceSession == null) { // 一個進程只有一個session,因此也只創(chuàng)建一次 SurfaceSession 對象 // 創(chuàng)建 SurfaceSession 對象 mSurfaceSession = new SurfaceSession(); // 每個session 都存入WMS中的 mService.mSessions.add(this); if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) { mService.dispatchNewAnimatorScaleLocked(this); } } mNumWindow++; // 進程中所有窗口的數(shù)量+1 }
一個應用進程
對應一個Session
對象,一個Session對象對應一個SurfaceSession
。 WMS會把 這個Session 存儲起來。也就是說WMS 會把所有跟SurfaceFlinger保持連接狀態(tài)的應用Session
存儲起來。
2.3 SurfaceSession 創(chuàng)建過程
這個類的實例代表了和SurfaceFlinger的一個連接。我們可以通過它 創(chuàng)建一個或多個 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() { //創(chuàng)建sf代理binder對象sf,類型為 ISurfaceComposer sp<ISurfaceComposer> sf(ComposerService::getComposerService()); if (sf != nullptr && mStatus == NO_INIT) { sp<ISurfaceComposerClient> conn; //創(chuàng)建一個 ISurfaceComposerClient 對象,用來跨進程調用 conn = sf->createConnection(); if (conn != nullptr) { mClient = conn; mStatus = NO_ERROR; } } }
ISurfaceComposer
實現(xiàn)類就是 SurfaceFlinger對象。在server進程的代理對象是 ComposerService。This class defines the Binder IPC interface for accessing various SurfaceFlinger features.- 通過SF.createConnection(),創(chuàng)建一個
ISurfaceComposerClient
對象 mClient,用來跨進程調用。
那么 ISurfaceComposerClient的實現(xiàn)類是哪個呢? 繼續(xù)看看 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的實現(xiàn)類就是 SF中定義的 Client
。也是一個binder服務。 我們回到 SurfaceComposerClient 類,它持有 ISurfaceComposerClient的binder引用 mClient。通過 mClient實現(xiàn)與SF通信
。
2.3 小結
- Session 類中,創(chuàng)建了一個
SurfaceSession
對象,內部引用c++層的SurfaceComposerClient
對象。 - SurfaceComposerClient 對象是通過SF創(chuàng)建的另一個binder服務。減輕SF的工作量。
SurfaceComposerClient
對象則通過 mClient成員(ISurfaceComposerClient)代理binder,后續(xù)用來創(chuàng)建 Surface。
到目前為止,WMS中應用進程對應的Session對象已經(jīng)建立了與SF的聯(lián)系。
三、Surface的創(chuàng)建
3.1 Java層的Surface
ViewRootImpl 類成員變量 :
ViewRootImpl.java
// 任何線程都可以訪問這個對象,只需要加鎖就可以了。 public final Surface mSurface = new Surface();
調用的是空參構造,因此 此時的Surface只是Java層的空殼而已。
3.2 App端的 relayoutWindow()
當SF收到vsync信號后,通過Choreographer監(jiān)聽,分發(fā)到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 可以控制一個被合成系統(tǒng)管理的、正在屏幕上顯示的surface。它是Buffer數(shù)據(jù)和窗口的metadata的鏈接器。 通過這個 SurfaceControl構造的surface,app可以直接提交buffer數(shù)據(jù)到合成系統(tǒng)進行合成。此外還可以通過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() 內部是如何做到的呢? 繼續(xù)看 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) { // 繼續(xù)調用 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進程。 表示結果接收。它實現(xiàn)了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 創(chuàng)建 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 { // 否則創(chuàng)建一個 WindowSurfaceController mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, attrs.getTitle().toString(), width, height, format, flags, this, windowType, ownerUid); // ... } catch (OutOfResourcesException e) { //... } return mSurfaceController; }
createSurfaceLocked()
就是創(chuàng)建了一個 WindowSurfaceController 對象。WindowSurfaceController的構造方法
中會創(chuàng)建一個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 創(chuàng)建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."); } // 創(chuàng)建對象 ,調用了 SurfaceControl的有參構造方法。 return new SurfaceControl( mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata); }
調用SurfaceControl的有參構造方法,構造了一個SurfaceControl對象。 還記得在3. 3
,ViewRootImpl的成員變量mSurfaceControl,調用的是空參構造
,啥都沒做。
但是,現(xiàn)在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 { //... //注意這里第一個參數(shù)是 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); //這個就是之前創(chuàng)建 SurfaceSession創(chuàng)建時候的 SurfaceComposerClient對象。SF的代理服務。 sp<SurfaceComposerClient> client; if (sessionObj != NULL) { // 之前創(chuàng)建的 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(),創(chuàng)建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數(shù)據(jù)的生產(chǎn)者 sp<IGraphicBufferProducer> gbp; uint32_t transformHint = 0; int32_t id = -1; // mClient 具體實現(xiàn)類是 SF的Client服務 。來創(chuàng)建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) { // 終于創(chuàng)建了一個native層的 SurfaceControl對象。注意,此時是native層的有參構造??! *outSurface = new SurfaceControl(this, handle, gbp, id, w, h, format, transformHint, flags); } } return err; } 繼續(xù)看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對象來創(chuàng)建 SurfaceControl 對象。此時的 SurfaceControl對象,不僅僅存在java層,也會在native層創(chuàng)建一個SurfaceControl對象。
- native層中,內部會通過之前建立連接surfaceSession來向SF請求buffer、metadata等信息,給SurfaceControl對象賦值。
注意,以上的邏輯還是在WMS的native層。 而跨進程的 createSurface()
調用到底干了啥?
3.6 SF端 ISurfaceComposerClient.createSurface()
此時進入SF進程
。 Client
就是 ISurfaceComposerClient
的實現(xiàn)類。
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。 創(chuàng)建一個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) { // 寬高不能為負數(shù) 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; } } // 根據(jù)flag 創(chuàng)建不同的layer對象。 switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: // 1 創(chuàng)建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 繼續(xù)調用 addClientLayer result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToCurrentState); ... return result; }
- 創(chuàng)建了 BufferQueueLayer 對象,里面持有
sp<BufferLayerConsumer> mConsumer
和sp<IGraphicBufferProducer> mProducer
,也就是GraphicBuffer
的生產(chǎn)者和消費者對象。 - 加入到
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; } // 創(chuàng)建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生產(chǎn)者 *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 // 聲明生產(chǎn)者和消費者 sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; // BufferQueue 初始化 BufferQueue::createBufferQueue(&producer, &consumer, true); // MonitoredProducer分裝了 producer,方便SF監(jiān)聽 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> producer
;sp<IGraphicBufferConsumer> consumer
; - 調用 BufferQueue::
createBufferQueue
(&producer, &consumer, true);來創(chuàng)建這兩個對象。
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 生產(chǎn)對象 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 真正的實現(xiàn)者就是 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創(chuàng)建了 layer 對象,并且加入了Client服務的 mLayers列表中。layer中持有 sp<IGraphicBufferProducer> producer
和 sp<IGraphicBufferConsumer> consumer
;兩個對象。具體的實現(xiàn)者就是 BufferQueueProducer
和 BufferQueueConsumer
。
3.6 小結
在回顧下總體流程:
App端
調用WMS的 relayoutWindow(MSurfaceControl),傳入的是一個空SurfaceControl對象-A(空參構造)。WMS端
生成了java層的另一個SurfaceControl對象-B(有參構造)。同時在native層也生成了一個SurfaceControl對象。 內部通過IComposerClient對象,調用了SF的createSurface()方法。同時持有 IGraphicBufferProducer gbp的引用。SF端
生成了Layer對象,同時生成了buffer生產(chǎn)者sp<IGraphicBufferProducer>
和buffer消費者的sp<IGraphicBufferConsumer>
。
接下來,從app端傳過來的 SurfaceControl-A如何跟 SurfaceControl-B
關聯(lián)起來呢?當然是通過getSurfaceControl()
方法了。
3.7 WindowSurfaceController.getSurfaceControl()
WindowSurfaceController.java
void getSurfaceControl(SurfaceControl outSurfaceControl) { outSurfaceControl.copyFrom(mSurfaceControl); }
mSurfaceControl
就是 WindowSurfaceController 中持有之前創(chuàng)建的 SurfaceControl-B
對象。 當前的 outSurfaceControl
是app傳遞
過來的。 繼續(xù)看 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) { // 根據(jù)引用值,得到native層的 SurfaceControl。此時是WMS的SurfaceControl對象-B sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); if (surface == nullptr) { return 0; } // 創(chuàng)建一個新的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
層創(chuàng)建了一個新的SurfaceControl
對象。
3.8.2 assignNativeObject()
SurfaceControl.java
private void assignNativeObject(long nativeObject) { // 傳入的是 上一步新創(chuàng)建的native層的 SurfaceControl對象C。 if (mNativeObject != 0) { // 釋放之前的 release(); } // 持有引用。 mNativeObject = nativeObject; }
至此,app端的Java層的SurfaceControl
對象就與native層的SurfaceControl
對象聯(lián)系了起來。創(chuàng)建完成后,返回到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()); }
邏輯已經(jīng)注釋清楚了。問題是 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) { // 創(chuàng)建一個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. // 創(chuàng)建 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對象建立聯(lián)系后。 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生產(chǎn)者sp<IGraphicBufferProducer>
和buffer消費者的sp<IGraphicBufferConsumer>
。WMS端
通過copy()
方法讓 App端傳遞過來的SurfaceControl-A對象
也引用到了SF的IGraphicBufferProducer
。- 在App端的 SurfaceControl-A對象唄賦值后,再通過Surface對象的
copyFrom()
方法,讓Java
層Surface
與Native
層的Surface
建立聯(lián)系。最終,也就是和SF
的IGraphicBufferProducer
建立了聯(lián)系。
到此這篇關于基于Android10渲染Surface的創(chuàng)建過程的文章就介紹到這了,更多相關Android Surface內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android開發(fā)之React Navigation 導航欄樣式調整+底部角標消息提示
這篇文章主要介紹了React Navigation 導航欄樣式調整+底部角標消息提示的相關知識,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下2019-05-05Android和IOS的瀏覽器中檢測是否安裝某個客戶端的方法
這篇文章主要介紹了Android和IOS的瀏覽器中檢測是否安裝某個客戶端的方法,需要的朋友可以參考下2014-06-06Android應用開發(fā)的版本更新檢測升級功能實現(xiàn)示例
本文對Android版本更新的知識做全面的總結,主要包括開發(fā)中版本的設置,如何檢測本程序的版本,版本的更新判斷和顯示,新版本程序的安裝2022-04-04Android引用開源框架通過AsyncHttpClient實現(xiàn)文件上傳
這篇文章主要介紹了Android引用開源框架通過AsyncHttpClient實現(xiàn)文件上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01