GraphicBuffer的使用(筆記)

2021-10-25 13:53:30 字數 4059 閱讀 7544

關於graphicbuffer的使用,前幾天再檢視乙個記憶體洩漏的問題時,了解了一些關於android上的graphicbuffer使用的細節。以下的這個sample就是為了測試graphicbuffer對應的gralloc如何分配內/釋放記憶體,以及對於不同的執行緒或者是程序gralloc如何處理這塊graphicbuffer的生命週期。以及不同的graphicbuffer::handlewrapmethod,對應的如何處理這個graphicbuffer的構造和析構

對於初學者,可以參考frameworks/native/ui/tests的目錄下的測試用例,寫一些簡單的graphicbuffer的sample。

#include

#include

#include

using

namespace android;

constexpr

uint32_t ktestwidth =

1024

;constexpr

uint32_t ktestheight =

200;

constexpr

uint32_t ktestlayercount =1;

constexpr

uint64_t ktestusage = graphicbuffer::usage_sw_write_often;

constexpr pixelformat format = pixel_format_rgba_8888;

//填充buffer的資料,以及引數設定

void

fillrgba8buffer

(uint8_t

* buf,

int w,

int h,

int stride)}}

}class

mythread

:public thread

public

:explicit

mythread

(const native_handle_t* inhandle)

~mythread()

};int main (

void

)

說明: 以上的sample,大致的意思是,在主線程先建立乙個graphicbuffer,然後把這個native_handle_t傳遞給mythread,這個mythread會建立乙個新的graphicbuffer,那這些graphicbuffer的建構函式中有乙個關鍵的引數graphicbuffer::handlewrapmethod.

標頭檔案graphicbuffer.h中說明如下:

enum handlewrapmethod :

uint8_t

;

這個method在整個android的工程中,用的比較多,因為這個比較安全,但是這個也是需要按照一定的規則使用,因為上層呼叫這個在使用clone_handle建立出來的graphicbuffer。

比如說有些gpu的晶元方實現driver的時候,要求上層要保證gpu使用的時候這個graphicbuffer的生命週期有效,這個buffer的引用計數不能減到0,因為如果上層還有在用這個handle的時候,gpu釋放,根據不同的廠家gpu的實現,出現不同的問題。有些gpu釋放graphicbuffer的時候,對應的handle被lock的話,有些gpu的driver是實現不會處理這個error的資訊,只拋乙個warning,最種可能導致gralloc上記憶體洩漏。

接著說clone_handle的作用,這個method的使用,是為了保證,程序或者是執行緒之間傳遞這個native_handle_t的時候,防止這個handle對應的實際物理記憶體被別的程序或者執行緒釋放掉,需要呼叫

native_handle_create 建立乙個新的native_handle_t,對這個物理buffer引用+

1

其實也是呼叫了dup的方法,複製出來乙個這個handle對應的fd,就是在kernel那邊註冊下,告訴kernel或者是實際物理記憶體管理者,這個記憶體我還在用,需要把這個buffer的引用計數+1,不能被釋放。等我不用的時候,把這個

native_handle_close

native_handle_delete的時候,再把這個buffer的引用計數-

1。

注:那這塊實際的buffer釋放,是不確定的,誰最後呼叫了引用計數-1,正好踩到計數0的話,就可能會真的析構這個物理buffer。

native_handle_create –>

native_handle_close

((native_handle_t *

)psnativehandle)

->

native_handle_delete

((native_handle_t *

)psnativehandle)

因為graphicbuffer的構造和析構會根據method,決定是否去建立新的native_handle_t,wrap_handle是表示,只使用這個native_handle_t,不管理這個native_handle_t對應的記憶體釋放。

sample2 簡化為三步:

第一步:sp test1 =

newgraphicbuffer

(…)-

> 建立graphicbuffer,應該是呼叫下面的模板類生成sp的指標

sp的模板類如下:

template

<

typename t>

sp& sp

::operator

=(t* other)

第二步: test1.

clear

()的呼叫如下:

template

<

typename t>

void sp

::clear()

} 第三步:test1 =

nullptr的話,跟第乙個sp指標賦值的過程相同,同樣也會呼叫引用計數-

1

總之:誰踩到了減到0 的點,誰就會接著呼叫graphicbuffer的析構,這個跟物理buffer的析構不是乙個引用,因為物理buffer由驅動或者kernel管理生命週期。

anativewindowbuffer* graphicbuffer::

getnativebuffer()

const

列印graphicbuffer的指標和anativewindowbuffer的指標,但是返回的位址不是相同的,會有一定的偏移。

graphicbuffer=

0xef9701e0

, anativewindowbuffer=

0xef9701e8

這個應該是c++中類繼承的時候強轉的計算,要做偏移之後才能指向aanativewindowbuffer

void graphicbuffer::

free_handle()

else

if(mowner == owndata)

handle =

nullptr

;}

讀寫這個buffer之前需要先lock這個buffer,map出來乙個虛擬位址,寫完或者是讀完之後,需要unlock釋放。

lock和unlock的使用是需要配對,否則會有虛擬記憶體異常的問題或者是gpu的driver異常。

總結

graphicbuffer是可以程序間共享的buffer,程序間傳遞的時候,除了一些graphicbuffer中寬高引數傳遞之外,還有乙個重要的引數,就是這個buffer對應的fd。graphicbuffer對應的物理buffer,在kernel中有對應的管理,也就是物理buffer的引用計數,對於上層不同的應用,每個應用都可以用乙個fd對應這個物理buffer,這個fd在不同的程序中也不一定相同。上面說的native_handle_create 就是生成乙個新的fd,也就是對這個物理buffer的引用計數+1。(這個是從別的部落格和跟同事討論中獲取的一些資訊,可能也表述的不夠精確,但是fd大概的意思就這樣,嘿嘿)

SqlCacheDependency的使用方法

步驟一 sql資料庫必須開啟servicebroker服務,首先檢測是否已經啟用servicebroker,檢測方法 select databasepropertyex 資料庫名稱 isbrokerenabled 1表示已經啟用0表示沒有啟用 步驟二 如果servicebroker沒有啟用,使用下面...

UITabBarController的使用心得

這段時間了解下uitabbarcontroller,今天把我遇到的問題和心得記錄下。網上有很多uitabbarcontroller的資料,對於一些uitabbarcontroller的基礎性知識,在這裡我就不囉嗦了。可以看這裡 今天我要說的是自己的一些不同於網上的的心得。官方的一副還是要貼出來。我也...

UITabBarController的使用步驟

初始化 uitabbarcontroller 設定uiwindow的rootviewcontroller為 uitabbarcontroller 根據具體情況,通過addchildviewcontroller方法新增對應個數的子控制器 uitabbarcontroller新增控制器的方式有2種 新增...