Android 中的framebuffer和SurFaceFlinger的關係
FrameBuffer 在Android中並不像在其它GUI那樣直觀,抽象的層次比較多,加上GUI的更新是通過OpenGLES來做的。所以讓人很難搞清GUI更新的整個流程,最近要準備一個講稿,所以花了一些去研究,這裡做點筆記供大家參考,原始碼是基於高通平臺的,這些程式碼在網上都可以下載。
FrameBuffer 的相關元件如下圖所示:
圖片貼不過來,請到原地址去檢視http://www.linuxgraphics.cn/android/framebuffer_arch.html
- SurfaceFlinger是一個服務,主要是負責合成各視窗的Surface,然後通過OpenGLES顯示到FrameBuffer上。SurfaceFlinger本身比較重要而且比較複雜,以後專門寫一篇吧。
- DisplayHardware是對顯示裝置的抽象,包括FrameBuffer和Overlay。它載入FrameBuffer和Overlay外掛,並初始化OpenGLES:
mNativeWindow = new FramebufferNativeWindow(); framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { overlay_control_open(module, &mOverlayEngine); } surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); eglMakeCurrent(display, surface, surface, context);
- FramebufferNativeWindow 是framebuffer 的抽象,它負責載入libgralloc,並開啟framebuffer裝置。FramebufferNativeWindow並不直接使用 framebuffer,而是自己建立了兩個Buffer:
- queueBuffer負責顯示一個Buffer到螢幕上,它呼叫fb->post去顯示。
- dequeueBuffer獲取一個空閒的Buffer,用來在後臺繪製。
這兩個函式由eglSwapBuffers調過來,調到:
egl_window_surface_v2_t::swapBuffers: nativeWindow->queueBuffer(nativeWindow, buffer); nativeWindow->dequeueBuffer(nativeWindow, &buffer);
- msm7k/liboverlay是Overlay的實現,與其它平臺不同的是,高通平臺上的Overlay並不是提供一個framebuffer裝置,而通過fb0的ioctl來實現的,ioctl分為兩類操作:
OverlayControlChannel用於設定引數,比如設定Overlay的位置,寬度和高度:
mNativeWindow = new FramebufferNativeWindow(); framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { overlay_control_open(module, &mOverlayEngine); } surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); eglMakeCurrent(display, surface, surface, context);
- FramebufferNativeWindow 是framebuffer 的抽象,它負責載入libgralloc,並開啟framebuffer裝置。FramebufferNativeWindow並不直接使用 framebuffer,而是自己建立了兩個Buffer:
- queueBuffer負責顯示一個Buffer到螢幕上,它呼叫fb->post去顯示。
- dequeueBuffer獲取一個空閒的Buffer,用來在後臺繪製。
這兩個函式由eglSwapBuffers調過來,調到:
egl_window_surface_v2_t::swapBuffers: nativeWindow->queueBuffer(nativeWindow, buffer); nativeWindow->dequeueBuffer(nativeWindow, &buffer);
- msm7k/liboverlay是Overlay的實現,與其它平臺不同的是,高通平臺上的Overlay並不是提供一個framebuffer裝置,而通過fb0的ioctl來實現的,ioctl分為兩類操作:
OverlayControlChannel用於設定引數,比如設定Overlay的位置,寬度和高度:
bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) {
ov.dst_rect.x = x;
ov.dst_rect.y = y;
ov.dst_rect.w = w;
ov.dst_rect.h = h;
ioctl(mFD, MSMFB_OVERLAY_SET, &ov);
}
OverlayDataChannel用於顯示Overlay,其中最重要的函式就是queueBuffer:
bool OverlayDataChannel::queueBuffer(uint32_t offset) { mOvData.data.offset = offset; ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) }
- msm7k/libgralloc 是顯示快取的抽象,包括framebuffer和普通Surface的Buffer。
framebuffer只是/dev/graphic/fb0的包裝,Surface的Buffer則是對/dev/pmem、ashmem和GPU記憶體(msm_hw3dm)的包裝,它的目標主要是方便硬體加速,因為 DMA傳輸使用實體地址,要求記憶體在實體地址上連續。
- msm7k/libcopybit這是2D加速庫,主要負責Surface的拉伸、旋轉和合成等操作。它有兩種實現方式:
- copybit.cpp: 基於fb0的ioctl(MSMFB_BLIT)的實現。
- copybit_c2d.cpp: 基於kgsl的實現,只是對libC2D2.so的包裝,libC2D2.so應該是不開源的。
- pmem
- misc/pmem.c: 對實體記憶體的管理,演算法和使用者空間的介面。
- board-msm7x27.c定義了實體記憶體的預設大小:
#define MSM_PMEM_MDP_SIZE 0x1B76000 #define MSM_PMEM_ADSP_SIZE 0xB71000 #define MSM_PMEM_AUDIO_SIZE 0x5B000 #define MSM_FB_SIZE 0x177000 #define MSM_GPU_PHYS_SIZE SZ_2M #define PMEM_KERNEL_EBI1_SIZE 0x1C000
msm_msm7x2x_allocate_memory_regions分配幾大塊記憶體用於給pmem做二次分配。
- KGSL
Kernel Graphics System Layer (KGSL),3D圖形加速驅動程式,原始碼drivers/gpu/msm目錄下,它是對GPU的包裝,給OpenGLES 2.0提供抽象的介面。
- msm_hw3dm
這個我在核心中沒有找到相關程式碼。
- msm_fb
msm_fb.c: framebuffer, overlay和blit的使用者介面。
mdp_dma.c: 對具體顯示裝置的包裝,提供兩種framebuffer更新的方式:
mdp_refresh_screen: 定時更新。
mdp_dma_pan_update: 通過pan display主動更新。
mdp_dma_lcdc.c:針對LCD實現的顯示裝置,mdp_lcdc_updat