Android GUI SurfaceFlinger

本文涉及的源代碼基于 Android-7.1.1r。

一、Android GUI 框架

SurfaceFlinger 是 Android GUI 的核心,但是從 OpenGL_ES 的角度來看,它也只是個(gè)“應(yīng)用程序”。Android 的顯示系統(tǒng)大致框架圖下圖所示:

GUI_STRUCT.png

下面就“由下向上”來逐一分析該框架。

(1) 顯示驅(qū)動(dòng)

Linux 內(nèi)核提供了統(tǒng)一的 framebuffer 顯示驅(qū)動(dòng)。設(shè)備節(jié)點(diǎn)是 /dev/graphics/fb* 或 /dev/fb*,而 fb0 表示第一個(gè) Monitor,當(dāng)前系統(tǒng)實(shí)現(xiàn)中只用到了一個(gè)顯示屏。

(2) HAL 層

Android 的 HAL 層提供了 Gralloc,包括 fb 和 gralloc 兩個(gè)設(shè)備。

  • fb 負(fù)責(zé)打開內(nèi)核中的 framebuffer,初始化配置,并提供 post,setSwapIntervel 等操作接口;
  • gralloc 用于管理幀緩沖區(qū)的分配和釋放。

HAL 層還包含另一個(gè)重要模塊 —— “Composer”,它為廠商自定制“UI合成”提供了接口。Composer 的直接使用者是 SurfaceFlinger 中的 HWComposer,HWComposer 除了負(fù)責(zé)管理 Composer 的 HAL 模塊外,還負(fù)責(zé) VSync 信號(hào)(軟件、硬件)的產(chǎn)生和控制。

(3) FramebufferNativeWindow

FramebufferNativeWindow 是負(fù)責(zé) OpenGL ES(通用函數(shù)庫(kù)) 在 Android 平臺(tái)上本地化的中介之一,它將 Android 的窗口系統(tǒng)與 OpenGL ES 產(chǎn)生聯(lián)系,為 OpenGL ES 配置本地窗口的是 EGL。

(4) EGL

EGL 負(fù)責(zé)為 OpenGL ES 配合本地窗口。OpenGL ES 更多的只是一個(gè)接口協(xié)議,具體實(shí)現(xiàn)即可以采用軟件,也可以采用硬件實(shí)現(xiàn),而 EGL 會(huì)去讀取 egl.cfg,并根據(jù)用戶的設(shè)置來動(dòng)態(tài)加載 libagl(軟件實(shí)現(xiàn))或是 libhgl(硬件實(shí)現(xiàn))。

(5) DisplayDevice

SurfaceFlinger 中持有一個(gè)成員數(shù)組 mDisplays 用來描述系統(tǒng)中支持的各種"顯示設(shè)備",具體有那些 Display 是由 SurfaceFlinger 在 readyToRun 中進(jìn)行判斷并賦值的。DisplayDevice 在初始化的時(shí)候會(huì)調(diào)用 eglGetDisplay,eglCreateWindowSurface 等接口,并利用 EGL 來完成 OpenGL ES 環(huán)境的搭建。

(6) OpenGL ES 模塊

很多模塊都可以調(diào)用 OpenGL ES 提供的 API,其中就包括 SurfaceFLinger 和 DisplayerDevice。

與 OpenGL ES 的相關(guān)的模塊分為以下幾類:

  • 配置類:幫助 OpenGL ES 完成配置,包括 EGL,DisplayHardware 都屬這一類。
  • 依賴類:OpenGL ES 要運(yùn)行的起來所依賴的“本地化”的東西,在上圖中指的就是 FramebufferNativeWindow。
  • 使用類:使用 OpenGL ES 的用戶,如 DisplayDevice 即扮演了使用者,又扮演了構(gòu)建 OpenGL ES 的配置者。

二、HAL

