1. 在Android Eclair 及其之后的版本中,显示系统增加了一个名为Gralloc的硬件模块。
Gralloc的含义为, Graphics Alloc(图形分配),这个模块位于libui和显示设备的驱动程序之间。
Gralloc模块被放在/system/lib/hw/下,下面是omap3的一个gralloc:
$ ls system/lib/hw -l
总用量 144
-rwxrwxr-x 1 xxha xxha 18204 2012-03-14 15:57 alsa.adlink.so
-rwxrwxr-x 1 xxha xxha 9840 2012-03-13 15:56 gps.goldfish.so
-rwxrwxr-x 1 xxha xxha 5596 2012-03-13 15:56 gps.omap4.so
-rwxrwxr-x 1 xxha xxha 10112 2012-03-13 15:56 gralloc.default.so
lrwxrwxrwx 1 xxha xxha 28 2012-03-19 11:11 gralloc.omap3.so -> gralloc.omap3.so.1.1.17.4403
-rw-rw-r-- 1 xxha xxha 14380 2012-03-19 11:11 gralloc.omap3.so.1.1.17.4403
-rwxrwxr-x 1 xxha xxha 9756 2012-03-13 15:56 lights.omap3.so
-rwxrwxr-x 1 xxha xxha 34860 2012-03-13 15:56 overlay.omap3.so
-rwxrwxr-x 1 xxha xxha 14416 2012-03-13 15:56 sensors.adlink.so
-rwxrwxr-x 1 xxha xxha 10044 2012-03-13 15:56 sensors.goldfish.so
2. gralloc相当与显示系统的硬件抽象层,以硬件模块的形式存在,这时一个Android标准的硬件模块。
其头文件位于:hardware/libhardware/include/hardware/gralloc.h
a. Gralloc.h 首先定义模块和自设备的名称:
/**
* The id of this module
*/
#define GRALLOC_HARDWARE_MODULE_ID "gralloc" //这个硬件模块的名称
/**
* Name of the graphics device to open
*/
#define GRALLOC_HARDWARE_FB0 "fb0"
#ifdef OMAP_ENHANCEMENT
#define GRALLOC_HARDWARE_FB1 "fb1"
#endif
#define GRALLOC_HARDWARE_GPU0 "gpu0"
b. gralloc_module_t 是模块的核心:
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct gralloc_module_t {
struct hw_module_t common;
/*
* (*registerBuffer)() must be called before a buffer_handle_t that has not
* been created with (*alloc_device_t::alloc)() can be used.
*
* This is intended to be used with buffer_handle_t's that have been
* received in this process through IPC.
*
* This function checks that the handle is indeed a valid one and prepares
* it for use with (*lock)() and (*unlock)().
*
* It is not necessary to call (*registerBuffer)() on a handle created
* with (*alloc_device_t::alloc)().
*
* returns an error if this buffer_handle_t is not valid.
*/
int (*registerBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
/*
* (*unregisterBuffer)() is called once this handle is no longer needed in
* this process. After this call, it is an error to call (*lock)(),
* (*unlock)(), or (*registerBuffer)().
*
* This function doesn't close or free the handle itself; this is done
* by other means, usually through libcutils's native_handle_close() and
* native_handle_free().
*
* It is an error to call (*unregisterBuffer)() on a buffer that wasn't
* explicitly registered first.
*/
int (*unregisterBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
/*
* The (*lock)() method is called before a buffer is accessed for the
* specified usage. This call may block, for instance if the h/w needs
* to finish rendering or if CPU caches need to be synchronized.
*
* The caller promises to modify only pixels in the area specified
* by (l,t,w,h).
*
* The content of the buffer outside of the specified area is NOT modified
* by this call.
*
* If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address
* of the buffer in virtual memory.
*
* THREADING CONSIDERATIONS:
*
* It is legal for several different threads to lock a buffer from
* read access, none of the threads are blocked.
*
* However, locking a buffer simultaneously for write or read/write is
* undefined, but:
* - shall not result in termination of the process
* - shall not block the caller
* It is acceptable to return an error or to leave the buffer's content
* into an indeterminate state.
*
* If the buffer was created with a usage mask incompatible with the
* requested usage flags here, -EINVAL is returned.
*
*/
int (*lock)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
/*
* The (*unlock)() method must be called after all changes to the buffer
* are completed.
*/
int (*unlock)(struct gralloc_module_t const* module,
buffer_handle_t handle);
/* reserved for future use */
int (*perform)(struct gralloc_module_t const* module,
int operation, ... );
/* reserved for future use */
void* reserved_proc[7];
} gralloc_module_t;
c. gralloc 和 framebuffer 两种设备的打开和关闭接口如下:open/close
/** convenience API for opening and closing a supported device */
static inline int gralloc_open(const struct hw_module_t* module,
struct alloc_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}
static inline int gralloc_close(struct alloc_device_t* device) {
return device->common.close(&device->common);
}
static inline int framebuffer_open(const struct hw_module_t* module,
struct framebuffer_device_t** device) {
return module->methods->open(module,
GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
}
#ifdef OMAP_ENHANCEMENT
static inline int framebuffer_open_by_name(const struct hw_module_t* module,
struct framebuffer_device_t** device, const char *fb_name) {
return module->methods->open(module,
fb_name, (struct hw_device_t**)device);
}
#endif
static inline int framebuffer_close(struct framebuffer_device_t* device) {
return device->common.close(&device->common);
}
这4个函数是Gralloc模块特定的API。
d. GRALLOC_HARDWARE_GPU0对应的设备为alloc_device_t:
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct alloc_device_t {
struct hw_device_t common;
/*
* (*alloc)() Allocates a buffer in graphic memory with the requested
* parameters and returns a buffer_handle_t and the stride in pixels to
* allow the implementation to satisfy hardware constraints on the width
* of a pixmap (eg: it may have to be multiple of 9 pixels).
* The CALLER TAKES OWNERSHIP of the buffer_handle_t.
*
* Returns 0 on success or -errno on error.
*/
int (*alloc)(struct alloc_device_t* dev, //用于分配一个显示内存。
int w, int h, int format, int usage,
buffer_handle_t* handle, int* stride);
/*
* (*free)() Frees a previously allocated buffer.
* Behavior is undefined if the buffer is still mapped in any process,
* but shall not result in termination of the program or security breaches
* (allowing a process to get access to another process' buffers).
* THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes
* invalid after the call.
*
* Returns 0 on success or -errno on error.
*/
int (*free)(struct alloc_device_t* dev,
buffer_handle_t handle);
} alloc_device_t;
e. GRALLOC_HARDWARE_FB0对应的设备为framebuffer_device_t:
typedef struct framebuffer_device_t {
struct hw_device_t common;
/* flags describing some attributes of the framebuffer */
const uint32_t flags;
/* dimensions of the framebuffer in pixels */
const uint32_t width;
const uint32_t height;
/* frambuffer stride in pixels */
const int stride;
/* framebuffer pixel format */
const int format;
/* resolution of the framebuffer's display panel in pixel per inch*/
const float xdpi;
const float ydpi;
/* framebuffer's display panel refresh rate in frames per second */
const float fps;
/* min swap interval supported by this framebuffer */
const int minSwapInterval;
/* max swap interval supported by this framebuffer */
const int maxSwapInterval;
int reserved[8];
/*
* requests a specific swap-interval (same definition than EGL)
*
* Returns 0 on success or -errno on error.
*/
int (*setSwapInterval)(struct framebuffer_device_t* window, //用于交换显示区域
int interval);
/*
* This hook is OPTIONAL.
*
* It is non NULL If the framebuffer driver supports "update-on-demand"
* and the given rectangle is the area of the screen that gets
* updated during (*post)().
*
* This is useful on devices that are able to DMA only a portion of
* the screen to the display panel, upon demand -- as opposed to
* constantly refreshing the panel 60 times per second, for instance.
*
* Only the area defined by this rectangle is guaranteed to be valid, that
* is, the driver is not allowed to post anything outside of this
* rectangle.
*
* The rectangle evaluated during (*post)() and specifies which area
* of the buffer passed in (*post)() shall to be posted.
*
* return -EINVAL if width or height <=0, or if left or top < 0
*/
int (*setUpdateRect)(struct framebuffer_device_t* window, //用于更新指定区域
int left, int top, int width, int height);
/*
* Post <buffer> to the display (display it on the screen)
* The buffer must have been allocated with the
* GRALLOC_USAGE_HW_FB usage flag.
* buffer must be the same width and height as the display and must NOT
* be locked.
*
* The buffer is shown during the next VSYNC.
*
* If the same buffer is posted again (possibly after some other buffer),
* post() will block until the the first post is completed.
*
* Internally, post() is expected to lock the buffer so that a
* subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or
* USAGE_*_WRITE will block until it is safe; that is typically once this
* buffer is shown and another buffer has been posted.
*
* Returns 0 on success or -errno on error.
*/
int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer); //用于发送某个Buffer到屏幕上
/*
* The (*compositionComplete)() method must be called after the
* compositor has finished issuing GL commands for client buffers.
*/
int (*compositionComplete)(struct framebuffer_device_t* dev);
void* reserved_proc[8];
} framebuffer_device_t;
3. 在上层,libui库中的FramebufferNativeWindow.cpp 是Gralloc的主要调用者。
Gralloc 与上层的关系,见下篇。