3. fb设备的打开过程
在Gralloc模块中,fb设备的ID值定义为GRALLOC_HARDWARE_FB0。GRALLOC_HARDWARE_FB0是一个宏,定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示:
1. #define GRALLOC_HARDWARE_FB0 "fb0"
fb设备使用结构体framebuffer_device_t 来描述。结构体framebuffer_device_t是用来描述系统帧缓冲区的信息,它定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示:
1. typedef struct framebuffer_device_t {
2. struct hw_device_t common;
3.
4. /* flags describing some attributes of the framebuffer */
5. const uint32_t flags;
6.
7. /* dimensions of the framebuffer in pixels */
8. const uint32_t width;
9. const uint32_t height;
10.
11. /* frambuffer stride in pixels */
12. const int stride;
13.
14. /* framebuffer pixel format */
15. const int format;
16.
17. /* resolution of the framebuffer's display panel in pixel per inch*/
18. const float xdpi;
19. const float ydpi;
20.
21. /* framebuffer's display panel refresh rate in frames per second */
22. const float fps;
23.
24. /* min swap interval supported by this framebuffer */
25. const int minSwapInterval;
26.
27. /* max swap interval supported by this framebuffer */
28. const int maxSwapInterval;
29.
30. int reserved[8];
31.
32. int (*setSwapInterval)(struct framebuffer_device_t* window,
33. int interval);
34.
35. int (*setUpdateRect)(struct framebuffer_device_t* window,
36. int left, int top, int width, int height);
37.
38. int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
39.
40. int (*compositionComplete)(struct framebuffer_device_t* dev);
41.
42. void* reserved_proc[8];
43.
44. } framebuffer_device_t;
成员变量flags用来记录系统帧缓冲区的标志,目前没有使用这成员变量,它的值被设置为0。
成员变量width和height分别用来描述设备显示屏的宽度和高度,它们是以像素为单位的。
成员变量stride用来描述设备显示屏的一行有多少个像素点。
成员变量format用来描述系统帧缓冲区的像素格式,支持的像素格式主要有HAL_PIXEL_FORMAT_RGBX_8888和HAL_PIXEL_FORMAT_RGB_565两种。HAL_PIXEL_FORMAT_RGBX_8888表示一个像素使用32位来描述,R、G和B分别占8位,另外8位未使用。HAL_PIXEL_FORMAT_RGB_565表示一个像素使用16位来描述,R、G和B分别占5、6和5位。
成员变量xdpi和ydpi分别用来描述设备显示屏在宽度和高度上的密度,即每英寸有多少个像素点。
成员变量fps用来描述设备显示屏的刷新频率,它的单位是帧每秒。
成员变量minSwapInterval和maxSwapInterval用来描述帧缓冲区交换前后两个图形缓冲区的最小和最大时间间隔。
成员变量reserved是保留给将来使用的。
成员函数setSwapInterval用来设置帧缓冲区交换前后两个图形缓冲区的最小和最大时间间隔。
成员函数setUpdateRect用来设置帧缓冲区的更新区域。
成员函数post用来将图形缓冲区buffer的内容渲染到帧缓冲区中去,即显示在设备的显示屏中去。
成员函数compositionComplete用来通知fb设备device,图形缓冲区的组合工作已经完成,目前没有使用这个成员函数。
成员变量reserved是一个函数指针数组,它们是保留给将来使用的。
在结构体framebuffer_device_t的一系列成员函数中,post是最重要的一个成员函数,用户空间的应用程序通过调用这个成员函数就可以在设备的显示屏中渲染指定的画面,后面我们将详细这个函数的实现。
Gralloc模块在在文件hardware/libhardware/include/hardware/gralloc.h中定义了一个帮助函数framebuffer_open,用来打开fb设备,如下所示:
1. static inline int framebuffer_open(const struct hw_module_t* module,
2. struct framebuffer_device_t** device) {
3. return module->methods->open(module,
4. struct hw_device_t**)device);
5. }
参数module指向的是一个用来描述Gralloc模块的hw_module_t结构体,前面提到,它的成员变量methods所指向的一个hw_module_methods_t结构体的成员函数open指向了Gralloc模块中的函数gralloc_device_open,这个函数打开fb设备的代码段如下所示:
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. ......
7. else {
8. status = fb_device_open(module, name, device);
9. }
10. return status;
11. }
参数name的值等于GRALLOC_HARDWARE_FB0,因此,函数gralloc_device_open接下来会调用另外一个函数fb_device_open来执行打开fb设备的操作。
函数fb_device_open定义在文件hardware/libhardware/modules/gralloc/framebuffer.cpp中,如下所示:
1. struct fb_context_t {
2. framebuffer_device_t device;
3. };
4.
5. ......
6.
7. int fb_device_open(hw_module_t const* module, const char* name,
8. hw_device_t** device)
9. {
10. int status = -EINVAL;
11. if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
12. alloc_device_t* gralloc_device;
13. status = gralloc_open(module, &gralloc_device);
14. if (status < 0)
15. return status;
16.
17. /* initialize our state here */
18. sizeof(*dev));
19. sizeof(*dev));
20.
21. /* initialize the procs */
22. dev->device.common.tag = HARDWARE_DEVICE_TAG;
23. dev->device.common.version = 0;
24. const_cast<hw_module_t*>(module);
25. dev->device.common.close = fb_close;
26. dev->device.setSwapInterval = fb_setSwapInterval;
27. dev->device.post = fb_post;
28. dev->device.setUpdateRect = 0;
29.
30. private_module_t* m = (private_module_t*)module;
31. status = mapFrameBuffer(m);
32. if (status >= 0) {
33. int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
34. int format = (m->info.bits_per_pixel == 32)
35. ? HAL_PIXEL_FORMAT_RGBX_8888
36. : HAL_PIXEL_FORMAT_RGB_565;
37. #ifdef NO_32BPP
38. format = HAL_PIXEL_FORMAT_RGB_565;
39. #endif
40. const_cast<uint32_t&>(dev->device.flags) = 0;
41. const_cast<uint32_t&>(dev->device.width) = m->info.xres;
42. const_cast<uint32_t&>(dev->device.height) = m->info.yres;
43. const_cast<int&>(dev->device.stride) = stride;
44. const_cast<int&>(dev->device.format) = format;
45. const_cast<float&>(dev->device.xdpi) = m->xdpi;
46. const_cast<float&>(dev->device.ydpi) = m->ydpi;
47. const_cast<float&>(dev->device.fps) = m->fps;
48. const_cast<int&>(dev->device.minSwapInterval) = 1;
49. const_cast<int&>(dev->device.maxSwapInterval) = 1;
50. *device = &dev->device.common;
51. }
52. }
53. return status;
54. }
这个函数主要是用来创建一个fb_context_t结构体,并且对它的成员变量device进行初始化。结构体fb_context_t的成员变量device的类型为framebuffer_device_t,前面提到,它是用来描述fb设备的。fb设备主要是用来渲染图形缓冲区的,这是通过调用它的成员函数post来实现的。从这里可以看出,函数fb_device_open所打开的fb设备的成员函数post被设置为Gralloc模块中的函数fb_post,后面我们再详细分析它的实现。