Gralloc.default.so 的实现

本文探讨了Android系统中默认Gralloc模块的实现细节,主要关注其位于hardware/libhardware/modules/gralloc/的代码实现,包括Android.mk、framebuffer.cpp、gralloc.cpp、gralloc_priv.h和mapper.cpp等关键文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


默认的Gralloc模块实现的代码路径如下:
hardware/libhardware/modules/gralloc/*

  1. $ ls hardware/libhardware/modules/gralloc/
  2. Android.mk framebuffer.cpp gralloc.cpp gralloc_priv.h gr.h mapper.cpp
1. gralloc.c, 实现了 gralloc_module_t 模块和 alloc_device_t 设备
    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)) {    //打开alloc_device_t设备
            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;   //alloc_device_t的alloc接口
            dev->device.free = gralloc_free;     //alloc_device_t的free接口
            *device = &dev->device.common;
            status = 0;
        } else {
            status = fb_device_open(module, name, device);   //打开framebuffer_device_t设备
        }
        return status;
    }

private_module_t 扩展了 gralloc_module_t 结构:
    struct private_module_t HAL_MODULE_INFO_SYM= {
        base:{                   //base 就是gralloc_module_t
            common:{
                tag: HARDWARE_MODULE_TAG,
                version_major: 1,
                version_minor: 0,
                id: GRALLOC_HARDWARE_MODULE_ID,
                name:"Graphics Memory Allocator Module",
                author:"The Android Open Source Project",
                methods:&gralloc_module_methods
            },
            registerBuffer: gralloc_register_buffer,    //都是gralloc_module_t的方法,这些方法都在mapper.cpp中实现。
            unregisterBuffer: gralloc_unregister_buffer,
            lock: gralloc_lock,
            unlock: gralloc_unlock,
        },
        framebuffer: 0,
        flags: 0,
        numBuffers: 0,
        bufferMask: 0,
        lock: PTHREAD_MUTEX_INITIALIZER,
        currentBuffer: 0,
    };

private_module_t 原型定义在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;
    };

2. framebuffer.cpp 用于实现 framebuffer_device_t 设备:
打开framebuffer_device_t设备函数 fb_device_open(),该函数初始化了一个framebuffer_device_t 设备。

    int fb_device_open(hw_module_tconst* module, constchar* name,
            hw_device_t** device)
    {
        int status= -EINVAL;
        if (!strcmp(name, GRALLOC_HARDWARE_FB0)){
            alloc_device_t* gralloc_device;
            status = gralloc_open(module,&gralloc_device);
            if (status < 0)
                return status;
            /* initialize our state here */
            fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
            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= fb_close;      
            dev->device.setSwapInterval= fb_setSwapInterval;    //赋值各个函数指针
            dev->device.post= fb_post;
            dev->device.setUpdateRect= 0;
            private_module_t* m= (private_module_t*)module;
            status = mapFrameBuffer(m);            //映射framebuffer设备
            if (status >= 0){                     //填充framebuffeer_device_t 设备的各项内容
                int stride= m->finfo.line_length/ (m->info.bits_per_pixel>> 3);
                int format= (m->info.bits_per_pixel== 32)
                             ? HAL_PIXEL_FORMAT_RGBX_8888
                             : HAL_PIXEL_FORMAT_RGB_565;
    #ifdef NO_32BPP
                format = HAL_PIXEL_FORMAT_RGB_565;
    #endif
                const_cast<uint32_t&>(dev->device.flags)= 0;
                const_cast<uint32_t&>(dev->device.width)= m->info.xres;
                const_cast<uint32_t&>(dev->device.height)= m->info.yres;
                const_cast<int&>(dev->device.stride)= stride;
                const_cast<int&>(dev->device.format)= format;
                const_cast<float&>(dev->device.xdpi)= m->xdpi;
                const_cast<float&>(dev->device.ydpi)= m->ydpi;
                const_cast<float&>(dev->device.fps)= m->fps;
                const_cast<int&>(dev->device.minSwapInterval)= 1;
                const_cast<int&>(dev->device.maxSwapInterval)= 1;
                *device= &dev->device.common;
            }
        }
        return status;
    }

