軟件總體結構,Android4.4深入淺出之SurfaceFlinger總體結構

 2023-11-30 阅读 25 评论 0

摘要:?轉自:http://blog.csdn.net/w401229755/article/details/38420191 一.?????????????Android GUI框架: SurfaceFlinger:每當用戶程序刷新UI的時候,會中介BufferQueue申請一個buffer(dequeueBuffer),然后把UI的信息填入
?轉自:http://blog.csdn.net/w401229755/article/details/38420191

一.?????????????Android GUI框架:

SurfaceFlinger:每當用戶程序刷新UI的時候,會中介BufferQueue申請一個bufferdequeueBuffer),然后把UI的信息填入,丟給SurfaceFlingerSurfaceFlinger通過計算多重計算合成visibleRegion之后,丟給openGL層處理,處理之后送到顯示器display上顯示。

????根據整個Android系統的GUI設計理念,我們不難猜想到至少需要兩種本地窗口:

???面向管理者(SurfaceFlinger)

既然SurfaceFlinger扮演了系統中所有UI界面的管理者,那么它無可厚非地需要直接或間接地持有本地窗口,這個窗口就是FramebufferNativeWindow

???面向應用程序

這類窗口是Surface(這里和以前版本出入比較大,之前的版本本地窗口是SurfaceTextureClient)

第二種窗口是能直接顯示在終端屏幕上的——它使用了幀緩沖區,而第一種Window實際上是從內存緩沖區分配的空間。當系統中存在多個應用程序時,這能保證它們都可以獲得一個本地窗口,并且這些窗口最終也能顯示到屏幕上——SurfaceFlinger會收集所有程序的顯示需求,對它們做統一的圖像混合操作。

二.?????????????SurfaceFlinger和BufferQueue

一個UI完全顯示到diplay的過程,SurfaceFlinger扮演著重要的角色但是它的職責是“Flinger”,即把系統中所有應用程序的最終的繪圖結果進行混合,然后統一顯示到物理屏幕上,而其他方面比如各個程序的繪畫過程,就由其他東西來擔任了。這個光榮的任務自然而然地落在了BufferQueue的肩膀上,它是每個應用程序一對一的輔導老師,指導著UI程序的畫板申請作畫流程等一系列細節。下面的圖描述了這三者的關系:

?

雖說是三者的關系,但是他們所屬的層卻只有兩個,app屬于java層,BufferQueue/SurfaceFlinger屬于native層。軟件總體結構,也就是說BufferQueue也是隸屬SurfaceFlinger,所有工作圍繞SurfaceFlinger展開。

這里IGraphicBufferProducer就是appBufferQueue重要橋梁,GraphicBufferProducer承擔著單個應用進程中的UI顯示需求,與BufferQueue打交道的就是它。它的工作流程如下:

?

?

BpGraphicBufferProducerGraphicBufferProducer在客戶端這邊的代理對象,負責和SF交互,GraphicBufferProducer通過gbpIGraphicBufferProducer類對象)向BufferQueue獲取buffer,然后進行填充UI信息,當填充完畢會通知SFSF知道后就對該Buffer進行下一步操作。典型的生產-消費者模式。

接下來具體說明客戶端(producer)和服務端SurfaceFlingerconsumer)工作的模式:

?????首先這里的buffer是共享緩沖區,故肯定會涉及到互斥鎖,所以buffer的狀態也會有多種,一般的buffer大致會經過FREE->DEQUEUED->QUEUED->ACQUIRED->FREE這個流程,如右圖:???

?? BufferQueue

可以認為BufferQueue是一個服務中心,其它兩個owner必須要通過它來管理buffer。比如說當producer想要獲取一個buffer時,它不能越過BufferQueue直接與consumer進行聯系,反之亦然。android surfaceview。

?? Producer

