Android圖形顯示之硬件抽象層Gralloc【轉】


https://blog.csdn.net/yangwen123/article/details/12192401

 

FrameBuffer驅動程序分析文中介紹了Linux系統下的顯示驅動框架,每個顯示屏被抽象為一個幀緩沖區,注冊到FrameBuffer模塊中,並在/dev/graphics目錄下創建對應的fbX設備。Android系統在硬件抽象層中提供了一個Gralloc模塊,封裝了對幀緩沖區的所有訪問操作。用戶空間的應用程序在使用幀緩沖區之間,首先要加載Gralloc模塊,並且獲得一個gralloc設備和一個fb設備。有了gralloc設備之后,用戶空間中的應用程序就可以申請分配一塊圖形緩沖區,並且將這塊圖形緩沖區映射到應用程序的地址空間來,以便可以向里面寫入要繪制的畫面的內容。最后,用戶空間中的應用程序就通過fb設備來將已經准備好了的圖形緩沖區渲染到幀緩沖區中去,即將圖形緩沖區的內容繪制到顯示屏中去。相應地,當用戶空間中的應用程序不再需要使用一塊圖形緩沖區的時候,就可以通過gralloc設備來釋放它,並且將它從地址空間中解除映射。

 

Gralloc模塊實現源碼位於:hardware/libhardware/modules/gralloc

├── Android.mk
├── framebuffer.cpp
├── gralloc.cpp
├── gralloc_priv.h
├── gr.h
└── mapper.cpp

 

Android硬件抽象Hardware庫加載過程源碼分析介紹了Android系統中的硬件抽象層模塊的加載過程,並指出每個硬件抽象層模塊都必須定義HAL_MODULE_INFO_SYM符號,並且有自己唯一的ID,Gralloc也不例外,Gralloc模塊ID定義為:

1 #define GRALLOC_HARDWARE_MODULE_ID "gralloc"

 

同時定義了以HAL_MODULE_INFO_SYM為符號的類型為private_module_t的結構體:

hardware\libhardware\modules\gralloc\gralloc.cpp

 1 static struct hw_module_methods_t gralloc_module_methods = {
 2         open: gralloc_device_open
 3 };
 4 struct private_module_t HAL_MODULE_INFO_SYM = {
 5     base: {
 6         common: {
 7             tag: HARDWARE_MODULE_TAG,
 8             version_major: 1,
 9             version_minor: 0,
10             id: GRALLOC_HARDWARE_MODULE_ID,
11             name: "Graphics Memory Allocator Module",
12             author: "The Android Open Source Project",
13             methods: &gralloc_module_methods
14         },
15         registerBuffer: gralloc_register_buffer,
16         unregisterBuffer: gralloc_unregister_buffer,
17         lock: gralloc_lock,
18         unlock: gralloc_unlock,
19     },
20     framebuffer: 0,
21     flags: 0,
22     numBuffers: 0,
23     bufferMask: 0,
24     lock: PTHREAD_MUTEX_INITIALIZER,
25     currentBuffer: 0,
26 };

 通過Android硬件抽象Hardware庫加載過程源碼分析的方法將Gralloc模塊加載到內存中來之后,就可以調用函數dlsym來獲得它所導出的符號HMI,得到private_module_t的首地址后,由於private_module_t的第一個成員變量的類型為gralloc_module_t,因此也是gralloc_module_t的首地址,由於gralloc_module_t的第一個成員變量類型為hw_module_t,因此也是hw_module_t的首地址,因此只要得到這三種類型中其中一種類型變量的地址,就可以相互轉換為其他兩種類型的指針。

 

數據結構定義