其主体实现函数是 mapFrameBuffer(m)
    staticint mapFrameBuffer(struct private_module_t*module)
    {
        pthread_mutex_lock(&module->lock);
        int err = mapFrameBufferLocked(module);
        pthread_mutex_unlock(&module->lock);
        return err;
    }

    int mapFrameBufferLocked(struct private_module_t*module)
    {
        // already initialized...
        if (module->framebuffer){
            return 0;
        }
        char const* const device_template[]= {      //定义framebuffer设备
                "/dev/graphics/fb%u",
                "/dev/fb%u",
                0 };
        int fd =-1;
        int i=0;
        char name[64];
        while ((fd==-1)&& device_template[i]){
            snprintf(name, 64, device_template[i], 0);
            fd = open(name, O_RDWR, 0);
            i++;
        }
        if (fd< 0)
            return -errno;
        struct fb_fix_screeninfo finfo;
        if (ioctl(fd, FBIOGET_FSCREENINFO,&finfo) == -1)   //固定屏幕信息
            return -errno;
        struct fb_var_screeninfo info;
        if (ioctl(fd, FBIOGET_VSCREENINFO,&info) == -1)    //变化屏幕信息
            return -errno;
        info.reserved[0]= 0;
        info.reserved[1]= 0;
        info.reserved[2]= 0;
        info.xoffset = 0;
        info.yoffset = 0;
        info.activate = FB_ACTIVATE_NOW;
    #if defined(NO_32BPP)
        /*
         * Explicitly request 5/6/5
         */
        info.bits_per_pixel = 16;        //RGB565的颜色空间
        info.red.offset= 11;
        info.red.length= 5;
        info.green.offset= 5;
        info.green.length= 6;
        info.blue.offset= 0;
        info.blue.length= 5;
        info.transp.offset= 0;
        info.transp.length= 0;
    #endif
        /*
         * Request NUM_BUFFERS screens (at lest 2 for page flipping)
         */
        info.yres_virtual = info.yres * NUM_BUFFERS;      //NUM_BUFFERS =2
        uint32_t flags = PAGE_FLIP;
        if (ioctl(fd, FBIOPUT_VSCREENINFO,&info) == -1){      //重新设置变化屏幕信息
            info.yres_virtual = info.yres;
            flags &=~PAGE_FLIP;
            LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
        }
        if (info.yres_virtual< info.yres* 2) {        //虚拟缓冲区尺寸小于实际缓冲区2倍的情况
            // we need at least 2 for page-flipping
            info.yres_virtual = info.yres;
            flags &=~PAGE_FLIP;
            LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
                    info.yres_virtual, info.yres*2);
        }
        if (ioctl(fd, FBIOGET_VSCREENINFO,&info) == -1)    //重新获取变化屏幕信息
            return -errno;
        uint64_t refreshQuotient =
        (
                uint64_t( info.upper_margin+ info.lower_margin+ info.yres)
                * ( info.left_margin + info.right_margin + info.xres )
                * info.pixclock
        );
        /* Beware, info.pixclock might be 0 under emulation, so avoid a
         * division-by-0 here (SIGFPE on ARM) */
        int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU/ refreshQuotient): 0;
        if (refreshRate== 0){
            // bleagh, bad info from the driver
            refreshRate = 60*1000;// 60 Hz            //刷新率为60Hz
        }
        if (int(info.width)<= 0 || int(info.height)<= 0){
            // the driver doesn't return that information
            // default to 160 dpi
            info.width = ((info.xres* 25.4f)/160.0f+ 0.5f);    //默认dpi为160,大屏可以设为250
            info.height = ((info.yres* 25.4f)/160.0f+ 0.5f);    //dpi ---单位面积的像素数目
        }
        float xdpi = (info.xres* 25.4f)/ info.width;            //获得X,Y的dpi
        float ydpi = (info.yres* 25.4f)/ info.height;
        float fps = refreshRate / 1000.0f;
        LOGI( "using (fd=%d)\n"
                "id = %s\n"
                "xres = %d px\n"
                "yres = %d px\n"
                "xres_virtual = %d px\n"
                "yres_virtual = %d px\n"
                "bpp = %d\n"                                
                "r = %2u:%u\n"
                "g = %2u:%u\n"
                "b = %2u:%u\n",
                fd,
                finfo.id,
                info.xres,
                info.yres,
                info.xres_virtual,
                info.yres_virtual,
                info.bits_per_pixel,                    //bpp---像素深度
                info.red.offset, info.red.length,
                info.green.offset, info.green.length,
                info.blue.offset, info.blue.length
        );
        LOGI( "width = %d mm (%f dpi)\n"
                "height = %d mm (%f dpi)\n"
                "refresh rate = %.2f Hz\n",
                info.width, xdpi,
                info.height, ydpi,
                fps
        );
        if (ioctl(fd, FBIOGET_FSCREENINFO,&finfo) == -1)
            return -errno;
        if (finfo.smem_len<= 0)
            return -errno;
        module->flags= flags;        //设置模块内容
        module->info= info;
        module->finfo= finfo;
        module->xdpi= xdpi;
        module->ydpi= ydpi;
        module->fps= fps;
        /*
         * map the framebuffer
         */
        int err;
        size_t fbSize = roundUpToPageSize(finfo.line_length* info.yres_virtual);
        module->framebuffer= new private_handle_t(dup(fd), fbSize, 0);
        module->numBuffers= info.yres_virtual/ info.yres;       //数值一般为2
        module->bufferMask= 0;
        //进行从设备的内存映射
        void* vaddr= mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if (vaddr== MAP_FAILED){
            LOGE("Error mapping the framebuffer (%s)", strerror(errno));
            return -errno;
        }
        module->framebuffer->base= intptr_t(vaddr);
        memset(vaddr, 0, fbSize);
        return 0;
    }