HAL 是子系統(tǒng)(顯示系統(tǒng)、音頻系統(tǒng))與 Linux 內(nèi)核驅(qū)動(dòng)之間的統(tǒng)一接口。

HAL 需要解決以下問題:

  • 硬件的抽象;
  • 接口的穩(wěn)定;
  • 靈活的使用。

(1) 硬件抽象

HAL 多數(shù)使用 C 語言編寫,而 C 語言不是面向?qū)ο蟮?,所以具體的“繼承”關(guān)系就沒有像 C++ 或是 Java 這類的面向?qū)ο蟮恼Z言表現(xiàn)的那么直接。在 C 語言中要實(shí)現(xiàn)類似的“繼承”關(guān)系,只需要讓子類的第一個(gè)成員變量是父類結(jié)構(gòu)即可。以 Gralloc 為例,它就是 hw_module_t 的子類,代碼如下:

typedef struct gralloc_module_t {
    struct hw_module_t common; // 父類

    // 結(jié)構(gòu)體中定義函數(shù)指針(結(jié)構(gòu)體中不能定義函數(shù))
    int (*registerBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);

    int (*unregisterBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);

    int (*lock)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr);

    int (*unlock)(struct gralloc_module_t const* module,
            buffer_handle_t handle);

    int (*perform)(struct gralloc_module_t const* module,
            int operation, ... );

    int (*lock_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr);

    int (*lockAsync)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr, int fenceFd);

    int (*unlockAsync)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int* fenceFd);

    int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr, int fenceFd);

    void* reserved_proc[3];
} gralloc_module_t;

(2) 接口的穩(wěn)定

HAL 中的接口必須是穩(wěn)定不變的,Android 系統(tǒng)中已經(jīng)預(yù)定好了這些接口,如下圖所示(源碼位置:hardware/libhardware/include/hardware):

HAL接口.png

(3) 靈活的使用

硬件生產(chǎn)商只要按照 Android 提供的硬件要求來實(shí)現(xiàn) HAL 接口,手機(jī)開發(fā)商只需要移植硬件生產(chǎn)商提供的 HAL 庫(kù)就可以了。

三、Android 終端顯示設(shè)備 ———— Gralloc 和 Framebuffer

Framebuffer 是 Linux 內(nèi)核提供的圖形硬件的抽象描述,它占用了系統(tǒng)內(nèi)存的一部分,是一塊包含屏幕顯示信息的緩沖區(qū)。在 Android 中,F(xiàn)ramebuffer 提供的設(shè)備文件節(jié)點(diǎn)是 /dev/graphics/fb*。這里以 sony Xperia 為例,它的 fb 節(jié)點(diǎn)如下圖所示:

Sony_Xperia_fb.png

Android 的子系統(tǒng)不會(huì)直接使用內(nèi)核驅(qū)動(dòng),而是由 HAL 層來間接引用底層框架。顯示系統(tǒng)也是一樣,它通過 HAL 層來做操作幀緩沖區(qū),而完成這一中介任務(wù)的就是 Gralloc。

3.1、Gralloc 模塊的加載

Gralloc 對(duì)應(yīng)的模塊是在 FramebufferNativeWindow(GUI 結(jié)構(gòu)圖中位于 Grlloc 上方) 的構(gòu)造函數(shù)中加載的(在 Androdi-7.1.1 中是通過 Gralloc1.cpp 進(jìn)行加載的),即:

int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); //

hw_get_module 是上層使用(FramebufferNativeWindow)者加載 HAL 庫(kù)的入口。lib 庫(kù)有以下幾種形式;

gralloc.[ro.hardware].so
gralloc.[ro.product.board].so
gralloc.[ro.board.platform].so
gralloc.[ro.arch].so

當(dāng)以上文件都不存在時(shí),就使用默認(rèn)的:

gralloc.default.so

源碼位置:hardware/libhardware/modules/gralloc/,由 gralloc.cpp,framebuffer.cpp 和 mapper.cpp 三個(gè)主要文件編譯而成。

3.2、Gralloc 提供的接口

Gralloc 是 hw_module_t 的子類,hw_module_t 代碼如下:

typedef struct hw_module_t {
    uint32_t tag;
    uint16_t module_api_version;
#define version_major module_api_version
    uint16_t hal_api_version;
#define version_minor hal_api_version
    const char *id;
    const char *name;
    const char *author;
    struct hw_module_methods_t* methods; // hw_module_t 中必須提供
    void* dso;
#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    uint32_t reserved[32-7];
#endif
} hw_module_t;

typedef struct hw_module_methods_t {
    // 函數(shù)指針,用于打開設(shè)備
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

任何硬件設(shè)備的 HAL 庫(kù)都必須實(shí)現(xiàn) hw_module_methods_t,該結(jié)構(gòu)體中只有一個(gè)函數(shù)指針變量,也就是 open,由于函數(shù)體內(nèi)不能定義函數(shù),所以這里使用了函數(shù)指針。當(dāng)上層使用者調(diào)用 hw_get_module 時(shí),系統(tǒng)首先會(huì)在指定目錄下加載正確的 HAL 庫(kù),然后通過 open 函數(shù)打開指定的設(shè)備。這里 open 方法對(duì)應(yīng)的實(shí)現(xiàn)是 gralloc_device_open()@gralloc.cpp。open接口可以可以幫助上層使用者打開兩種設(shè)備:

  • define GRALLOC_HARDWARE_FB0:主屏
  • define GRALLOC_HARDWARE_GPU0:負(fù)責(zé)圖形緩沖區(qū)的分配和釋放

define 前有“#”,由于格式問題,這里沒有打出。

下面看 gralloc_device_open() 的實(shí)現(xiàn):

// gralloc.cpp
int gralloc_device_open(const hw_module_t* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    // 打開 gralloc 設(shè)備或是打開 fb 設(shè)備。
    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
        gralloc_context_t *dev;
        dev = (gralloc_context_t*)malloc(sizeof(*dev));

        /* initialize our state here */
        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        dev->device.common.close = gralloc_close;

        dev->device.alloc   = gralloc_alloc;
        dev->device.free    = gralloc_free;

        *device = &dev->device.common;
        status = 0;
    } else {
        status = fb_device_open(module, name, device); // 打開 Framebuffer
    }
    return status;
}

下面看 framebuffer 設(shè)備的打開過程:

int fb_device_open(hw_module_t const* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
        /* initialize our state here */
        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); // 分配 hw_device_t 空間,這只是一個(gè)“殼”
        memset(dev, 0, sizeof(*dev)); // 初始化

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        // 核心接口
        dev->device.common.close = fb_close;
        dev->device.setSwapInterval = fb_setSwapInterval;
        dev->device.post            = fb_post;

        dev->device.setUpdateRect = 0;

        private_module_t* m = (private_module_t*)module;

        status = mapFrameBuffer(m); // 內(nèi)存映射 mmap
        if (status >= 0) {
            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
            int format = (m->info.bits_per_pixel == 32)
                         ? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : HAL_PIXEL_FORMAT_RGBX_8888)
                         : HAL_PIXEL_FORMAT_RGB_565;
            const_cast<uint32_t&>(dev->device.flags) = 0;
            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
            const_cast<int&>(dev->device.stride) = stride;
            const_cast<int&>(dev->device.format) = format;
            const_cast<float&>(dev->device.xdpi) = m->xdpi;
            const_cast<float&>(dev->device.ydpi) = m->ydpi;
            const_cast<float&>(dev->device.fps) = m->fps;
            const_cast<int&>(dev->device.minSwapInterval) = 1;
            const_cast<int&>(dev->device.maxSwapInterval) = 1;
            *device = &dev->device.common; // 核心
        }
    }
    return status;
}

其中 fb_context_t 是 framebuffer 內(nèi)部使用的一個(gè)類,它包含了眾多信息,而最終返回的 device 只是其內(nèi)部的 device.common。這種“通用和差異”并存的編碼風(fēng)格在 HAL 層非常常見。

fb_context_t 唯一的成員就是 framebuffer_device_t,這是對(duì) frambuffer 設(shè)備的統(tǒng)一描述。

struct fb_context_t {
    framebuffer_device_t  device;
};

一個(gè)標(biāo)準(zhǔn)的 fb 設(shè)備通常要提供如下的函數(shù)實(shí)現(xiàn):

  • int(post)(struct framebuffer_device_t dev, buffer_handle_t buffer);
    將 buffer 數(shù)據(jù) post 到顯示屏上。要求 buffer 必須與屏幕尺寸一致,并且沒有被 locked。這樣的話
    buffer 內(nèi)容將在下一次 VSYNC 中被顯示出來。

  • int(setSwapInterval)(struct framebuffer_device_t window, int interval);
    設(shè)置兩個(gè)緩沖區(qū)交換的時(shí)間間隔

  • int(setUpdateRect)(struct framebuffer_device_t window, int left, int top, int width, int height);
    設(shè)置刷新區(qū)域,需要 framebuffer 驅(qū)動(dòng)支持“update-on-demand”。也就是說在這個(gè)區(qū)域外的數(shù)據(jù)很可能
    被認(rèn)為無效。

framebuffer_device_t 中的重要成員變量:

typedef struct framebuffer_device_t {
    struct hw_device_t common;
    const uint32_t  flags; // 用來記錄系統(tǒng)幀緩沖區(qū)的標(biāo)志
    const uint32_t  width; // 用來描述設(shè)備顯示屏的寬度
    const uint32_t  height; // 用來描述設(shè)備顯示屏的高度
    const int       stride; // 用來描述設(shè)備顯示屏的一行有多少個(gè)像素點(diǎn)
    const int       format; // 用來描述系統(tǒng)幀緩沖區(qū)的像素格式
    const float     xdpi; // 用來描述設(shè)備顯示屏在寬度上的密度
    const float     ydpi; // 用來描述設(shè)備顯示屏在高度上的密度
    const float     fps; // 用來描述設(shè)備顯示屏的刷新頻率
    const int       minSwapInterval; // 用來描述幀緩沖區(qū)交換前后兩個(gè)圖形緩沖區(qū)的最小時(shí)間間隔
    const int       maxSwapInterval; // 用來描述幀緩沖區(qū)交換前后兩個(gè)圖形緩沖區(qū)的最大時(shí)間間隔
    int reserved[8];//保留
    // 用來設(shè)置幀緩沖區(qū)交換前后兩個(gè)圖形緩沖區(qū)的最小和最大時(shí)間間隔
    int (*setSwapInterval)(struct framebuffer_device_t* window,int interval);
    // 用來設(shè)置幀緩沖區(qū)的更新區(qū)域
    int (*setUpdateRect)(struct framebuffer_device_t* window,int left, int top, int width, int height);
    // 用來將圖形緩沖區(qū)buffer的內(nèi)容渲染到幀緩沖區(qū)中去
    int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
    // 用來通知 fb 設(shè)備,圖形緩沖區(qū)的組合工作已經(jīng)完成
    int (*compositionComplete)(struct framebuffer_device_t* dev);
    void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);
    int (*enableScreen)(struct framebuffer_device_t* dev, int enable);
    // 保留
    void* reserved_proc[6];
} framebuffer_device_t;
變 量 描 述
uint32_t flags 標(biāo)志位,指示framebuffer 的屬性配置
uint32_t width; uint32_t height; framebuffer 的寬和高,以像素為單位
int format framebuffer 的像素格式,比如:HAL_PIXEL_FORMAT_RGBA_8888,HAL_PIXEL_FORMAT_RGBX_8888,HAL_PIXEL_FORMAT_RGB_888,HAL_PIXEL_FORMAT_RGB_565 等等
float xdpi;float ydpi; x和y軸的密度(pixel per inch)
float fps 屏幕的每秒刷新頻率,假如無法正常從設(shè)備獲取的話,默認(rèn)設(shè)置為 60Hz
int minSwapInterval;int maxSwapInterval; 該 framebuffer 支持的最小和最大緩沖交換時(shí)間

