gralloc模块-摘抄自老罗

用户空间的应用程序在使用帧缓冲区之间,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容。最后,用户空间中的应用程序就通过fb设备来将前面已经准备好了的图形缓冲区渲染到帧缓冲区中去,即将图形缓冲区的内容绘制到显示屏中去。相应地,当用户空间中的应用程序不再需要使用一块图形缓冲区的时候,就可以通过gralloc设备来释放它,并且将它从地址空间中解除映射。

gralloc设备是用来分配和释放图形缓冲区的

Gralloc模块负责注册图形缓冲区,

fb设备主要是用来渲染图形缓冲区的

1;帧缓冲区

结构体private_module_t定义在文件hardware/libhardware/modules/gralloc/gralloc_priv.h中,它主要是用来描述帧缓冲区的属性,如下所示:

struct private_module_t {  
    gralloc_module_t base;  
  
    private_handle_t* framebuffer;  
    uint32_t flags;  
    uint32_t numBuffers;  
    uint32_t bufferMask;  
    pthread_mutex_t lock;  
    buffer_handle_t currentBuffer;  
    int pmem_master;  
    void* pmem_master_base;  
  
    struct fb_var_screeninfo info;  
    struct fb_fix_screeninfo finfo;  
    float xdpi;  
    float ydpi;  
    float fps;  
};  
复制代码
  • 成员变量framebuffer的类型为private_handle_t,它是一个指向系统帧缓冲区的句柄,后面我们再分析结构体private_handle_t的定义。
  • 成员变量flags用来标志系统帧缓冲区是否支持双缓冲。如果支持的话,那么它的PAGE_FLIP位就等于1,否则的话,就等于0。
  • 成员变量numBuffers表示系统帧缓冲区包含有多少个图形缓冲区。一个帧缓冲区包含有多少个图形缓冲区是与它的可视分辨率以及虚拟分辨率的大小有关的。例如,如果一个帧缓冲区的可视分辨率为800 x 600,而虚拟分辨率为1600 x 600,那么这个帧缓冲区就可以包含有两个图形缓冲区。
  • 成员变量bufferMask用来记录系统帧缓冲区中的图形缓冲区的使用情况。例如,假设系统帧缓冲区有两个图形缓冲区,这时候成员变量bufferMask就有四种取值,分别是二进制的00、01、10和11,其中,00分别表示两个图缓冲区都是空闲的,01表示第1个图形缓冲区已经分配出去,而第2个图形缓冲区是空闲的,10表示第1个图形缓冲区是空闲的,而第2个图形缓冲区已经分配出去,11表示两个图缓冲区都已经分配出去。
  • 成员变量lock是一个互斥锁,用来保护结构体private_module_t的并行访问。
  • 成员变量currentBuffer的类型为buffer_handle_t,用来描述当前正在被渲染的图形缓冲区,后面我们再分析它的定义。
  • 成员变量pmem_master和pmem_master_base目前没有使用。
  • 成员变量info和finfo的类型分别为fb_var_screeninfo和fb_fix_screeninfo,它们用来保存设备显示屏的属性信息,其中,成员变量info保存的属性信息是可以动态设置的,而成员变量finfo保存的属性信息是只读的。这两个成员变量的值可以通过IO控制命令FBIOGET_VSCREENINFO和FBIOGET_FSCREENINFO来从帧缓冲区驱动模块中获得。
  • 成员变量xdpi和ydpi分别用来描述设备显示屏在宽度和高度上的密度,即每英寸有多少个像素点。
  • 成员变量fps用来描述显示屏的刷新频率,它的单位的fps,即每秒帧数。

2:图形缓冲区

结构体private_handle_t用来描述一块图形缓冲区,这块图形缓冲区可能是在帧缓冲区中分配的,也可能是在内存中分配的,视具体情况而定,它定义在文件hardware/libhardware/modules/gralloc/gralloc_priv.h文件中,如下所示:

#ifdef __cplusplus  
struct private_handle_t : public native_handle {  
#else  
struct private_handle_t {  
    struct native_handle nativeHandle;  
#endif  
  
    enum {  
        PRIV_FLAGS_FRAMEBUFFER = 0x00000001  
    };  
  