fb_device_open()基本上是对framebuffer驱动程序的标准操作。
使用RGB565的颜色空间,至少需要虚拟缓冲区是实际缓冲区的2倍(主要是指y方向2倍)。
刷新率和DPI(单位面积的像素数目)是android系统的一个可选参数。


3. fb_post()是framebuffer_device_t 设备实现的一个重点,表示将某个缓冲区Buffer显示在屏幕上。

    static int fb_post(struct framebuffer_device_t* dev, buffer_handle_tbuffer)
    {
        if (private_handle_t::validate(buffer)< 0)
            return -EINVAL;
        
        fb_context_t* ctx = (fb_context_t*)dev;  
        
        private_handle_t const* hnd= reinterpret_cast<private_handle_tconst*>(buffer);
        private_module_t* m = reinterpret_cast<private_module_t*>(
                dev->common.module);
        
        if (hnd->flags& private_handle_t::PRIV_FLAGS_FRAMEBUFFER){
            const size_t offset = hnd->base- m->framebuffer->base;
            m->info.activate= FB_ACTIVATE_VBL;
            m->info.yoffset= offset / m->finfo.line_length;    //设置变化屏幕信息
            if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info)== -1) {
                LOGE("FBIOPUT_VSCREENINFO failed");
                m->base.unlock(&m->base,buffer);        //解锁缓冲区
                return -errno;
            }
            m->currentBuffer= buffer;
            
        } else{
            // If we can't do the page_flip, just copy the buffer to the front
            // FIXME: use copybit HAL instead of memcpy
            
            void* fb_vaddr;
            void* buffer_vaddr;
            //对内存区域进行操作,锁定-->复制-->解锁
            m->base.lock(&m->base, m->framebuffer,
                    GRALLOC_USAGE_SW_WRITE_RARELY,
                    0, 0, m->info.xres, m->info.yres,
                    &fb_vaddr);
            
            m->base.lock(&m->base,buffer,
                    GRALLOC_USAGE_SW_READ_RARELY,
                    0, 0, m->info.xres, m->info.yres,
                    &buffer_vaddr);
            
            memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length* m->info.yres);
            
            m->base.unlock(&m->base,buffer);
            m->base.unlock(&m->base, m->framebuffer);
        }
        
        return 0;
    }

屏幕上实际上需要显示系统通过硬件DMA读取的显示缓冲区数据,而在程序中需要写显示缓冲区的数据。
为了避免这两个步骤同时进行,Gralloc处理的方式就是,锁定一个,写内容,解锁它。在锁定期间显示缓冲区不能被硬件DMA获取。


4. alloc_device_t 部分:
gralloc.cpp 中实现 alloc_device_t 设备的几个部分:alloc, free, close 等函数指针。

    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){          //颜色空间的处理,不同颜色空间决定每像素字节(bpp)。
            case HAL_PIXEL_FORMAT_RGBA_8888:      //每像素4字节
            case HAL_PIXEL_FORMAT_RGBX_8888:
            case HAL_PIXEL_FORMAT_BGRA_8888:
                bpp = 4;
                break;
            case HAL_PIXEL_FORMAT_RGB_888:       //每像素3字节
                bpp = 3;
                break;
            case HAL_PIXEL_FORMAT_RGB_565:
            case HAL_PIXEL_FORMAT_RGBA_5551:
            case HAL_PIXEL_FORMAT_RGBA_4444:
                bpp = 2;                          //每像素2字节
                break;
            default:
                return -EINVAL;
        }
        size_t bpr = (w*bpp +(align-1))& ~(align-1);    //根据行情况进行对齐处理
        size = bpr* h;
        stride = bpr / bpp;          //没行的像素个数,即跨度stride
        
        int err;
        if (usage& GRALLOC_USAGE_HW_FB){
            err = gralloc_alloc_framebuffer(dev,size, usage, pHandle);   //调用了framebuffer.cpp中的mapFrameBuffer().
        } else{
            err = gralloc_alloc_buffer(dev,size, usage, pHandle);  //调用了ashmem_create_region(),使用ashmem(匿名共享内存)分配了名称为"gralloc-buffer"的内存,这是一个纯软件的实现
        }
        
        if (err< 0) {
            return err;
        }
        
        *pStride = stride;
        return 0;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值