<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
OpenGL ES/Skia
定義了一組繪製介面的規範,為什麼能夠跨平臺? 本質上需要與對應平臺上的本地視窗建立連線。也就是說OpenGL ES負責輸入了繪製的命令,但是需要一個 "畫布" 來承載輸出結果,最終展示到螢幕。這個畫布就是本地視窗。
因此,每個平臺的有著不一樣的本地視窗的實現。Android平臺上是 ANativeWindow。
疑問:
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
輸出到螢幕上。
有了一個整體的概念,接下來就好理解很多。
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()
。最後會呼叫 ViewRootImpl
的setView()
方法。 內部會呼叫 IWindowSession
的addToDisplay()
方法。IWindowSession是WMS提供的一個binder服務(實現類就是Session)。
內部會建立一個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
儲存起來。
這個類的範例代表了和SurfaceFlinger的一個連線。我們可以通過它 建立一個或多個 Surface
物件。
> 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
是什麼呢?
在 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.ISurfaceComposerClient
物件 mClient,用來跨程序呼叫。那麼 ISurfaceComposerClient的實現類是哪個呢? 繼續看看 SF.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通訊
。
SurfaceSession
物件,內部參照c++層的 SurfaceComposerClient
物件。SurfaceComposerClient
物件則通過 mClient成員(ISurfaceComposerClient)代理binder,後續用來建立 Surface。到目前為止,WMS中應用程序對應的Session物件已經建立了與SF的聯絡。
ViewRootImpl 類成員變數 :
ViewRootImpl.java
// 任何執行緒都可以存取這個物件,只需要加鎖就可以了。 public final Surface mSurface = new Surface();
呼叫的是空參構造,因此 此時的Surface只是Java層的空殼而已。
當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的被顯示的屬性。如旋轉、平移、裁剪。
是 ViewRootImpl
類成員變數:
private final SurfaceControl mSurfaceControl = new SurfaceControl();
SurfaceControl 的空參構造方法,啥都沒幹!目前也是個空殼。
目前可以看出,在開始繪製時,呼叫了WMS的session.relayout(SurfaceControl mSurfaceControl)
方法之後。就可以從SurfaceControl
中得到 Surface物件。
那 session.relayout() 內部是如何做到的呢? 繼續看 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; }
最終:
WindowSurfaceController
物件獲取 SurfaceController
,返回給outSurfaceControl
。winAnimator 是 WindowStateAnimator型別。
> 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
物件。
> 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的native層。 而跨程序的 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; }
sp<BufferLayerConsumer> mConsumer
和 sp<IGraphicBufferProducer> mProducer
,也就是GraphicBuffer
的生產者和消費者物件。layers
全域性的集合中。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; }
frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp
sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override { return new BufferQueueLayer(args); }
繼承關係:
class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener {... class BufferLayer : public Layer {...
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> producer
; sp<IGraphicBufferConsumer> consumer
;createBufferQueue
(&producer, &consumer, true);來建立這兩個物件。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
。
最終,加入全域性的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
。
在回顧下總體流程:
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()
方法了。
WindowSurfaceController.java
void getSurfaceControl(SurfaceControl outSurfaceControl) { outSurfaceControl.copyFrom(mSurfaceControl); }
mSurfaceControl
就是 WindowSurfaceController 中持有之前建立的 SurfaceControl-B
物件。 當前的 outSurfaceControl
是app傳遞
過來的。 繼續看 copyFrom():
>SurfaceControl.java public void copyFrom(SurfaceControl other) { mName = other.mName; mWidth = other.mWidth; mHeight = other.mHeight; assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject)); }
>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
物件。
SurfaceControl.java
private void assignNativeObject(long nativeObject) { // 傳入的是 上一步新建立的native層的 SurfaceControl物件C。 if (mNativeObject != 0) { // 釋放之前的 release(); } // 持有參照。 mNativeObject = nativeObject; }
至此,app端的Java層的SurfaceControl
物件就與native層的SurfaceControl
物件聯絡了起來。建立完成後,返回到app端 ViewRootImpl 的relayoutWindow()
方法中。
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); } }
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()如何工作的?
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; }
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); }
// 繼承了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(); }
在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
。copyFrom()
方法,讓 Java
層Surface
與Native
層的Surface
建立聯絡。最終,也就是和SF
的IGraphicBufferProducer
建立了聯絡。到此這篇關於基於Android10渲染Surface的建立過程的文章就介紹到這了,更多相關Android Surface內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45