    // file-descriptors  
    int     fd;  
    // ints  
    int     magic;  
    int     flags;  
    int     size;  
    int     offset;  
  
    // FIXME: the attributes below should be out-of-line  
    int     base;  
    int     pid;  
  
#ifdef __cplusplus  
    static const int sNumInts = 6;  
    static const int sNumFds = 1;  
    static const int sMagic = 0x3141592;  
  
    private_handle_t(int fd, int size, int flags) :  
        fd(fd), magic(sMagic), flags(flags), size(size), offset(0),  
        base(0), pid(getpid())  
    {  
        version = sizeof(native_handle);  
        numInts = sNumInts;  
        numFds = sNumFds;  
    }  
    ~private_handle_t() {  
        magic = 0;  
    }  
  
    static int validate(const native_handle* h) {  
        const private_handle_t* hnd = (const private_handle_t*)h;  
        if (!h || h->version != sizeof(native_handle) ||  
                h->numInts != sNumInts || h->numFds != sNumFds ||  
                hnd->magic != sMagic)  
        {  
            LOGE("invalid gralloc handle (at %p)", h);  
            return -EINVAL;  
        }  
        return 0;  
    }  
#endif  
}; 
复制代码

为了方便描述,我们假设我们是在C++环境中编译文件gralloc_priv.h,即编译环境定义有宏__cplusplus。这样,结构体private_handle_t就是从结构体native_handle_t继承下来的,它包含有1个文件描述符以及6个整数,以及三个静态成员变量。

  • 成员变量fd指向一个文件描述符,这个文件描述符要么指向帧缓冲区设备,要么指向一块匿名共享内存,取决于它的宿主结构体private_handle_t描述的一个图形缓冲区是在帧缓冲区分配的,还是在内存中分配的。
  • 成员变量magic指向一个魔数,它的值由静态成员变量sMagic来指定,用来标识一个private_handle_t结构体。
  • 成员变量flags用来描述一个图形缓冲区的标志,它的值要么等于0,要么等于PRIV_FLAGS_FRAMEBUFFER。当一个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候,就表示它是在帧缓冲区中分配的。
  • 成员变量size用来描述一个图形缓冲区的大小。
  • 成员变量offset用来描述一个图形缓冲区的偏移地址。例如,当一个图形缓冲区是在一块内存中分块的时候,假设这块内存的地址为start,那么这个图形缓冲区的起始地址就为start + offset。
  • 成员变量base用来描述一个图形缓冲区的实际地址,它是通过成员变量offset来计算得到的。例如,上面计算得到的start + offset的值就保存在成员变量base中。
  • 成员变量pid用来描述一个图形缓冲区的创建者的PID。例如,如果一个图形缓冲区是在ID值为1000的进程中创建的,那么用来描述这个图形缓冲区的private_handle_t结构体的成员变量pid的值就等于1000。

结构体private_handle_t的静态成员变量sMagic前面已经描述过了,另外两个静态成员变量sNumInts和sNumFds的值分别等于1和6,表示结构体private_handle_t包含有1个文件描述符和6个整数,它们是用来初始化结构体private_handle_t的父类native_handle_t的成员变量numInts和numFds的,如结构体private_handle_t的构造函数所示。从这里就可以看出,结构体private_handle_t的父类native_handle_t的成员变量data所指向的缓冲区就是由结构体private_handle_t的成员变量fds、magic、flags、size、offset、base和pid所占用的连续内存块来组成的,一共包含有7个整数。

结构体private_handle_t还定义了一个静态成员函数validate,用来验证一个native_handle_t指针是否指向了一个private_handle_t结构体。

至此,Gralloc模块的加载过程以及相关的数据结构体就介绍到这里,接下来我们分别分析定义在Gralloc模块中的gralloc和fb设备的打开过程。

3. gralloc设备的打开过程

在Gralloc模块中,gralloc设备的ID值定义为GRALLOC_HARDWARE_GPU0。GRALLOC_HARDWARE_GPU0是一个宏,定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示:

#define GRALLOC_HARDWARE_GPU0 "gpu0"  
复制代码

gralloc设备使用结构体alloc_device_t 来描述。结构体alloc_device_t有两个成员函数alloc和free,分别用来分配和释放图形缓冲区。

结构体alloc_device_t 也是定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示:

typedef struct alloc_device_t {  
    struct hw_device_t common;  
  
    int (*alloc)(struct alloc_device_t* dev,  
            int w, int h, int format, int usage,  
            buffer_handle_t* handle, int* stride);  
  
    int (*free)(struct alloc_device_t* dev,  
            buffer_handle_t handle);  
  
} alloc_device_t;  
复制代码

Gralloc模块在在文件hardware/libhardware/include/hardware/gralloc.h中定义了一个帮助函数gralloc_open,用来打开gralloc设备,如下所示:

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);  
}  
复制代码

参数module指向的是一个用来描述Gralloc模块的hw_module_t结构体,它的成员变量methods所指向的一个hw_module_methods_t结构体的成员函数open指向了Gralloc模块中的函数gralloc_device_open。

函数gralloc_device_open定义在文件hardware/libhardware/modules/gralloc/gralloc.cpp文件中,如下所示:

struct gralloc_context_t {  
    alloc_device_t  device;  
    /* our private data here */  
};  
  
......  
  
int gralloc_device_open(const hw_module_t* module, const char* name,  
        hw_device_t** device)  
{  
    int status = -EINVAL;  
    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;  
    }   
    ......  
  
    return status;  
复制代码

这个函数主要是用来创建一个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,后面我们再详细分析它们的实现。

从gralloc设备的两个函数alloc和free可见gralloc设备是用来分配和释放图形缓冲区的

4. fb设备的打开过程

在Gralloc模块中,fb设备的ID值定义为GRALLOC_HARDWARE_FB0。GRALLOC_HARDWARE_FB0是一个宏,定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示:

#define GRALLOC_HARDWARE_FB0 "fb0"  
复制代码

fb设备使用结构体framebuffer_device_t 来描述。结构体framebuffer_device_t是用来描述系统帧缓冲区的信息,它定义在文件hardware/libhardware/include/hardware/gralloc.h中, 如下所示:

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];  
  
    int (*setSwapInterval)(struct framebuffer_device_t* window,  
            int interval);  
  
    int (*setUpdateRect)(struct framebuffer_device_t* window,  
            int left, int top, int width, int height);  
  
    int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);  
  
    int (*compositionComplete)(struct framebuffer_device_t* dev);  
  
    void* reserved_proc[8];  
  
} 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是最重要的一个成员函数,用户空间的应用程序通过调用这个成员函数就可以在设备的显示屏中渲染指定的画面/

5. 分配图形缓冲区

前面提到,用户空间的应用程序用到的图形缓冲区是由Gralloc模块中的函数gralloc_alloc来分配的,这个函数实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中,如下所示:

static int gralloc_alloc(alloc_device_t* dev,  
        int w, int h, int format, int usage,  
        buffer_handle_t* pHandle, int* pStride)  
{  
    if (!pHandle || !pStride)  
        return -EINVAL;  
  
    size_t size, stride;  
  
    int align = 4;  
    int bpp = 0;  
    switch (format) {  
        case HAL_PIXEL_FORMAT_RGBA_8888:  
        case HAL_PIXEL_FORMAT_RGBX_8888:  
        case HAL_PIXEL_FORMAT_BGRA_8888:  
            bpp = 4;  
            break;  
        case HAL_PIXEL_FORMAT_RGB_888:  
            bpp = 3;  
            break;  
        case HAL_PIXEL_FORMAT_RGB_565:  
        case HAL_PIXEL_FORMAT_RGBA_5551:  
        case HAL_PIXEL_FORMAT_RGBA_4444:  
            bpp = 2;  
            break;  
        default:  
            return -EINVAL;  
    }  
    size_t bpr = (w*bpp + (align-1)) & ~(align-1);  
    size = bpr * h;  
    stride = bpr / bpp;  
  
    int err;  
    if (usage & GRALLOC_USAGE_HW_FB) {  
        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);  
    } else {  
        err = gralloc_alloc_buffer(dev, size, usage, pHandle);  
    }  
  
    if (err < 0) {  
        return err;  
    }  
  
    *pStride = stride;  
    return 0;  
}  
复制代码

函数gralloc_alloc_framebuffer用来在系统帧缓冲区中分配图形缓冲区,而函数gralloc_alloc_buffer用来在内存在分配图形缓冲区,

5.1函数gralloc_alloc_framebuffer实现在文件

hardware/libhardware/modules/gralloc/gralloc.cpp中,如下所示:

static int gralloc_alloc_framebuffer(alloc_device_t* dev,  
        size_t size, int usage, buffer_handle_t* pHandle)  
{  
    private_module_t* m = reinterpret_cast<private_module_t*>(  
            dev->common.module);  
    pthread_mutex_lock(&m->lock);  
    int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);  
    pthread_mutex_unlock(&m->lock);  
    return err;  
}  
复制代码

这个函数调用了另外一个函数gralloc_alloc_framebuffer_locked来分配图形缓冲区。

函数gralloc_alloc_framebuffer_locked也是实现在文件hardware/libhardware/modules/gralloc/gralloc.cpp中,如下所示:

static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,  
        size_t size, int usage, buffer_handle_t* pHandle)  
{  
    private_module_t* m = reinterpret_cast<private_module_t*>(  
            dev->common.module);  
  
    // allocate the framebuffer  
    if (m->framebuffer == NULL) {  
        // initialize the framebuffer, the framebuffer is mapped once  
        // and forever.  
        int err = mapFrameBufferLocked(m);  
        if (err < 0) {  
            return err;  
        }  
    }  
  
    const uint32_t bufferMask = m->bufferMask;  
    const uint32_t numBuffers = m->numBuffers;  
    const size_t bufferSize = m->finfo.line_length * m->info.yres;  
    if (numBuffers == 1) {  
        // If we have only one buffer, we never use page-flipping. Instead,  
        // we return a regular buffer which will be memcpy'ed to the main  
        // screen when post is called.  
        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;  
        return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);  
    }  
  
    if (bufferMask >= ((1LU<<numBuffers)-1)) {  
        // We ran out of buffers.  
        return -ENOMEM;  
    }  
  
    // create a "fake" handles for it  
    intptr_t vaddr = intptr_t(m->framebuffer->base);  
    private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,  
            private_handle_t::PRIV_FLAGS_FRAMEBUFFER);  
  
    // find a free slot  
    for (uint32_t i=0 ; i<numBuffers ; i++) {  
        if ((bufferMask & (1LU<<i)) == 0) {  
            m->bufferMask |= (1LU<<i);  
            break;  
        }  
        vaddr += bufferSize;  
    }  
  
    hnd->base = vaddr;  
    hnd->offset = vaddr - intptr_t(m->framebuffer->base);  
    *pHandle = hnd;  
  
    return 0;  
} 
复制代码

在系统帧缓冲区分配图形缓冲区之前,首先要对系统帧缓冲区进行过初始化,即这里的变量m所指向的一个private_module_t结构体的成员变量framebuffer的值不能等于NULL。如果等于NULL的话,那么就必须要调用另外一个函数mapFrameBufferLocked来初始化系统帧缓冲区。初始化系统帧缓冲区的过程可以参考前面第3部分的内容。

变量bufferMask用来描述系统帧缓冲区的使用情况,而变量numBuffers用来描述系统帧缓冲区可以划分为多少个图形缓冲区来使用,另外一个变量bufferSize用来描述设备显示屏一屏内容所占用的内存的大小。

如果系统帧缓冲区只有一个图形缓冲区大小,即变量numBuffers的值等于1,那么这个图形缓冲区就始终用作系统主图形缓冲区来使用。在这种情况下,我们就不能够在系统帧缓冲区中分配图形缓冲区来给用户空间的应用程序使用,因此,这时候就会转向内存中来分配图形缓冲区,即调用函数gralloc_alloc_buffer来分配图形缓冲区。注意,这时候分配的图形缓冲区的大小为一屏内容的大小,即bufferSize。

如果bufferMask的值大于等于((1LU<<numBuffers)-1)的值,那么就说明系统帧缓冲区中的图形缓冲区全部都分配出去了,这时候分配图形缓冲区就失败了。例如,假设图形缓冲区的个数为2,那么((1LU<<numBuffers)-1)的值就等于3,即二制制0x11。如果这时候bufferMask的值也等于0x11,那么就表示第一个和第二个图形缓冲区都已经分配出去了。因此,这时候就不能再在系统帧缓冲区中分配图形缓冲区。