在分析Gralloc模塊之前,首先介紹Gralloc模塊定義的一些數據結構。private_module_t用於描述Gralloc模塊下的系統幀緩沖區信息

 1 struct private_module_t {
 2     gralloc_module_t base;
 3     private_handle_t* framebuffer; //指向系統幀緩沖區的句柄
 4     uint32_t flags; //用來標志系統幀緩沖區是否支持雙緩沖
 5     uint32_t numBuffers;//表示系統幀緩沖區包含有多少個圖形緩沖區
 6     uint32_t bufferMask; //記錄系統幀緩沖區中的圖形緩沖區的使用情況
 7     pthread_mutex_t lock; //一個互斥鎖,用來保護結構體private_module_t的並行訪問
 8     buffer_handle_t currentBuffer; //用來描述當前正在被渲染的圖形緩沖區
 9     int pmem_master;
10     void* pmem_master_base;
11     struct fb_var_screeninfo info; //保存設備顯示屏的動態屬性信息
12     struct fb_fix_screeninfo finfo; ////保存設備顯示屏的固定屬性信息
13     float xdpi; //描述設備顯示屏在寬度
14     float ydpi; //描述設備顯示屏在高度
15     float fps; //用來描述顯示屏的刷新頻率
16 };

 

 framebuffer_device_t用來描述系統幀緩沖區設備的信息
 1 typedef struct framebuffer_device_t {  
 2     struct hw_device_t common;  
 3     const uint32_t  flags;//用來記錄系統幀緩沖區的標志  
 4     const uint32_t  width;//用來描述設備顯示屏的寬度  
 5     const uint32_t  height;//用來描述設備顯示屏的高度  
 6     const int       stride;//用來描述設備顯示屏的一行有多少個像素點  
 7     const int       format;//用來描述系統幀緩沖區的像素格式  
 8     const float     xdpi;//用來描述設備顯示屏在寬度上的密度  
 9     const float     ydpi;//用來描述設備顯示屏在高度上的密度  
10     const float     fps;//用來描述設備顯示屏的刷新頻率  
11     const int       minSwapInterval;//用來描述幀緩沖區交換前后兩個圖形緩沖區的最小時間間隔  
12     const int       maxSwapInterval;//用來描述幀緩沖區交換前后兩個圖形緩沖區的最大時間間隔  
13     int reserved[8];//保留  
14     //用來設置幀緩沖區交換前后兩個圖形緩沖區的最小和最大時間間隔  
15     int (*setSwapInterval)(struct framebuffer_device_t* window,int interval);  
16     //用來設置幀緩沖區的更新區域  
17     int (*setUpdateRect)(struct framebuffer_device_t* window,int left, int top, int width, int height);  
18     //用來將圖形緩沖區buffer的內容渲染到幀緩沖區中去  
19     int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);  
20     //用來通知fb設備,圖形緩沖區的組合工作已經完成  
21     int (*compositionComplete)(struct framebuffer_device_t* dev);  
22     void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);  
23     int (*enableScreen)(struct framebuffer_device_t* dev, int enable);  
24     //保留  
25     void* reserved_proc[6];  
26 } framebuffer_device_t

 gralloc_module_t用於描述gralloc模塊信息

 1 typedef struct gralloc_module_t {
 2   struct hw_module_t common;
 3   //映射一塊圖形緩沖區到一個進程的地址空間去
 4   int (*registerBuffer)(struct gralloc_module_t const* module,buffer_handle_t handle);
 5   //取消映射一塊圖形緩沖區到一個進程的地址空間去
 6   int (*unregisterBuffer)(struct gralloc_module_t const* module,buffer_handle_t handle);
 7   //鎖定一個指定的圖形緩沖區
 8     int (*lock)(struct gralloc_module_t const* module,buffer_handle_t handle, int usage,
 9             int l, int t, int w, int h,void** vaddr);
10     //解鎖一個指定的圖形緩沖區
11   int (*unlock)(struct gralloc_module_t const* module,buffer_handle_t handle);
12     int (*perform)(struct gralloc_module_t const* module,int operation, ... );
13     void* reserved_proc[7];
14 } gralloc_module_t;

alloc_device_t用於描述gralloc設備的信息

1 typedef struct alloc_device_t {  
2     struct hw_device_t common;  
3     //用於分配一塊圖形緩沖區  
4     int (*alloc)(struct alloc_device_t* dev,int w, int h, int format, int usage,buffer_handle_t* handle, int* stride);  
5     //用於釋放指定的圖形緩沖區  
6     int (*free)(struct alloc_device_t* dev,buffer_handle_t handle);  
7     void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);  
8     void* reserved_proc[7];  
9 } alloc_device_t;  

 

 

 

 1 typedef struct hw_module_t {  
 2     uint32_t tag;//標簽  
 3   uint16_t version_major;//模塊主設備號  
 4   uint16_t version_minor;//模塊次設備號  
 5     const char *id;//模塊ID  
 6     const char *name;//模塊名稱  
 7     const char *author;//模塊作者  
 8     struct hw_module_methods_t* methods;//模塊操作方法  
 9     void* dso;//保存模塊首地址  
10     uint32_t reserved[32-7];//保留位  
11 } hw_module_t;  

