Android的Graphic系統分析之skia_第1頁
Android的Graphic系統分析之skia_第2頁
Android的Graphic系統分析之skia_第3頁
Android的Graphic系統分析之skia_第4頁
Android的Graphic系統分析之skia_第5頁
已閱讀5頁,還剩12頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、skia庫Skia庫是一個外部庫,代碼位于external/skia/下面,生成的庫名稱是libskia.so。Skia庫負責2維圖形的繪制,繪制的結果最終一般以位圖的形式存放在內存的一塊緩沖區中。我們可以從它里面幾個比較重要的類來了解它到底完成什么功能。使用SkCanvas,可以將繪制(drawing)結果保存到一個設備如位圖(bitmap)中,這些繪制操作包含一系列幾何圖形的繪制,如繪制點、線、矩形、多邊形、橢圓和圓弧等幾何圖形。Canvas.cpp調用了skia庫的API,有的調用僅僅是對SkCanvas的簡單包裹。繪制的狀態(State)封裝在Paint類中,如繪制的線條粗細、線條顏色

2、、區域如何填充、線條形狀等。SkBitmap是光柵位圖,它包含高度和寬度兩個整數以及格式(配置config規定),也可以通過getAddr()獲取存儲實際像素(pixel)塊的地址。一副圖形可以通過它的像素位圖來保存,也可以通過保存它的繪制過程通過SkPicture保存起來,然后寫到文件里,最后通過繪制過程恢復圖形。另外,skia也包括將YUV格式轉變為Jpg的編碼,見YuvToJpegEncoder.cpp。Java部分通過JNI調用Skia關系如下,包括但不限于下圖中的四個類。庫libsurfaceflinger_client.so庫libsurfaceflinger_client.so鏈

3、接到應用程序中,也鏈接到server側(主要因為layer state管理和內存控制塊等類),因此,其大多數類運行在應用程序所在進程空間中,它通過Binder與與進程sufaceflinger進行交互。它的代碼位于frameworks/base/libs/surfaceflinger_client下面,SurfaceComposerClient/SurfaceControl如JNI層章節所述,在創建SurfaceSession(Java)時,會創建SurfaceComposerClient對象,并將SurfaceComposerClient對象指針保存到SurfaceSession(Java)

4、的mClient中。我們來看下創建SurfaceComposerClient對象時還發生了什么?SurfaceComposerClient繼承自RefBase,所以在第一次初始化時,會執行其重載的onFirstRef。在onFirstRef中,會獲取Composer Service,也就是SurfaceFlinger在client側的binder-ISurfaceComposer,接著使用它建立client connection連接(實際上是分配一個用于兩側通訊的共享內存塊),獲取ISurfaceComposerClient,最后創建layer_state_t,保存窗口狀態,用于兩側的窗口狀態

5、通訊。SurfaceComposerClient可以加入到列表中由Composer來維護。SurfaceControl對象指針保存在Surface(Java)中的mSurfaceControl。SurfaceControl借助于SurfaceComposerClient,實現對UI控件的一些操作:· show/hide: 顯示隱藏操作 · setSize/setPosition: 設置大小和位置 · SetLayer:設置圖層 · freeze/unfreeze:凍結與去凍結操作,即是否更新屏幕 · SetAlpha:設置Alpha通道,即設置

6、透明等級 · SetMatrix:設置平移矩陣 · setFlags:設置其它標志 這些SurfaceControl類的功能實現僅僅是對SurfaceComposerClient的簡單封裝。可以通過SurfaceComposerClient的函數獲取Display的個數、高、寬、旋轉方向以及其它信息。它是通過ComposerService中的控制塊信息來實現的。ScreenshotClient包含屏幕截屏寬(mWidth)和高(mHeight)以及像素格式(PixelFormat),截圖數據保存在IMemoryHeap中(mHeap)。它是調用ISurfaceCompose

7、r的captureScreen函數來實現的。SurfaceSurface類繼承自EGLNativeBase模板類,因此它實際上一個ANativeWindow,只不過該模板給它添加了引用計數功能,并可安全地進行類型轉換。class Surface: public EGLNativeBase<ANativeWindow, Surface, RefBase>上層應用程序各有自己的surface,因此多個surface會同時存在,這些surface在本側就是SurfaceComposerClient所代表,它們可以添加到Composer類維護的列表中。SurfaceControl會使用Su

8、rfaceClient和Surface去完成相應功能,SurfaceControl的getSurface函數會創建Surface,從而也會導致SurfaceClient的創建,進而相應的ISurfaceClientComposer等會被創建。ISurfaceComposerISurfaceComposer是SurfaceFlinger在client側的一個binder,提供的接口用于對整個屏幕的全局性的管理,如方向旋轉、屏幕快照、屏幕事件、屏幕更新的凍結與去凍結等。它提供的接口對應的枚舉類型有:enum / Note: BOOT_FINISHED must remain this value,