生產者就是填充”buffer空間的人,通常情況下當然就是應用程序。因為應用程序不斷地刷新UI,從而將產生的顯示數據源源不斷地寫到buffer中。當Producer需要使用一塊buffer時,它首先會向中介BufferQueue發起dequeue申請,然后才能對指定的緩沖區進行操作。這種情況下buffer就屬于producer一個人的了,它可以對buffer進行任何必要的操作,而其它owner此刻絕不能擅自插手。

當生產者認為一塊buffer已經寫入完成后,它進一步調用BufferQueuequeue。從字面上看這個函數是入列的意思,形象地表達了buffer此時的操作——buffer歸還到BufferQueue的隊列中。系統總體結構設計、一旦queue成功后,owner也就隨之改變為BufferQueue

?? Consumer

消費者是與生產者相對應的,它的操作同樣受到BufferQueue的管控。當一塊buffer已經就緒后,Consumer就可以開始工作了。這里需要特別留意的是,從各個對象所扮演的角色來看,BufferQueue是中介機構,屬于服務提供方;Producer屬于buffer內容的產出方,它對緩沖區的操作是一個主動的過程;反之,Consumerbuffer的處理則是被動的、等待式——它必須要等到一塊buffer填充完成后才能做工作。在這樣的模型下,我們怎么保證Consumer可以及時的處理buffer呢?換句話說,當一塊buffer數據ready后,應該怎么告知Consumer來操作呢?

仔細觀察的話,可以看到BufferQueue里還同時提供了一個特別的類,名稱為ProxyConsumerListener,其中的函數接口包括:

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. classProxyConsumerListener?:?public?BnConsumerListener?{??
  2. ??
  3. public:???????
  4. ??
  5. ?//省略構造函數??
  6. ??
  7. ????????virtual?void?onFrameAvailable();/*當一塊buffer可以被消費時,這個函數會被調用,特別注意此時沒有共享鎖的保護*/??
  8. ??
  9. ????????virtual?voidonBuffersReleased();/*BufferQueue通知consumer它已經釋放其slot中的一個或多個?GraphicBuffer引用*/??
  10. ??
  11. ????private:??
  12. ??
  13. ???wp<ConsumerListener>mConsumerListener;??
  14. ??
  15. }??


?

?這樣子就很清楚了,當有一幀數據準備就緒后,BufferQueue就會調用onFrameAvailable()來通知Consumer進行消費。

BufferQueueSurfaceFlinger之間的通信模式如下:

也是有一對BpGraphicBufferConsumer/BnGraphicBufferConsumer支持他們之間的信息傳輸。

三.?????????????具體分析BufferQueue

首先說明一下BufferQueue的類關系:

下面是BufferQueue中的核心函數分析:

核心成員函數

說明

setBufferCount

setBufferCount updates the? number of available buffer slots.

requestBuffer

requestBuffer returns the? GraphicBuffer for slot N.

dequeueBuffer

dequeueBuffer gets the next? buffer slot index for the producer to use.

queueBuffer

queueBuffer returns a filled? buffer to the BufferQueue.

cancelBuffer

cancelBuffer returns a? dequeued buffer to the BufferQueue

acquireBuffer

acquireBuffer attempts to? acquire ownership of the next pending buffer BufferQueue.

releaseBuffer

releaseBuffer releases a? buffer slot from the consumer back to the BufferQueue.

?

BufferQueue是IGraphicBufferProducerIGraphicBufferConsumer的具體實現,用戶在請求和SurfaceFlinger連接的過程中會請求SF創建一個LayerIGraphicBufferProducer就是在這個過程中獲取一個BufferQueue對象,又轉化成IGraphicBufferProducer類對象,是為了進一步和BufferQueue進行交互,下面是關鍵代碼:

?

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. status_t?SurfaceFlinger::createNormalLayer(constsp<Client>&?client,??
  2. ??
  3. ????????const?String8&?name,?uint32_t?w,uint32_t?h,?uint32_t?flags,?PixelFormat&?format,??
  4. ??
  5. ????????sp<IBinder>*?handle,?sp<IGraphicBufferProducer>*gbpsp<Layer>*?outLayer)??
  6. ??
  7. {??
  8. ??
  9. ????switch?(format)?{??
  10. ??
  11. ????case?PIXEL_FORMAT_TRANSPARENT:??
  12. ??
  13. ????case?PIXEL_FORMAT_TRANSLUCENT:??
  14. ??
  15. ????????format?=?PIXEL_FORMAT_RGBA_8888;??
  16. ??
  17. ????????break;??
  18. ??
  19. ????case?PIXEL_FORMAT_OPAQUE:??
  20. ??
  21. ????}??
  22. ??
  23. ???
  24. ??
  25. #ifdefNO_RGBX_8888??
  26. ??
  27. ????if?(format?==?PIXEL_FORMAT_RGBX_8888)??
  28. ??
  29. ????????format?=?PIXEL_FORMAT_RGBA_8888;??
  30. ??
  31. #endif??
  32. ??
  33. ???
  34. ??
  35. ????*outLayer?=?new?Layer(this,?client,?name,w,?h,?flags);??
  36. ??
  37. ????status_t?err?=(*outLayer)->setBuffers(w,?h,?format,?flags);??
  38. ??
  39. ????if?(err?==?NO_ERROR)?{??
  40. ??
  41. ????????*handle?=?(*outLayer)->getHandle();??
  42. ??
  43. ????????*gbp?=(*outLayer)->getBufferQueue();??
  44. ????}??
  45. ??
  46. ???
  47. ??
  48. ????ALOGE_IF(err,?"createNormalLayer()failed?(%s)",?strerror(-err));??
  49. ??
  50. ????return?err;??
  51. ??
  52. }??


?

下面是getBufferQueue的實現,很簡單,獲取BufferQueue對象:

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. sp<IGraphicBufferProducer>Layer::getBufferQueue()?const?{??
  2. ??
  3. ????return?mBufferQueue;??
  4. ??
  5. }??


?

IGraphicBufferProducer是個接口類,它的實現必然在子類BpGraphicBufferProducer中實現,我們來看下這個類:

?

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. classBpGraphicBufferProducer?:?public?BpInterface<IGraphicBufferProducer>??
  2. ??
  3. {??
  4. ??
  5. public:??
  6. ??
  7. ????BpGraphicBufferProducer(constsp<IBinder>&?impl)??
  8. ??
  9. ????????:BpInterface<IGraphicBufferProducer>(impl)??
  10. ??
  11. ????{??
  12. ??
  13. ????}??
  14. ??
  15. ????virtual?status_t?requestBuffer(intbufferIdx,?sp<GraphicBuffer>*?buf)?{??
  16. ??
  17. ????????Parcel?data,?reply;??
  18. ??
  19. ???????data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());??
  20. ??
  21. ????????data.writeInt32(bufferIdx);??
  22. ??
  23. ????????status_t?result?=remote()->transact(REQUEST_BUFFER,?data,&reply);??
  24. ??
  25. ????????if?(result?!=?NO_ERROR)?{??
  26. ??
  27. ????????????return?result;??
  28. ??
  29. ????????}??
  30. ??
  31. ????????bool?nonNull?=?reply.readInt32();??
  32. ??
  33. ????????if?(nonNull)?{??
  34. ??
  35. ????????????*buf?=?new?GraphicBuffer();??
  36. ??
  37. ????????????reply.read(**buf);??
  38. ??
  39. ????????}??
  40. ??
  41. ????????result?=?reply.readInt32();??
  42. ??
  43. ????????return?result;??
  44. ??
  45. ????}??
  46. ??
  47. ????virtual?status_t?dequeueBuffer(int*buf,?sp<Fence>*?fence,?bool?async,??
  48. ??
  49. ????????????uint32_t?w,?uint32_t?h,?uint32_tformat,?uint32_t?usage)?{??
  50. ??
  51. ????????Parcel?data,?reply;??
  52. ??
  53. ???????data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());??
  54. ??
  55. ????????data.writeInt32(async);??
  56. ??
  57. ????????data.writeInt32(w);??
  58. ??
  59. ????????data.writeInt32(h);??
  60. ??
  61. ????????data.writeInt32(format);??
  62. ??
  63. ????????data.writeInt32(usage);??
  64. ??
  65. ????????status_t?result?=?remote()->transact(DEQUEUE_BUFFER,?data,&reply);??
  66. ??
  67. ????????if?(result?!=?NO_ERROR)?{??
  68. ??
  69. ????????????return?result;??
  70. ??
  71. ????????}??
  72. ??
  73. ????????*buf?=?reply.readInt32();??
  74. ??
  75. ????????bool?nonNull?=?reply.readInt32();??
  76. ??
  77. ???????if?(nonNull)?{??
  78. ??
  79. ????????????*fence?=?new?Fence();??
  80. ??
  81. ????????????reply.read(**fence);??
  82. ??
  83. ????????}??
  84. ??
  85. ????????result?=?reply.readInt32();??
  86. ??
  87. ????????return?result;??
  88. ??
  89. ????}??
  90. ??
  91. ???
  92. ??
  93. ????virtual?status_t?queueBuffer(intbuf,??
  94. ??
  95. ????????????const?QueueBufferInput&?input,QueueBufferOutput*?output)?{??
  96. ??
  97. ????????Parcel?data,?reply;??
  98. ??
  99. ???????data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());??
  100. ??
  101. ????????data.writeInt32(buf);??
  102. ??
  103. ????????data.write(input);??
  104. ??
  105. ????????status_t?result?=?remote()->transactQUEUE_BUFFER,?data,?&reply);??
  106. ??
  107. ????????if?(result?!=?NO_ERROR)?{??
  108. ??
  109. ????????????return?result;??
  110. ??
  111. ????????}??
  112. ??
  113. ????????memcpy(output,reply.readInplace(sizeof(*output)),?sizeof(*output));??
  114. ??
  115. ????????result?=?reply.readInt32();??
  116. ??
  117. ????????return?result;??

?

省去了一些成員函數,只貼出關鍵成員函數,首先這里的dequeueBufferqueueBuffer并非真正對Buffer進行操作,留意紅色部分,會發現他只是發出一個“消息”通知接收方要去

Dequeue一個Bufferqueue一個Buffer。汽車總體結構分析?相對應的BnGraphicBufferProducer來接收消息。

BnGraphicBufferProducer中的onTransact負責這件事:

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. status_tBnGraphicBufferProducer::onTransact(??
  2. ??
  3. ????uint32_t?code,?const?Parcel&?data,Parcel*?reply,?uint32_t?flags)??
  4. ??
  5. {??
  6. ??
  7. ????switch(code)?{??
  8. ??
  9. ?case?DEQUEUE_BUFFER:?{??
  10. ??
  11. ???????????CHECK_INTERFACE(IGraphicBufferProducer,?data,?reply);??
  12. ??
  13. ????????????bool?async??????=?data.readInt32();??
  14. ??
  15. ????????????uint32_t?w??????=?data.readInt32();??
  16. ??
  17. ????????????uint32_t?h??????=data.readInt32();??
  18. ??
  19. ????????????uint32_t?format?=?data.readInt32();??
  20. ??
  21. ????????????uint32_t?usage??=?data.readInt32();??
  22. ??
  23. ????????????int?buf;??
  24. ??
  25. ????????????sp<Fence>?fence;??
  26. ??
  27. ????????????int?result?=?dequeueBuffer(&buf,?&fence,?async,?w,?h,format,?usage);??
  28. ??
  29. ????????????reply->writeInt32(buf);??
  30. ??
  31. ????????????reply->writeInt32(fence?!=NULL);??
  32. ??
  33. ????????????if?(fence?!=?NULL)?{??
  34. ??
  35. ????????????????reply->write(*fence);??
  36. ??
  37. ????????????}??
  38. ??
  39. ????????????reply->writeInt32(result);??
  40. ??
  41. ????????????return?NO_ERROR;??
  42. ??
  43. ????????}?break;??
  44. ??
  45. ????????case?QUEUE_BUFFER:?{??
  46. ??
  47. ???????????CHECK_INTERFACE(IGraphicBufferProducer,?data,?reply);??
  48. ??
  49. ????????????int?buf?=?data.readInt32();??
  50. ??
  51. ????????????QueueBufferInput?input(data);??
  52. ??
  53. ????????????QueueBufferOutput*?const?output?=??
  54. ??
  55. ????????????????????reinterpret_cast<QueueBufferOutput*>(??
  56. ??
  57. ???????????????????????????reply->writeInplace(sizeof(QueueBufferOutput)));??
  58. ??
  59. ????????????status_t?result?=?queueBuffer(buf,?input,?output);??
  60. ??
  61. ????????????reply->writeInt32(result);??
  62. ??
  63. ????????????return?NO_ERROR;??
  64. ??
  65. ????????}?break;??
  66. ??
  67. ?????????
  68. ??
  69. ????????
  70. ??
  71. ????}??
  72. ??
  73. ????return?BBinder::onTransact(code,?data,reply,?flags);??
  74. ??
  75. }??

?

省略了一些分支,留意紅色部分才發現這里調用了dequeueBufferqueueBuffer

它們的實現在BufferQueue中,這里才真正踏足到BufferQueue領域中。到這里客戶端和BufferQueue建立聯系,接下去的事就是BufferQueue內部處理的事了,BufferQueueSuefaceFlinger之間的關系也如此。

?

四.?????????????SurfaceFlinger處理buffer

??這里先用2張圖來介紹下SurfaceFlinger的整個消息處理機制和工作流程:

更具體的代碼流程之前有經過分析。

這里繼續下去對handleMessageRefresh分析,這是SuefaceFlinger的核心處理函數。

?

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. voidSurfaceFlinger::handleMessageRefresh()?{??
  2. ??
  3. ????ATRACE_CALL();??
  4. ??
  5. ????preComposition();??
  6. ??
  7. ????rebuildLayerStacks();??
  8. ??
  9. ????setUpHWComposer();??
  10. ??
  11. ????doDebugFlashRegions();??
  12. ??
  13. ????doComposition();??
  14. ??
  15. postComposition();??
  16. ??
  17. ???
  18. ??
  19. //………省略??
  20. ??
  21. }??

?

?preComposition();預先準備“合成物“就是客戶端那邊傳來的UI信息的buffer

?rebuildLayerStacks();在每一個screen上重建可見區域;

setUpHWComposer();初始化一個硬件容器;

doDebugFlashRegions();這個函數一般進去就返回來了;

doComposition();實質的合成過程,并且合成完的BUFFERopengl es處理,處理之后由postFramebuffer()送到display上顯示;

?

這里重點研究doComposition()

?

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. voidSurfaceFlinger::doComposition()?{??
  2. ??
  3. ????ATRACE_CALL();??
  4. ??
  5. ????const?bool?repaintEverything?=android_atomic_and(0,?&mRepaintEverything);??
  6. ??
  7. ????for?(size_t?dpy=0?;?dpy<mDisplays.size();?dpy++)?{??
  8. ??
  9. ????????const?sp<DisplayDevice>&hw(mDisplays[dpy]);??
  10. ??
  11. ????????if?(hw->canDraw())?{??
  12. ??
  13. ????????????//?transform?the?dirty?region?intothis?screen's?coordinate?space??
  14. ??
  15. ????????????const?Region?dirtyRegion(hw->getDirtyRegion(repaintEverything));??
  16. ??
  17. ???
  18. ??
  19. ????????????//?repaint?the?framebuffer?(ifneeded)??
  20. ??
  21. ????????????doDisplayComposition(hw,?dirtyRegion);??
  22. ??
  23. ???
  24. ??
  25. ???????????hw->dirtyRegion.clear();??
  26. ??
  27. ????????????hw->flip(hw->swapRegion);??
  28. ??
  29. ???????????hw->swapRegion.clear();??
  30. ????????}??
  31. ??
  32. ????????//?inform?the?h/w?that?we're?donecompositing??
  33. ??
  34. ??????hw->compositionComplete();??
  35. ????}??
  36. ??
  37. ????postFramebuffer();??
  38. }??