硬件抽象層Gralloc模塊定義了設備fb和設備gpu:

1 #define GRALLOC_HARDWARE_FB0 "fb0"  
2 #define GRALLOC_HARDWARE_GPU0 "gpu0"  

 

 

 

設備gpu用於分配圖形緩沖區,而設備fb用於渲染圖形緩沖區;hw_module_t用於描述硬件抽象層Gralloc模塊,而hw_device_t則用於描述硬件抽象層Gralloc設備,通過硬件抽象層設備可以找到對應的硬件抽象層模塊。在Gralloc模塊中,無論是定義fb設備還是gpu設備,都是用來處理圖形緩沖區,以下是關於緩沖區的數據結構 定義:

 

private_handle_t用來描述一塊緩沖區,Android對緩沖區的定義提供了C和C++兩種方式,C語言編譯器下的定義:

 1 struct private_handle_t {
 2     struct native_handle nativeHandle;
 3     enum {
 4         PRIV_FLAGS_FRAMEBUFFER = 0x00000001
 5     };
 6     int     fd; //指向一個文件描述符,這個文件描述符要么指向幀緩沖區設備,要么指向一塊匿名共享內存
 7     int     magic;
 8     int     flags;//用來描述一個緩沖區的標志,當一個緩沖區的標志值等於PRIV_FLAGS_FRAMEBUFFER的時候,就表示它是在幀緩沖區中分配的。
 9     int     size;//用來描述一個緩沖區的大小
10     int     offset;//用來描述一個緩沖區的偏移地址
11     int     base;//用來描述一個緩沖區的實際地址
12     int     pid;//用來描述一個緩沖區的創建者的PID
13 };

C++編譯器下的定義:

 1 struct private_handle_t : public native_handle {
 2     enum {
 3         PRIV_FLAGS_FRAMEBUFFER = 0x00000001
 4     };
 5     int     fd; //指向一個文件描述符,這個文件描述符要么指向幀緩沖區設備,要么指向一塊匿名共享內存
 6     int     magic;//指向一個魔數,它的值由靜態成員變量sMagic來指定,用來標識一個private_handle_t結構體。
 7     int     flags;//用來描述一個緩沖區的標志,它的值要么等於0,要么等於PRIV_FLAGS_FRAMEBUFFER
 8     int     size;//用來描述一個緩沖區的大小。
 9     int     offset;//用來描述一個緩沖區的偏移地址。
10     int     base;//用來描述一個緩沖區的實際地址,它是通過成員變量offset來計算得到的。
11     int     pid;//用來描述一個緩沖區的創建者的PID。
12     static const int sNumInts = 6; //包含有6個整數
13     static const int sNumFds = 1; //包含有1個文件描述符
14     static const int sMagic = 0x3141592;
15 };

 

 兩種編譯器下的private_handle_t定義都繼承於native_handle,native_handle的定義如下:
1 typedef struct native_handle  
2 {  
3     int version; //設置為結構體native_handle_t的大小,用來標識結構體native_handle_t的版本  
4     int numFds;  //表示結構體native_handle_t所包含的文件描述符的個數,這些文件描述符保存在成員變量data所指向的一塊緩沖區中。  
5     int numInts; //表示結構體native_handle_t所包含的整數值的個數,這些整數保存在成員變量data所指向的一塊緩沖區中。  
6     int data[0]; //指向的一塊緩沖區中  
7 } native_handle_t;  
8 typedef const native_handle_t* buffer_handle_t; 
 

Gralloc模塊的打開過程在Android硬件抽象Hardware庫加載過程源碼分析中詳細分析過了,下面就分析Gralloc模塊中定義了兩種設備的打開過程。

 

 

 

Fb設備打開過程