我們以下面簡(jiǎn)圖來小結(jié)對(duì) Gralloc 的分析:

[圖片上傳失敗...(image-f944da-1542183518291)]

四、Android 本地窗口

Native Window為OpenGL與本地窗口系統(tǒng)之間搭建了橋梁。整個(gè)GGUI系統(tǒng)至少需要兩種本地窗口:

  1. 面向管理者(SurfaceFlinger)
    SurfaceFlinger 是系統(tǒng)中所有 UI 界面的管理者,需要直接或間接的持有“本地窗口”,此本地窗口是
    FramebufferNativeWindow(4.2+ 后被廢棄)。
  2. 面向應(yīng)用程序
    這類本地窗口是 Surface。

正常情況按照 SDK 向?qū)?APK 應(yīng)用程序,是采用 Skia 等第三方圖形庫(kù),而對(duì)于希望使用 OpenGL ES 來完成復(fù)雜界面渲染的應(yīng)用開發(fā)者來說,Android 也提供封裝的 GLSurfaceView(或其他方式)來實(shí)現(xiàn)圖形顯示。

4.1、FramebufferNativeWindow

EGL 需要根據(jù)本地窗口來為 OpenGL/OpenGL ES 創(chuàng)造環(huán)境,但是不論哪一類本地窗口都需要和“本地窗口類型”保持一致。

// /frameworks/native/opengl/include/EGL/eglplatform.h
...
typedef HWND    EGLNativeWindowType;

#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */

typedef int   EGLNativeDisplayType;
typedef void *EGLNativeWindowType;
typedef void *EGLNativePixmapType;

#elif defined(__ANDROID__) || defined(ANDROID) // Android 系統(tǒng)

struct ANativeWindow;
struct egl_native_pixmap_t;

typedef struct ANativeWindow*           EGLNativeWindowType;
...
#elif defined(__unix__) // unix 系統(tǒng)
...
typedef Window   EGLNativeWindowType;

#else
#error "Platform not recognized"
#endif
...

EGLNativeWindowType 在不同系統(tǒng)中對(duì)應(yīng)不同的數(shù)據(jù)類型,而在 Android 中對(duì)應(yīng)的是 ANativeWindow 指針。

// /system/core/include/system/window.h
struct ANativeWindow
{
    ...
    const uint32_t flags;        // 與 Surface 或 update 有關(guān)的屬性
    const int   minSwapInterval; // 最小交換時(shí)間間隔
    const int   maxSwapInterval; // 最大交換時(shí)間間隔
    const float xdpi;            // 水平方向密度 dpi
    const float ydpi;            // 垂直方向密度 dpi
    intptr_t    oem[4];
    ...
    // 設(shè)置交換時(shí)間
    int     (*setSwapInterval)(struct ANativeWindow* window,
                int interval);
    // 向本地窗口查詢相關(guān)信息
    int     (*query)(const struct ANativeWindow* window,
                int what, int* value);
    // 用于執(zhí)行本地窗口的相關(guān)操作
    int     (*perform)(struct ANativeWindow* window,
                int operation, ... );
    int     (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);
    // EGL 通過該接口來申請(qǐng) buffer
    int     (*dequeueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer** buffer, int* fenceFd);
    // EGL 對(duì) buffer 渲染完成后就調(diào)用該接口,來 unlock 和 post buffer
    int     (*queueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer, int fenceFd);
    // 取消一個(gè)已經(jīng) dequeue 的 buffer
    int     (*cancelBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer, int fenceFd);
};