假设此时系统帧缓冲区中尚有空闲的图形缓冲区的,接下来函数就会创建一个private_handle_t结构体hnd来描述这个即将要分配出去的图形缓冲区。注意,这个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER,即表示这是一块在系统帧缓冲区中分配的图形缓冲区。

帧缓冲区分配方式图形缓冲区如下

接下来的for循环从低位到高位检查变量bufferMask的值,并且找到第一个值等于0的位,这样就可以知道在系统帧缓冲区中,第几个图形缓冲区的是空闲的。注意,变量vadrr的值开始的时候指向系统帧缓冲区的基地址,在下面的for循环中,每循环一次它的值都会增加bufferSize。从这里就可以看出,每次从系统帧缓冲区中分配出去的图形缓冲区的大小都是刚好等于显示屏一屏内容大小的。

最后分配出去的图形缓冲区的开始地址就保存在前面所创建的private_handle_t结构体hnd的成员变量base中,这样,用户空间的应用程序就可以直接将要渲染的图形内容拷贝到这个地址上去,这就相当于是直接将图形渲染到系统帧缓冲区中去。

在将private_handle_t结构体hnd返回给调用者之前,还需要设置它的成员变量offset,以便可以知道它所描述的图形缓冲区的起始地址相对于系统帧缓冲区的基地址的偏移量。

5.2函数gralloc_alloc_buffer也是实现在文件

hardware/libhardware/modules/gralloc/gralloc.cpp中,如下所示:

static int gralloc_alloc_buffer(alloc_device_t* dev,  
        size_t size, int usage, buffer_handle_t* pHandle)  
{  
    int err = 0;  
    int fd = -1;  
  
    size = roundUpToPageSize(size);  
  
    fd = ashmem_create_region("gralloc-buffer", size);  
    if (fd < 0) {  
        LOGE("couldn't create ashmem (%s)", strerror(-errno));  
        err = -errno;  
    }  
  
    if (err == 0) {  
        private_handle_t* hnd = new private_handle_t(fd, size, 0);  
        gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(  
                dev->common.module);  
        err = mapBuffer(module, hnd);  
        if (err == 0) {  
            *pHandle = hnd;  
        }  
    }  
  
    LOGE_IF(err, "gralloc failed err=%s", strerror(-err));  
  
    return err;  
}  
复制代码

这个函数的实现很简单,它首先调用函数ashmem_create_region来创建一块匿名共享内存,接着再在这块匿名共享内存上分配一个图形缓冲区。注意,这个图形缓冲区也是使用一个private_handle_t结构体来描述的,不过这个图形缓冲区的标志值等于0,以区别于在系统帧缓冲区中分配的图形缓冲区。匿名共享内存的相关知识,可以参考前面Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划一文,以及Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析这篇文章。

从匿名共享内存中分配的图形缓冲区还需要映射到进程的地址空间来,然后才可以使用,这是通过调用函数mapBuffer来实现的。

函数mapBuffer实现在文件hardware/libhardware/modules/gralloc/mapper.cpp中,如下所示:

int mapBuffer(gralloc_module_t const* module,  
        private_handle_t* hnd)  
{  
    void* vaddr;  
    return gralloc_map(module, hnd, &vaddr);  
}  
复制代码

它通过调用另外一个函数gralloc_map来将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间来。后面在分析图形缓冲区的注册过程时,我们再分析函数gralloc_map的实现。

注意,在Android系统中,在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用的,而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用,也可以在其它的应用程序中使用。当其它的应用程序需要使用图形缓冲区的时候,它们就会请求SurfaceFlinger服务为它们分配,因此,对于其它的应用程序来说,它们只需要将SurfaceFlinger服务返回来的图形缓冲区映射到自己的进程地址空间来使用就可以了,这就是后面我们所要分析的图形缓冲区的注册过程。

至此,图形缓冲区的分配过程就分析完成了,接下来我们继续分析图形缓冲区的释放过程。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享