fb設備的ID值定義為#defineGRALLOC_HARDWARE_FB0"fb0",fb設備使用結構體framebuffer_device_t來描述。結構體framebuffer_device_t是用來描述系統幀緩沖區的信息

 hardware\libhardware\include\hardware\fb.h

1 framebuffer_open(const struct hw_module_t* module,  
2         struct framebuffer_device_t** device) {  
3     return module->methods->open(module,GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);  
4 }  

 

 module指向的是一個用來描述Gralloc模塊的hw_module_t結構體,前面提到,它的成員變量methods所指向的一個hw_module_methods_t結構體的成員函數open指向了Gralloc模塊中的函數gralloc_device_open

 

 

hardware\libhardware\modules\gralloc\gralloc.cpp

gralloc_device_open(const hw_module_t* module, const char* name,  
        hw_device_t** device)  
{  
    int status = -EINVAL;  
    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {  
       ...  
    } else {  
        status = fb_device_open(module, name, device);  
    }  
    return status;  
}  

 

 gralloc_device_open函數即可以打開fb設備,也可以用於打開gpu設備,這里根據設備名來區分打開的設備,對應fb設備,則調用fb_device_open函數來完成設備打開操作。

 

hardware\libhardware\modules\gralloc\framebuffer.cpp

 1 int fb_device_open(hw_module_t const* module, const char* name,
 2         hw_device_t** device)
 3 {
 4     int status = -EINVAL;
 5     //判斷打開的是fb設備
 6     if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
 7         alloc_device_t* gralloc_device;
 8         //打開gpu設備
 9         status = gralloc_open(module, &gralloc_device);
10         if (status < 0)
11             return status;
12         //創建一個fb_context_t對象,用來描述fb設備上下文
13         fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
14         memset(dev, 0, sizeof(*dev));
15         //初始化fb_context_t對象
16         dev->device.common.tag = HARDWARE_DEVICE_TAG;
17         dev->device.common.version = 0;
18         dev->device.common.module = const_cast<hw_module_t*>(module);
19         //注冊fb設備的操作函數
20         dev->device.common.close = fb_close; 
21         dev->device.setSwapInterval = fb_setSwapInterval;
22         dev->device.post            = fb_post;
23         dev->device.setUpdateRect = 0;
24         
25         private_module_t* m = (private_module_t*)module;
26         //將fb映射到當前進程地址空間
27         status = mapFrameBuffer(m);
28         if (status >= 0) {
29             int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
30             int format = (m->info.bits_per_pixel == 32)
31                          ? HAL_PIXEL_FORMAT_RGBX_8888
32                          : HAL_PIXEL_FORMAT_RGB_565;
33             const_cast<uint32_t&>(dev->device.flags) = 0;
34             const_cast<uint32_t&>(dev->device.width) = m->info.xres;
35             const_cast<uint32_t&>(dev->device.height) = m->info.yres;
36             const_cast<int&>(dev->device.stride) = stride;
37             const_cast<int&>(dev->device.format) = format;
38             const_cast<float&>(dev->device.xdpi) = m->xdpi;
39             const_cast<float&>(dev->device.ydpi) = m->ydpi;
40             const_cast<float&>(dev->device.fps) = m->fps;
41             const_cast<int&>(dev->device.minSwapInterval) = 1;
42             const_cast<int&>(dev->device.maxSwapInterval) = 1;
43             *device = &dev->device.common;
44         }
45     }
46     return status;
47 }

這個函數主要是用來創建一個fb_context_t結構體,並且對它的成員變量device進行初始化。結構體fb_context_t的成員變量device的類型為framebuffer_device_t,它是用來描述fb設備的。fb設備主要是用來渲染圖形緩沖區的,這是通過調用它的成員函數post來實現的。函數fb_device_open所打開的fb設備的成員函數post被設置為Gralloc模塊中的函數fb_post。函數mapFrameBuffer除了用來獲得系統幀緩沖區的信息之外,還會將系統幀緩沖區映射到當前進程的地址空間來。line_length用來描述顯示屏一行像素總共所占用的字節數,bits_per_pixel用來描述顯示屏每一個像素所占用的位數,bits_per_pixel的值向右移3位,就可以得到顯示屏每一個像素所占用的字節數。用顯示屏像素總共所占用的字節數line_length除以每一個像素所占用的字節數就可以得到顯示屏一行有多少個像素點,並保存在stride中。