ANativeWindow 更像一份“協(xié)議”,規(guī)定了本地窗口的形態(tài)和功能。下面來分析 FramebufferNativeWindow 是如何履行“協(xié)議”的。

(1) FramebufferNativeWindow 構(gòu)造函數(shù)

FramebufferNativeWindow 構(gòu)造函數(shù)的功能包括:

  • 加載 Gralloc 模塊(GRALLOC_HARDWARE_MODULE_ID)。
  • 打開 fb 和 gralloc(gpu0) 設(shè)備,打開后由 fbDev 和 grDev 管理。
  • 根據(jù)設(shè)備屬性為 FramebufferNativeWindow 賦初值。
  • 根據(jù) FramebufferNativeWindow 的實(shí)現(xiàn)來填充 ANativeWindow 中的“協(xié)議”。
  • 其他必要的初始化。

所有申請(qǐng)到的緩沖區(qū)都由 FramebufferNativeWindow 中的 buffers[] 來記錄,每個(gè)元素是一個(gè) NativeBuffer,該類繼承了 ANativeWindowBuffer, 該類的聲明如下:

// /system/core/include/system/window.h
typedef struct ANativeWindowBuffer
{
    ...
    int width;
    int height;
    int stride;
    int format;
    int usage;

    void* reserved[2];

    buffer_handle_t handle; // 代表內(nèi)存塊的句柄

    void* reserved_proc[8];
} ANativeWindowBuffer_t;

(2) dequeueBuffer

int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
        ANativeWindowBuffer** buffer)
{
    FramebufferNativeWindow* self = getSelf(window);
    Mutex::Autolock _l(self->mutex);
    // 從 FramebufferNativeWindow 對(duì)象中取出 fb 設(shè)備描述符,在構(gòu)造 FramebufferNativeWindow 對(duì)象時(shí),已經(jīng)打開了 fb 設(shè)備
    framebuffer_device_t* fb = self->fbDev;
    // 計(jì)算當(dāng)前申請(qǐng)的圖形緩沖區(qū)在 buffers 數(shù)組中的索引,同時(shí)將下一個(gè)申請(qǐng)的 buffe r的索引保存到 mBufferHead 中
    int index = self->mBufferHead++;
    // 如果申請(qǐng)的下一個(gè) buffer 的索引大于或等于 buffer 總數(shù),則將下一個(gè)申請(qǐng)的 buffer 索引設(shè)置為 0,這樣就實(shí)現(xiàn)了對(duì) buffer 數(shù)組的循環(huán)管理
    if (self->mBufferHead >= self->mNumBuffers)
        self->mBufferHead = 0;
    // 如果當(dāng)前沒有空閑的 buffer,即 mNumFreeBuffers = 0,則線程睡眠等待 buffer 的釋放
    while (!self->mNumFreeBuffers) {
        self->mCondition.wait(self->mutex);
    }
    // 存在了空閑 buffer,線程被喚醒繼續(xù)執(zhí)行,由于此時(shí)要申請(qǐng)一塊 buffer,因此空閑 buffer 的個(gè)數(shù)又需要減 1
    self->mNumFreeBuffers--;
    // 保存當(dāng)前申請(qǐng)的 buffer 在緩沖區(qū)數(shù)組中的索引位置
    self->mCurrentBufferIndex = index;
    // 得到 buffer 數(shù)組中的 NativeBuffer 對(duì)象指針
    *buffer = self->buffers[index].get();
    return 0;
}