9、 it is called from/ Java by ActivityManagerService.BOOT_FINISHED = IBinder:FIRST_CALL_TRANSACTION,CREATE_CONNECTION,CREATE_CLIENT_CONNECTION,GET_CBLK,OPEN_GLOBAL_TRANSACTION,CLOSE_GLOBAL_TRANSACTION,SET_ORIENTATION,FREEZE_DISPLAY,UNFREEZE_DISPLAY,SIGNAL,CAPTURE_SCREEN,TURN_ELECTRON_BEAM_OFF,TURN_ELE

10、CTRON_BEAM_ON;它是通過Binder進行IPC通訊的接口,BpSurfaceComposer是client一側, BnSurfaceComposer是service一側。它們都繼承自各自的模板類BpInterface和BnInterface,這兩個模板類完成雙重繼承的功能,一個繼承IPC通訊的API接口,一個繼承Binder功能。RefBase用于索引計數,類IInterface和ISurface定義了IPC通訊的接口API,IBinder/BBinder使雙方具備Binder通訊功能。其中CREATE_CONNECTION和REATE_CLIENT_CONNECTION打開關閉一

11、個Transaction,在打開和關閉的過程中,可以設置狀態,實現窗口管理。狀態變化更改是在一個事務(transaction)中進行的。其類繼承關系如下:根據Binder繼承關系規則,client側的接口調用通過最終是由Bn側的子類完成。我們就可以知道它的它動態的調用關系如下,左側的調用者一般可以通過指向ISurfaceComposer的智能指針將操作將調用到SurfaceFlinger類的成員函數。ComposerService對IsurfaceComposer進行了包裹,使用它的getComposerService函數可以獲取IsurfaceComposer。另外,ComposerServ

12、ice還包含了surface_flinger_cblk_t控制塊信息,該內存塊位于Ashem內存上,由SurfaceFlinger申請,并依據display硬件信息填充字段值。client端程序通過讀取它,即可得到各display的信息。struct display_cblk_t/dispaly的各項信息uint16_t w;uint16_t h;uint8_t format;uint8_t orientation;uint8_t reserved2;float fps;float density;float xdpi;float ydpi;uint32_t pad2;struct surfa

13、ce_flinger_cblk_t / 4KB max/控制信息塊uint8_t connected;uint8_t reserved3;uint32_t pad7;display_cblk_t displaysSharedBufferStack:NUM_DISPLAY_MAX;/最多4個display;在SufraceFlinger的readyToRun會申請內存,并依據DisplayHardWare中得到display信息:/ create the shared control-blockmServerHeap = new MemoryHeapBase(4096,MemoryHeapBas

14、e:READ_ONLY, “SurfaceFlinger read-only heap”);/分配內存,沒有指定設備名稱或描述符fd,默認使用AShem上的內存LOGE_IF(mServerHeap=0, “cant create shared memory dealer”);mServerCblk = /得到內存基址static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase();LOGE_IF(mServerCblk=0, “cant get to shared control blocks address”);new

15、(mServerCblk) surface_flinger_cblk_t;/ initialize primary screen/ (other display should be initialized in the same manner, but / asynchronously, as they could come and go. None of this is supported yet).const GraphicPlane& plane(graphicPlane(dpy);const DisplayHardware& hw = plane.displayHard

16、ware();const uint32_t w = hw.getWidth();const uint32_t h = hw.getHeight();const uint32_t f = hw.getFormat();hw.makeCurrent();/ initialize the shared control blockmServerCblk->connected |= 1<<dpy;display_cblk_t* dcblk = mServerCblk->displays + dpy;memset(dcblk, 0, sizeof(display_cblk_t);/

17、給結構體賦值,同一塊內存上,client側可以立即得到dcblk->w = plane.getWidth();dcblk->h = plane.getHeight();dcblk->format = f;dcblk->orientation = ISurfaceComposer:eOrientationDefault;dcblk->xdpi = hw.getDpiX();dcblk->ydpi = hw.getDpiY();dcblk->fps = hw.getRefreshRate();dcblk->density = hw.getDensit

18、y();IsurfaceComposerClientISurfaceComposerClient用于通過Binder與SurfaceFlinger交互,創建和銷毀ISurface,它也可以獲取控制塊。在SurfaceFlinger側會有兩種類型的surface:Client(用于創建銷毀ISurace)和UserClient(用于獲取控制塊進行通訊)。它提供的接口對應的枚舉類型如下:enum GET_CBLK = IBinder:FIRST_CALL_TRANSACTION,GET_TOKEN,CREATE_SURFACE,DESTROY_SURFACE,SET_STATE;動態調用關系圖,調

19、用者通過對IsurfaceComposerClient的引用,最后由SufaceFlinger進程中的Client或UserClient來完成:ISurfaceIsurface提供了一個與SufaceFlinger側進行IPC交互的接口,它主要功能是操作緩沖區。我們可以從ISurface這個純虛類中看出起定義的接口操作:enum REGISTER_BUFFERS = IBinder:FIRST_CALL_TRANSACTION,UNREGISTER_BUFFERS,POST_BUFFER, / one-way transactionCREATE_OVERLAY,REQUEST_BUFFER,S

20、ET_BUFFER_COUNT,;這些枚舉就是所支持的接口操作,相應地對應著純虛成員函數。我們可以望文生義理解其含義。如下圖,BpSurface是client一側, BnSurface是service一側。它們都繼承自各自的模板類BpInterface和BnInterface,這兩個模板類完成雙重繼承的功能,一個繼承IPC通訊的API接口,一個繼承Binder功能。RefBase用于索引計數,類IInterface和ISurface定義了IPC通訊的接口API,IBinder/BBinder使雙方具備Binder通訊功能。類繼承關系圖動態調用關系如下圖所示:sp<Isurface>

21、Surface flinger制塊在文件SharedBufferStack.h中定義了一個結構體,它是為了通過共享內存的方式快速獲取系統所有display物理信息,這個控制塊由結構體surface_flinger_cblk_t定義:struct display_cblk_t/顯示控制塊,Android中默認支持最多4個diaplayuint16_t w; /display的寬uint16_t h; /display的高uint8_t format; /格式uint8_t orientation; /旋轉方向uint8_t reserved2; /保留字節float fps; /刷新率float

22、 density; /密度float xdpi;/x方向上的解析度,每英寸的點陣數(dots/inch)float ydpi;/y方向上的解析度uint32_t pad2;/填充字節;struct surface_flinger_cblk_t / 4KB maxuint8_t connected;/是否連接uint8_t reserved3;/保留字節uint32_t pad7;/填充字節display_cblk_t displaysSharedBufferStack:NUM_DISPLAY_MAX;/支持最多4個的display;Java層在創建一個SurfaceSession實例時,建立到

23、server側的連接,這個連接的動作實際就是分配內存、創建surface_flinger_cblk_t對象并初始化獲得初始值、以及可以跨進程訪問的過程。具體過程是:在client一側,創建Surface Session時,會創建一個SurfaceComposerClient對象,接著會調用SurfaceComposerClient:onFirstRef:void SurfaceComposerClient:onFirstRef()/第一次創建對象時被調用sp<ISurfaceComposer> sm(getComposerService();/導致獲取全局控制塊if (sm !=

24、0) sp<ISurfaceComposerClient> conn = sm->createConnection();/創建一個連接,surface flinger側會創建一個Client對象if (conn != 0) mClient = conn;Composer:addClient(this);mPrebuiltLayerState = new layer_state_t;mStatus = NO_ERROR;在上面的代碼中,先在ComposerService的構造函數中獲取surface flinger控制塊。ComposerService(也就是ISurfaceC

25、omposer的Wrapper)構造函數獲取surface flinger控制塊的過程如下:ComposerService:ComposerService(): Singleton<ComposerService>() const String16 name(“SurfaceFlinger”);while (getService(name, &mComposerService) != NO_ERROR) usleep(250000);mServerCblkMemory = mComposerService->getCblk();/獲取IMemoryHeapmServe

26、rCblk = static_cast<surface_flinger_cblk_t volatile *>(mServerCblkMemory->getBase();/在IMemoryHeap中的基址指針轉換為surface_flinger_cblk_t指針另外,SurfaceComposerClient的onFirstRef會創建一個connection,它的目的是創建代理對象,用于Binder IPC通訊,ISurfaceComposerClient接口強指針指向該代理對象。在server側,它只是調用Client(也就是ISurfaceComposerClient接口

27、在server側的真正實現者)構造函數創建一個Client對象進行類型轉換后返回。而實際的內存分配是在server側創建SurfaceFlinger后準備運行其工作線程時完成的,見SurfaceFlinger:readyToRun函數:status_t SurfaceFlinger:readyToRun()LOGI( “SurfaceFlingers main thread ready to run. ”“Initializing graphics H/W”);/ we only support one display currentlyint dpy = 0;/ initialize the

28、 main displayGraphicPlane& plane(graphicPlane(dpy);DisplayHardware* const hw = new DisplayHardware(this, dpy);plane.setDisplayHardware(hw);/ create the shared control-block/創建共享控制塊,因未指定在何處分配內存,默認的是ashmem上mServerHeap = new MemoryHeapBase(4096,MemoryHeapBase:READ_ONLY, “SurfaceFlinger read-only he

29、ap”);LOGE_IF(mServerHeap=0, “cant create shared memory dealer”);mServerCblk = static_cast<surface_flinger_cblk_t*> (mServerHeap->getBase();/獲取基址LOGE_IF(mServerCblk=0, “cant get to shared control blocks address”);new(mServerCblk) surface_flinger_cblk_t;/ initialize primary screen/ (other dis

30、play should be initialized in the same manner, but/ asynchronously, as they could come and go. None of this is supported yet).const GraphicPlane& plane(graphicPlane(dpy);const DisplayHardware& hw = plane.displayHardware();const uint32_t w = hw.getWidth();const uint32_t h = hw.getHeight();con

31、st uint32_t f = hw.getFormat();hw.makeCurrent();/ initialize the shared control blockmServerCblk->connected |= 1<<dpy;/下面是為共享控制塊賦值display_cblk_t* dcblk = mServerCblk->displays + dpy;memset(dcblk, 0, sizeof(display_cblk_t);dcblk->w = plane.getWidth();dcblk->h = plane.getHeight();dcb

32、lk->format = f;dcblk->orientation = ISurfaceComposer:eOrientationDefault;dcblk->xdpi = hw.getDpiX();dcblk->ydpi = hw.getDpiY();dcblk->fps = hw.getRefreshRate();dcblk->density = hw.getDensity();/省略部分代碼它為該控制塊在ashmem上分配內存并對其初始化賦值。SharedClient控制塊在SurfaceControl的getSurface() 時,會創建一個Surf

33、ace,接著調用SurfaceClient的構造函數,由于SurfaceClient是singleton,即系統中只有一個實例,因此,在其第一次創建時調用了構造函數,而在其構造函數中調用了createClientConnection,這個就是建立連接的過程,就是分配內存控制塊的過程。在client側,其代碼如下:SurfaceClient(): Singleton<SurfaceClient>(), mStatus(NO_INIT)sp<ISurfaceComposer> /獲取Composer servicesf(ComposerService:getComposer

34、Service();mComposerService = sf;mClient = sf->createClientConnection();/創建client連接if (mClient != NULL) /創建成功的話mControlMemory = mClient->getControlBlock();/獲取內存塊if (mControlMemory != NULL) mControl = static_cast<SharedClient *>(mControlMemory->getBase();/得到基地址,并轉換為SharedClient指針,然后賦值給m

35、Controlif (mControl) mStatus = NO_ERROR;在server側,它調用UserClient的構造函數:UserClient:UserClient(const sp<SurfaceFlinger>& flinger): ctrlblk(0), mBitmap(0), mFlinger(flinger)const int pgsize = getpagesize();/獲取內存頁大小const int cblksize = /控制塊大小,即進行頁對齊后的SharedClient大小(sizeof(SharedClient)+(pgsize-1)

36、&(pgsize-1);mCblkHeap = new MemoryHeapBase(cblksize, 0,/在ashmem上分配內存“SurfaceFlinger Client control-block”);ctrlblk = static_cast<SharedClient *>(mCblkHeap->getBase();/指針類型轉換if (ctrlblk) / construct the shared structure in-place.new(ctrlblk) SharedClient;/調用構造函數初始化內存塊對象也就是說,建立一個clientCon

37、nection的過程,也就是在server側:在堆上分配一塊頁對齊的內存塊,它被用來存儲SharedClient對象;之后,client側同樣也擁有該塊內存,同樣也被解釋為SharedClient對象指針。TODO:它們是跨進程的,所以通過IMemoryHeap這個binder接口來操作。那么SharedClient是何方神圣呢?在頭文件SharedBufferStack.h中有代碼注釋:“These classes manage a stack of buffers in shared memory.SharedClient: represents a client with several

38、 stacksSharedBufferStack: represents a stack of buffersSharedBufferClient: manipulates the SharedBufferStack from the client sideSharedBufferServer: manipulates the SharedBufferStack from the server sideBuffers can be dequeued until there are none available, they can be lockedunless they are in use

39、by the server, which is only the case for the lastdequeue-able buffer. When these various conditions are not met, the callerwaits until the condition is met.”我們先來看一下比較重要的一個類SharedBufferStackclass SharedBufferStack/省略部分代碼struct SmallRect /定義了一個矩形:左上角和右下角的坐標uint16_t l, t, r, b;/定義了一個平面區域,包含了若干(不超過5個)矩形struct FlatRegion / 52 bytes = 4 * (1 + 2*N)static const unsig

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論