1 stride = line_length / ( bits_per_pixel >> 3)  
1 static int mapFrameBuffer(struct private_module_t* module)
2 {
3     pthread_mutex_lock(&module->lock);
4     int err = mapFrameBufferLocked(module);
5     pthread_mutex_unlock(&module->lock);
6     return err;
7 }

 

 

 調用mapFrameBufferLocked函數執行映射過程,該函數在線程保護下完成。

 

 

  1 int mapFrameBufferLocked(struct private_module_t* module)
  2 {
  3     // already initialized...
  4     if (module->framebuffer) {
  5         return 0;
  6     }    
  7     char const * const device_template[] = {
  8             "/dev/graphics/fb%u",
  9             "/dev/fb%u",
 10             0 };
 11 
 12     int fd = -1;
 13     int i=0;
 14     char name[64];
 15     //檢查是否存在設備文件/dev/graphics/fb0或者/dev/fb0。如果存在的話,那么就調用函數open來打開它,並且將得到的文件描述符保存在變量fd中
 16     while ((fd==-1) && device_template[i]) {
 17         snprintf(name, 64, device_template[i], 0);
 18         fd = open(name, O_RDWR, 0);
 19         i++;
 20     }
 21     if (fd < 0)
 22         return -errno;
 23     //通過IO控制命令FBIOGET_FSCREENINFO來獲得系統幀緩沖區的固定信息,保存在fb_fix_screeninfo結構體finfo中
 24     struct fb_fix_screeninfo finfo;
 25     if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
 26         return -errno;
 27     //通過IO控制命令FBIOGET_VSCREENINFO來獲得系統幀緩沖區的可變信息,保存在fb_var_screeninfo結構體info中
 28     struct fb_var_screeninfo info;
 29     if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
 30         return -errno;
 31     //初始化info
 32     info.reserved[0] = 0;
 33     info.reserved[1] = 0;
 34     info.reserved[2] = 0;
 35     info.xoffset = 0;
 36     info.yoffset = 0;
 37     info.activate = FB_ACTIVATE_NOW;
 38     //fb_var_screeninfo的成員變量xres和yres用來描述顯示屏的可視分辨率,而成員變量xres_virtual和yres_virtual用來描述顯示屏的虛擬分辨率。
 39     //將虛擬分辨率的高度值設置為可視分辨率的高度值的NUM_BUFFERS倍。
 40     info.yres_virtual = info.yres * NUM_BUFFERS; //2
 41     uint32_t flags = PAGE_FLIP;
 42     //設置設備顯示屏的虛擬分辨率
 43     if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
 44         //設置失敗,重新設置顯示屏的虛擬分辨率
 45         info.yres_virtual = info.yres;
 46         flags &= ~PAGE_FLIP;
 47         ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
 48     }
 49     if (info.yres_virtual < info.yres * 2) {
 50         // we need at least 2 for page-flipping
 51         info.yres_virtual = info.yres;
 52         flags &= ~PAGE_FLIP;
 53         ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",info.yres_virtual, info.yres*2);
 54     }
 55     //通過IO控制命令FBIOGET_VSCREENINFO來重新獲得系統幀緩沖區的可變信息
 56     if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
 57         return -errno;
 58     //計算設備顯示屏的刷新頻率
 59     uint64_t  refreshQuotient =
 60     (
 61             uint64_t( info.upper_margin + info.lower_margin + info.yres )* ( info.left_margin  + info.right_margin + info.xres )* info.pixclock
 62     );
 63     //模擬器的info.pixclock=0,因此計算得到的refreshQuotient=0
 64     int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0;
 65     //如果是模擬器,設置刷新頻率為60 Hz
 66     if (refreshRate == 0) {
 67         refreshRate = 60*1000;  // 60 Hz
 68     }
 69     if (int(info.width) <= 0 || int(info.height) <= 0) {
 70         info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
 71         info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
 72     }
 73     //計算顯示屏的密度
 74     float xdpi = (info.xres * 25.4f) / info.width;
 75     float ydpi = (info.yres * 25.4f) / info.height;
 76     float fps  = refreshRate / 1000.0f;
 77     //再次通過IO控制命令FBIOGET_FSCREENINFO來獲得系統幀緩沖區的固定信息
 78     if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
 79         return -errno;
 80     if (finfo.smem_len <= 0)
 81         return -errno;
 82     //得到的系統幀緩沖區的其它信息來初始化參數module所描述的一個private_module_t結構體。
 83     module->flags = flags;
 84     module->info = info;
 85     module->finfo = finfo;
 86     module->xdpi = xdpi;
 87     module->ydpi = ydpi;
 88     module->fps = fps;
 89     int err;
 90     //整個系統幀緩沖區的大小=虛擬分辨率的高度值info.yres_virtual * 每一行所占用的字節數finfo.line_length,並將整個系統幀緩沖區的大小對齊到頁面邊界
 91     size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
 92     //創建一個private_handle_t,用來描述整個系統幀緩沖區的信息,
 93     module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);
 94     //計算整個系統幀緩沖區可以划分為多少個圖形緩沖區來使用
 95     module->numBuffers = info.yres_virtual / info.yres;
 96     //表示系統幀緩沖區中的所有圖形緩沖區都是處於空閑狀態
 97     module->bufferMask = 0;
 98     //以讀寫共享方式將幀緩沖區映射到當前進程地址空間中
 99     void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