dequeueBuffer 函數(shù)就是從 FramebufferNativeWindow 創(chuàng)建的包含 2 個(gè)圖形緩沖區(qū)的緩沖區(qū)隊(duì)列 buffers 中取出一塊空閑可用的圖形 buffer,如果當(dāng)前緩沖區(qū)隊(duì)列中沒有空閑的 buffer,則當(dāng)前申請(qǐng) buffer 線程阻塞等待,等待其他線程釋放圖形緩沖區(qū)。mNumFreeBuffers 用來描述可用的空閑圖形 buffer 個(gè)數(shù),index 記錄當(dāng)前申請(qǐng) buffer 在圖形緩沖區(qū)隊(duì)列中的索引位置,mBufferHead 指向下一次申請(qǐng)的圖形 buffer 的位置,由于我們是循環(huán)利用兩個(gè)緩沖區(qū)的,所以如果這個(gè)變量的值超過 mNumBuffers,就需要置 0。也就是說 mBufferHead 的值永遠(yuǎn)只能是 0或者 1。

4.2、SurfaceView

Surface 也繼承了 ANativeWindow:

class Surface: public ANativeObjectBase<ANativeWindow, Surface, RefBase>{ ... }

Surface 是面向 Android 系統(tǒng)中所有 UI 應(yīng)用程序的,即它承擔(dān)著應(yīng)用進(jìn)程中的 UI 顯示需求。

Surface 需要面向上層實(shí)現(xiàn)(主要是 Java 層)提供繪制圖像的畫板。SurfaceFlinger 需要收集系統(tǒng)中所有應(yīng)用程序繪制的圖像數(shù)據(jù),然后集中顯示到物理屏幕上。Surface 需要扮演相應(yīng)角色,本質(zhì)上還是由 SurfaceFlinger 服務(wù)統(tǒng)一管理的,涉及到很多跨進(jìn)程的通信細(xì)節(jié)。

下面來看 Surface 中的關(guān)鍵成員變量:

成員變量 說明
sp<IGraphicsBufferProducer> mGraphicsBufferProducer Surface 核心變量
BufferSlot mSlots[32] Surface 內(nèi)部存儲(chǔ) buffer 的地方,BufferSlot 內(nèi)不包括:GraphicsBuffer 和 dirtyRegion,當(dāng)用戶 dequeue 時(shí)將申請(qǐng)內(nèi)存

Surface 將通過 mGraphicBufferProducer 來獲取 buffer,這些緩沖區(qū)會(huì)被記錄在 mSlots 中數(shù)據(jù)中。mGraphicBufferProducer 這一核心成員的初始化流程如下:

  • ViewRootImpl 持有一個(gè) Java 層的 Surface 對(duì)象(mSurface)。
  • ViewRootImpl 向 WindowManagerService 發(fā)起 relayout 請(qǐng)求,此時(shí) mSurface 被賦予真正的有效值,
    將輾轉(zhuǎn)生成的 SurfaceControl 通過S urface.copyFrom() 函數(shù)復(fù)制到 mSurface 中。

由此,Surface 由 SurfaceControl 管理,SurfaceControl 由 SurfaceComposerClient 創(chuàng)建。SurfaceComposerClient 獲得的匿名 Binder 是 ISurfaceComposer,其服務(wù)端實(shí)現(xiàn)是 SurfaceFlinger。而 Surface 依賴的 IGraphicBufferProducer 對(duì)象在 Service 端的實(shí)現(xiàn)是 BufferQueue。

class SurfaceFlinger :
  public BinderService<SurfaceFlinger>, // 在 ServiceManager 中注冊(cè)為 SurfaceFlinger
  public BnSurfaceComposer, // 實(shí)現(xiàn)的接口卻叫 ISurfaceComposer

Buffer,Consumer,Producer 是“生產(chǎn)者-消費(fèi)者”模型中的 3 個(gè)參與對(duì)象,如何協(xié)調(diào)好它們的工作是應(yīng)用程序能否正常顯示UI的關(guān)鍵。Buffer 是 BufferQueue,Producer 是應(yīng)用程序,Consumer 是 SurfaceFlinger。

五、BufferQueue

To be continued ....

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容