?

doDisplayComposition(hw, dirtyRegion);負責渲染的核心函數它的走向是:

doDisplayComposition-> doComposeSurfaces->draw->onDraw->drawWithOpenGL.一直走到OPENGL層。系統總體結構。Opengl貼完圖之后,調用了flip函數,在這里跟之前版本有很大出入,之前版本flip是在postFramebuffer中的,而且函數內容也做了很大的改變,只是計數加一。

???在這里說明一下,UI顯示是雙緩沖機制,每當畫完一個buffer需要flip一下,也就是交換。但在這個版本已經融合到postFramebuffer中:

貼出關鍵代碼

r = hwc.commit();

成員變量hwc是在DisplayHardware::init中生成的一個HWComposer對象。只要HWC_HARDWARE_MODULE_ID模塊可以正常加載,且hwc_open能打開hwc_composer_device設備,那么initCheck()就返回NO_ERROR,否則就是NO_INIT

此時我們通過HWComposer::commit來執行flip,這個函數直接調用如下硬件接口:

mHwc->set(mHwc, mNumDisplays, mLists);

set()和后面的eglSwapBuffers是基本等價的,原型如下:

???int (*set)(struct hwc_composer_device*dev,hwc_display_t dpy,

???????????????hwc_layer_list_t* list);

其中最后一個list必須與最近一次的prepare()所用列表完全一致。假如list為空或者列表數量為0的話,說明SurfaceFlinger已經利用OpenGL ES做了composition,此時set就和eglSwapBuffers一樣。管理信息系統總體結構包括,當list不為空,且layercompositionType == HWC_OVERLAY,那么HWComposer需要進行硬件合成。

如果成功執行的話,set返回0,否則就是HWC_EGL_ERROR

如果沒成功的話,后面還有一句:

if (r)

?{

?hw->hwcSwapBuffers();

}

作用也是跟flip一樣。它的函數走向是:

hwcSwapBuffers->eglSwapBuffers->swapBuffers->advanceFrame-> fbPost->post

一旦交換完畢就順著這個走向拋給底層display去顯示。

這里我們主要研究swapBuffers這個函數:

?

[cpp]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. EGLBooleanegl_window_surface_v2_t::swapBuffers()??
  2. ??
  3. {??
  4. ??
  5. ????//………….??
  6. ??
  7. ????nativeWindow->queueBuffer(nativeWindow,buffer,?-1);??
  8. ??
  9. ???
  10. ??
  11. ????//?dequeue?a?new?buffer??
  12. ??
  13. ????if?(nativeWindow->dequeueBuffer(nativeWindow,?&buffer,?&fenceFd)==?NO_ERROR)?{??
  14. ??
  15. ????????sp<Fence>?fence(new?Fence(fenceFd));??
  16. ??
  17. ????????if(fence->wait(Fence::TIMEOUT_NEVER))?{??
  18. ??
  19. ???????????nativeWindow->cancelBuffer(nativeWindow,?buffer,?fenceFd);??
  20. ??
  21. ????????????return?setError(EGL_BAD_ALLOC,EGL_FALSE);??
  22. ??
  23. ????????}??
  24. ??
  25. //。android surfaceflinger???
  26. ??
  27. }??


?

這和我一開始的那張圖的流程是一致的——通過queueBuffer來入隊,然后通過dequeueBuffer重新申請一個buffer以用于下一輪的刷新。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/185711.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息