c语言调用android surface,Android GUI SurfaceFlinger
本文涉及的源代碼基于 Android-7.1.1r。
一、Android GUI 框架
SurfaceFlinger 是 Android GUI 的核心,但是從 OpenGL_ES 的角度來看,它也只是個“應用程序”。Android 的顯示系統(tǒng)大致框架圖下圖所示:
GUI_STRUCT.png
下面就“由下向上”來逐一分析該框架。
(1) 顯示驅動
Linux 內(nèi)核提供了統(tǒng)一的 framebuffer 顯示驅動。設備節(jié)點是 /dev/graphics/fb* 或 /dev/fb*,而 fb0 表示第一個 Monitor,當前系統(tǒng)實現(xiàn)中只用到了一個顯示屏。
(2) HAL 層
Android 的 HAL 層提供了 Gralloc,包括 fb 和 gralloc 兩個設備。
fb 負責打開內(nèi)核中的 framebuffer,初始化配置,并提供 post,setSwapIntervel 等操作接口;
gralloc 用于管理幀緩沖區(qū)的分配和釋放。
HAL 層還包含另一個重要模塊 —— “Composer”,它為廠商自定制“UI合成”提供了接口。Composer 的直接使用者是 SurfaceFlinger 中的 HWComposer,HWComposer 除了負責管理 Composer 的 HAL 模塊外,還負責 VSync 信號(軟件、硬件)的產(chǎn)生和控制。
(3) FramebufferNativeWindow
FramebufferNativeWindow 是負責 OpenGL ES(通用函數(shù)庫) 在 Android 平臺上本地化的中介之一,它將 Android 的窗口系統(tǒng)與 OpenGL ES 產(chǎn)生聯(lián)系,為 OpenGL ES 配置本地窗口的是 EGL。
(4) EGL
EGL 負責為 OpenGL ES 配合本地窗口。OpenGL ES 更多的只是一個接口協(xié)議,具體實現(xiàn)即可以采用軟件,也可以采用硬件實現(xiàn),而 EGL 會去讀取 egl.cfg,并根據(jù)用戶的設置來動態(tài)加載 libagl(軟件實現(xiàn))或是 libhgl(硬件實現(xiàn))。
(5) DisplayDevice
SurfaceFlinger 中持有一個成員數(shù)組 mDisplays 用來描述系統(tǒng)中支持的各種"顯示設備",具體有那些 Display 是由 SurfaceFlinger 在 readyToRun 中進行判斷并賦值的。DisplayDevice 在初始化的時候會調用 eglGetDisplay,eglCreateWindowSurface 等接口,并利用 EGL 來完成 OpenGL ES 環(huán)境的搭建。
(6) OpenGL ES 模塊
很多模塊都可以調用 OpenGL ES 提供的 API,其中就包括 SurfaceFLinger 和 DisplayerDevice。
與 OpenGL ES 的相關的模塊分為以下幾類:
配置類:幫助 OpenGL ES 完成配置,包括 EGL,DisplayHardware 都屬這一類。
依賴類:OpenGL ES 要運行的起來所依賴的“本地化”的東西,在上圖中指的就是 FramebufferNativeWindow。
使用類:使用 OpenGL ES 的用戶,如 DisplayDevice 即扮演了使用者,又扮演了構建 OpenGL ES 的配置者。
二、HAL
HAL 是子系統(tǒng)(顯示系統(tǒng)、音頻系統(tǒng))與 Linux 內(nèi)核驅動之間的統(tǒng)一接口。
HAL 需要解決以下問題:
硬件的抽象;
接口的穩(wěn)定;
靈活的使用。
(1) 硬件抽象
HAL 多數(shù)使用 C 語言編寫,而 C 語言不是面向對象的,所以具體的“繼承”關系就沒有像 C++ 或是 Java 這類的面向對象的語言表現(xiàn)的那么直接。在 C 語言中要實現(xiàn)類似的“繼承”關系,只需要讓子類的第一個成員變量是父類結構即可。以 Gralloc 為例,它就是 hw_module_t 的子類,代碼如下:
typedef struct gralloc_module_t {
struct hw_module_t common; // 父類
// 結構體中定義函數(shù)指針(結構體中不能定義函數(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)預定好了這些接口,如下圖所示(源碼位置:hardware/libhardware/include/hardware):
HAL接口.png
(3) 靈活的使用
硬件生產(chǎn)商只要按照 Android 提供的硬件要求來實現(xiàn) HAL 接口,手機開發(fā)商只需要移植硬件生產(chǎn)商提供的 HAL 庫就可以了。
三、Android 終端顯示設備 ———— Gralloc 和 Framebuffer
Framebuffer 是 Linux 內(nèi)核提供的圖形硬件的抽象描述,它占用了系統(tǒng)內(nèi)存的一部分,是一塊包含屏幕顯示信息的緩沖區(qū)。在 Android 中,Framebuffer 提供的設備文件節(jié)點是 /dev/graphics/fb*。這里以 sony Xperia 為例,它的 fb 節(jié)點如下圖所示:
Sony_Xperia_fb.png
Android 的子系統(tǒng)不會直接使用內(nèi)核驅動,而是由 HAL 層來間接引用底層框架。顯示系統(tǒng)也是一樣,它通過 HAL 層來做操作幀緩沖區(qū),而完成這一中介任務的就是 Gralloc。
3.1、Gralloc 模塊的加載
Gralloc 對應的模塊是在 FramebufferNativeWindow(GUI 結構圖中位于 Grlloc 上方) 的構造函數(shù)中加載的(在 Androdi-7.1.1 中是通過 Gralloc1.cpp 進行加載的),即:
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); //
hw_get_module 是上層使用(FramebufferNativeWindow)者加載 HAL 庫的入口。lib 庫有以下幾種形式;
gralloc.[ro.hardware].so
gralloc.[ro.product.board].so
gralloc.[ro.board.platform].so
gralloc.[ro.arch].so
當以上文件都不存在時,就使用默認的:
gralloc.default.so
源碼位置:hardware/libhardware/modules/gralloc/,由 gralloc.cpp,framebuffer.cpp 和 mapper.cpp 三個主要文件編譯而成。
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ù)指針,用于打開設備
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
任何硬件設備的 HAL 庫都必須實現(xiàn) hw_module_methods_t,該結構體中只有一個函數(shù)指針變量,也就是 open,由于函數(shù)體內(nèi)不能定義函數(shù),所以這里使用了函數(shù)指針。當上層使用者調用 hw_get_module 時,系統(tǒng)首先會在指定目錄下加載正確的 HAL 庫,然后通過 open 函數(shù)打開指定的設備。這里 open 方法對應的實現(xiàn)是 gralloc_device_open()@gralloc.cpp。open接口可以可以幫助上層使用者打開兩種設備:
define GRALLOC_HARDWARE_FB0:主屏
define GRALLOC_HARDWARE_GPU0:負責圖形緩沖區(qū)的分配和釋放
define 前有“#”,由于格式問題,這里沒有打出。
下面看 gralloc_device_open() 的實現(xiàn):
// gralloc.cpp
int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int status = -EINVAL;
// 打開 gralloc 設備或是打開 fb 設備。
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(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 設備的打開過程:
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 空間,這只是一個“殼”
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(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(dev->device.flags) = 0;
const_cast(dev->device.width) = m->info.xres;
const_cast(dev->device.height) = m->info.yres;
const_cast(dev->device.stride) = stride;
const_cast(dev->device.format) = format;
const_cast(dev->device.xdpi) = m->xdpi;
const_cast(dev->device.ydpi) = m->ydpi;
const_cast(dev->device.fps) = m->fps;
const_cast(dev->device.minSwapInterval) = 1;
const_cast(dev->device.maxSwapInterval) = 1;
*device = &dev->device.common; // 核心
}
}
return status;
}
其中 fb_context_t 是 framebuffer 內(nèi)部使用的一個類,它包含了眾多信息,而最終返回的 device 只是其內(nèi)部的 device.common。這種“通用和差異”并存的編碼風格在 HAL 層非常常見。
fb_context_t 唯一的成員就是 framebuffer_device_t,這是對 frambuffer 設備的統(tǒng)一描述。
struct fb_context_t {
framebuffer_device_t device;
};
一個標準的 fb 設備通常要提供如下的函數(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);
設置兩個緩沖區(qū)交換的時間間隔
int(setUpdateRect)(struct framebuffer_device_t window, int left, int top, int width, int height);
設置刷新區(qū)域,需要 framebuffer 驅動支持“update-on-demand”。也就是說在這個區(qū)域外的數(shù)據(jù)很可能
被認為無效。
framebuffer_device_t 中的重要成員變量:
typedef struct framebuffer_device_t {
struct hw_device_t common;
const uint32_t flags; // 用來記錄系統(tǒng)幀緩沖區(qū)的標志
const uint32_t width; // 用來描述設備顯示屏的寬度
const uint32_t height; // 用來描述設備顯示屏的高度
const int stride; // 用來描述設備顯示屏的一行有多少個像素點
const int format; // 用來描述系統(tǒng)幀緩沖區(qū)的像素格式
const float xdpi; // 用來描述設備顯示屏在寬度上的密度
const float ydpi; // 用來描述設備顯示屏在高度上的密度
const float fps; // 用來描述設備顯示屏的刷新頻率
const int minSwapInterval; // 用來描述幀緩沖區(qū)交換前后兩個圖形緩沖區(qū)的最小時間間隔
const int maxSwapInterval; // 用來描述幀緩沖區(qū)交換前后兩個圖形緩沖區(qū)的最大時間間隔
int reserved[8];//保留
// 用來設置幀緩沖區(qū)交換前后兩個圖形緩沖區(qū)的最小和最大時間間隔
int (*setSwapInterval)(struct framebuffer_device_t* window,int interval);
// 用來設置幀緩沖區(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 設備,圖形緩沖區(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
標志位,指示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
屏幕的每秒刷新頻率,假如無法正常從設備獲取的話,默認設置為 60Hz
int minSwapInterval;int maxSwapInterval;
該 framebuffer 支持的最小和最大緩沖交換時間
我們以下面簡圖來小結對 Gralloc 的分析:
[圖片上傳失敗...(image-f944da-1542183518291)]
四、Android 本地窗口
Native Window為OpenGL與本地窗口系統(tǒng)之間搭建了橋梁。整個GGUI系統(tǒng)至少需要兩種本地窗口:
面向管理者(SurfaceFlinger)
SurfaceFlinger 是系統(tǒng)中所有 UI 界面的管理者,需要直接或間接的持有“本地窗口”,此本地窗口是
FramebufferNativeWindow(4.2+ 后被廢棄)。
面向應用程序
這類本地窗口是 Surface。
正常情況按照 SDK 向導生成 APK 應用程序,是采用 Skia 等第三方圖形庫,而對于希望使用 OpenGL ES 來完成復雜界面渲染的應用開發(fā)者來說,Android 也提供封裝的 GLSurfaceView(或其他方式)來實現(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)中對應不同的數(shù)據(jù)類型,而在 Android 中對應的是 ANativeWindow 指針。
// /system/core/include/system/window.h
struct ANativeWindow
{
...
const uint32_t flags; // 與 Surface 或 update 有關的屬性
const int minSwapInterval; // 最小交換時間間隔
const int maxSwapInterval; // 最大交換時間間隔
const float xdpi; // 水平方向密度 dpi
const float ydpi; // 垂直方向密度 dpi
intptr_t oem[4];
...
// 設置交換時間
int (*setSwapInterval)(struct ANativeWindow* window,
int interval);
// 向本地窗口查詢相關信息
int (*query)(const struct ANativeWindow* window,
int what, int* value);
// 用于執(zhí)行本地窗口的相關操作
int (*perform)(struct ANativeWindow* window,
int operation, ... );
int (*cancelBuffer_DEPRECATED)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer);
// EGL 通過該接口來申請 buffer
int (*dequeueBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer** buffer, int* fenceFd);
// EGL 對 buffer 渲染完成后就調用該接口,來 unlock 和 post buffer
int (*queueBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer, int fenceFd);
// 取消一個已經(jīng) dequeue 的 buffer
int (*cancelBuffer)(struct ANativeWindow* window,
struct ANativeWindowBuffer* buffer, int fenceFd);
};
ANativeWindow 更像一份“協(xié)議”,規(guī)定了本地窗口的形態(tài)和功能。下面來分析 FramebufferNativeWindow 是如何履行“協(xié)議”的。
(1) FramebufferNativeWindow 構造函數(shù)
FramebufferNativeWindow 構造函數(shù)的功能包括:
加載 Gralloc 模塊(GRALLOC_HARDWARE_MODULE_ID)。
打開 fb 和 gralloc(gpu0) 設備,打開后由 fbDev 和 grDev 管理。
根據(jù)設備屬性為 FramebufferNativeWindow 賦初值。
根據(jù) FramebufferNativeWindow 的實現(xiàn)來填充 ANativeWindow 中的“協(xié)議”。
其他必要的初始化。
所有申請到的緩沖區(qū)都由 FramebufferNativeWindow 中的 buffers[] 來記錄,每個元素是一個 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 對象中取出 fb 設備描述符,在構造 FramebufferNativeWindow 對象時,已經(jīng)打開了 fb 設備
framebuffer_device_t* fb = self->fbDev;
// 計算當前申請的圖形緩沖區(qū)在 buffers 數(shù)組中的索引,同時將下一個申請的 buffe r的索引保存到 mBufferHead 中
int index = self->mBufferHead++;
// 如果申請的下一個 buffer 的索引大于或等于 buffer 總數(shù),則將下一個申請的 buffer 索引設置為 0,這樣就實現(xiàn)了對 buffer 數(shù)組的循環(huán)管理
if (self->mBufferHead >= self->mNumBuffers)
self->mBufferHead = 0;
// 如果當前沒有空閑的 buffer,即 mNumFreeBuffers = 0,則線程睡眠等待 buffer 的釋放
while (!self->mNumFreeBuffers) {
self->mCondition.wait(self->mutex);
}
// 存在了空閑 buffer,線程被喚醒繼續(xù)執(zhí)行,由于此時要申請一塊 buffer,因此空閑 buffer 的個數(shù)又需要減 1
self->mNumFreeBuffers--;
// 保存當前申請的 buffer 在緩沖區(qū)數(shù)組中的索引位置
self->mCurrentBufferIndex = index;
// 得到 buffer 數(shù)組中的 NativeBuffer 對象指針
*buffer = self->buffers[index].get();
return 0;
}
dequeueBuffer 函數(shù)就是從 FramebufferNativeWindow 創(chuàng)建的包含 2 個圖形緩沖區(qū)的緩沖區(qū)隊列 buffers 中取出一塊空閑可用的圖形 buffer,如果當前緩沖區(qū)隊列中沒有空閑的 buffer,則當前申請 buffer 線程阻塞等待,等待其他線程釋放圖形緩沖區(qū)。mNumFreeBuffers 用來描述可用的空閑圖形 buffer 個數(shù),index 記錄當前申請 buffer 在圖形緩沖區(qū)隊列中的索引位置,mBufferHead 指向下一次申請的圖形 buffer 的位置,由于我們是循環(huán)利用兩個緩沖區(qū)的,所以如果這個變量的值超過 mNumBuffers,就需要置 0。也就是說 mBufferHead 的值永遠只能是 0或者 1。
4.2、SurfaceView
Surface 也繼承了 ANativeWindow:
class Surface: public ANativeObjectBase{ ... }
Surface 是面向 Android 系統(tǒng)中所有 UI 應用程序的,即它承擔著應用進程中的 UI 顯示需求。
Surface 需要面向上層實現(xiàn)(主要是 Java 層)提供繪制圖像的畫板。SurfaceFlinger 需要收集系統(tǒng)中所有應用程序繪制的圖像數(shù)據(jù),然后集中顯示到物理屏幕上。Surface 需要扮演相應角色,本質上還是由 SurfaceFlinger 服務統(tǒng)一管理的,涉及到很多跨進程的通信細節(jié)。
下面來看 Surface 中的關鍵成員變量:
成員變量
說明
sp mGraphicsBufferProducer
Surface 核心變量
BufferSlot mSlots[32]
Surface 內(nèi)部存儲 buffer 的地方,BufferSlot 內(nèi)不包括:GraphicsBuffer 和 dirtyRegion,當用戶 dequeue 時將申請內(nèi)存
Surface 將通過 mGraphicBufferProducer 來獲取 buffer,這些緩沖區(qū)會被記錄在 mSlots 中數(shù)據(jù)中。mGraphicBufferProducer 這一核心成員的初始化流程如下:
ViewRootImpl 持有一個 Java 層的 Surface 對象(mSurface)。
ViewRootImpl 向 WindowManagerService 發(fā)起 relayout 請求,此時 mSurface 被賦予真正的有效值,
將輾轉生成的 SurfaceControl 通過S urface.copyFrom() 函數(shù)復制到 mSurface 中。
由此,Surface 由 SurfaceControl 管理,SurfaceControl 由 SurfaceComposerClient 創(chuàng)建。SurfaceComposerClient 獲得的匿名 Binder 是 ISurfaceComposer,其服務端實現(xiàn)是 SurfaceFlinger。而 Surface 依賴的 IGraphicBufferProducer 對象在 Service 端的實現(xiàn)是 BufferQueue。
class SurfaceFlinger :
public BinderService, // 在 ServiceManager 中注冊為 SurfaceFlinger
public BnSurfaceComposer, // 實現(xiàn)的接口卻叫 ISurfaceComposer
Buffer,Consumer,Producer 是“生產(chǎn)者-消費者”模型中的 3 個參與對象,如何協(xié)調好它們的工作是應用程序能否正常顯示UI的關鍵。Buffer 是 BufferQueue,Producer 是應用程序,Consumer 是 SurfaceFlinger。
五、BufferQueue
To be continued ....
總結
以上是生活随笔為你收集整理的c语言调用android surface,Android GUI SurfaceFlinger的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java界面化二叉排序树_105-线索化
- 下一篇: java 1000到9999_java