100     if (vaddr == MAP_FAILED) {
101         ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
102         return -errno;
103     }
104     //系統幀緩沖區在當前進程的地址空間中的起始地址保存到private_handle_t的域base中
105     module->framebuffer->base = intptr_t(vaddr);
106     //清空大小為fbSize的幀緩沖區
107     memset(vaddr, 0, fbSize);
108     return 0;
109 }

在了解本節內容之前首先需要了解Linux的FrameBuffer驅動,請查看FrameBuffer驅動程序分析.

 

 

Gpu設備打開過程

gralloc設備使用結構體alloc_device_t來描述。結構體alloc_device_t有兩個成員函數alloc和free,分別用來分配和釋放圖形緩沖區,gralloc設備的ID值定義為:
1 #defineGRALLOC_HARDWARE_GPU0"gpu0"  

 

 

 

 

hardware\libhardware\include\hardware\gralloc.h

1 static inline int gralloc_open(const struct hw_module_t* module, 
2         struct alloc_device_t** device) {
3     return module->methods->open(module, 
4             GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
5 }

 

 

 

 

module指向的是一個用來描述Gralloc模塊的hw_module_t結構體,它的成員變量methods所指向的一個hw_module_methods_t結構體的成員函數open指向了Gralloc模塊中的函數gralloc_device_open。前面介紹了函數gralloc_device_open即可以打開fb設備也可用來打開gpu設備,這里傳入的設備名為GRALLOC_HARDWARE_GPU0,表示當前打開的是gpu設備。

 

hardware\libhardware\modules\gralloc\gralloc.cpp

 

 
 1 int gralloc_device_open(const hw_module_t* module, const char* name,
 2         hw_device_t** device)
 3 {
 4     int status = -EINVAL;
 5     if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
 6         gralloc_context_t *dev;
 7         dev = (gralloc_context_t*)malloc(sizeof(*dev));
 8         /* initialize our state here */
 9         memset(dev, 0, sizeof(*dev));
10         /* initialize the procs */
11         dev->device.common.tag = HARDWARE_DEVICE_TAG;
12         dev->device.common.version = 0;
13         dev->device.common.module = const_cast<hw_module_t*>(module);
14         dev->device.common.close = gralloc_close;
15         dev->device.alloc   = gralloc_alloc;
16         dev->device.free    = gralloc_free;
17         *device = &dev->device.common;
18         status = 0;
19     } else {
20         ...
21     }
22     return status;
23 }

 

這個函數主要是用來創建一個gralloc_context_t結構體,並且對它的成員變量device進行初始化。結構體gralloc_context_t的成員變量device的類型為gralloc_device_t,它用來描述一個gralloc設備。前面提到,gralloc設備是用來分配和釋放圖形緩沖區的,這是通過調用它的成員函數alloc和free來實現的。從這里可以看出,函數gralloc_device_open所打開的gralloc設備的成員函數alloc和free分別被設置為Gralloc模塊中的函數gralloc_alloc和gralloc_free。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM