android gralloc 流程分析

Android 中 lcd 是一个帧缓冲设备,驱动程序通过处理器的 lcd 控制器将物理内存的一段区域设置为显存,如果向这段内存区域写入数据就会马上在 lcd 上显示出来。Android 在 HAL 中提供了gralloc 模块,封装了用户层对帧缓冲设备的所有操作接口,并通过 SurfaceFlinger 服务向应用提供显示支持。在启动过程中系统会加载 gralloc 模块,然后打开帧缓冲设备,获取设备的各种参数并完成 gralloc 模块的初始化。当应用程序需要把内容显示到 lcd 上时,需要通过 gralloc 模块申请一块图形缓冲区,然后将这块图形缓冲区映射到自己的地址空间并写入内容即可。当应用程序不再需要这块图形缓冲区时需要通过 gralloc 模块释放掉,然后解除对缓冲区的映射。

1、基础数据结构

gralloc 模块通过 struct private_module_t 来描述,该结构定义如下:

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;           /* 保护结构体private_module_t的并行访问 */
    buffer_handle_t currentBuffer;  /* 描述当前正在被渲染的图形缓冲区 */
    int pmem_master;                /* pmem设备节点的描述符 */
    void* pmem_master_base;         /* pmem的起始虚拟地址 */

    struct fb_var_screeninfo info;  /* lcd的可变参数 */
    struct fb_fix_screeninfo finfo; /* lcd的固定参数 */
    float xdpi;                     /* x方向上每英寸的像素数量 */
    float ydpi;                     /* y方向上每英寸的像素数量 */
    float fps;                      /* lcd的刷新率 */
    
    int orientation;                /* 显示方向 */

    enum {
        PRIV_USAGE_LOCKED_FOR_POST = 0x80000000  /* flag to indicate we'll post this buffer */
    };
};
该结构的成员记录了 gralloc 模块的各种参数,主要为模块自己使用,应用程序操作的 图形缓冲区的数据结构是 struct private_handle_t,定义如下:
#ifdef __cplusplus
struct private_handle_t : public native_handle {
#else
struct private_handle_t {
    struct native_handle nativeHandle;  /* 用来描述一个本地句柄值 */
#endif
    
    enum {
        PRIV_FLAGS_FRAMEBUFFER    = 0x00000001,
        PRIV_FLAGS_USES_PMEM      = 0x00000002,
        PRIV_FLAGS_USES_MMEM      = 0x00000004,
        PRIV_FLAGS_NEEDS_FLUSH    = 0x00000008,
    };

    enum {
        LOCK_STATE_WRITE     =   1<<31,
        LOCK_STATE_MAPPED    =   1<<30,
        LOCK_STATE_READ_MASK =   0x3FFFFFFF
    };

    /* 指向一个文件描述符,这个文件描述符要么指向帧缓冲区设备,要么指向一块匿名共享内存
     * 取决于private_handle_t描述的图形缓冲区是在帧缓冲区分配的,还是在内存中分配的 */
    int     fd;
    /* 指向一个魔数,它的值由静态成员变量sMagic来指定,用来标识一个private_handle_t结构体 */
    int     magic;
    /* 用来描述一个图形缓冲区的标志,它的值要么等于0,要么等于PRIV_FLAGS_FRAMEBUFFER
     * 当一个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候,就表示它是在帧缓冲区中分配的 */
    int     flags;
    int     size;   /* 描述一个图形缓冲区的大小 */
    int     offset; /* 描述一个图形缓冲区的偏移地址 */

    int     phys;   /* 图形缓冲区或帧缓冲的起始物理地址 */
    int     base;   /* 图形缓冲区或帧缓冲的起始虚拟地址 */
    int     lockState;
    int     writeOwner;
    int     pid;    /* 描述一个图形缓冲区的创建者的PID */

#ifdef __cplusplus
    static const int sNumInts = 9;  /* 有9个整数变量 */
    static const int sNumFds = 1;   /* 有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),
        phys(0), base(0), lockState(0), writeOwner(0), pid(getpid())
    {
        version = sizeof(native_handle);
        numInts = sNumInts;
        numFds = sNumFds;
    }
    ~private_handle_t() {
        magic = 0;
    }

    bool usesPhysicallyContiguousMemory() {
        return (flags & PRIV_FLAGS_USES_PMEM) != 0;
    }

    /* 用来验证一个native_handle_t指针是否指向了一个private_handle_t结构体 */
    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;
    }

    static private_handle_t* dynamicCast(const native_handle* in) {
        if (validate(in) == 0) {
            return (private_handle_t*) in;
        }
        return NULL;
    }
#endif
};

图形缓冲区的操作接口由结构 struct gralloc_module_t 定义:

typedef struct gralloc_module_t {
    struct hw_module_t comm
  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值