我是靠谱客的博主 自觉小伙,最近开发中收集的这篇文章主要介绍GraphicBuffer和Gralloc模块,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Gralloc硬件抽象层:申请释放渲染图像缓冲,驱动屏幕的显示

  • open函数,打开设备,通过name区分了不同的设备
   int gralloc_device_open(const hw_module_t* module, const char* name,
        hw_device_t** device){
         if(name=="gpu0"){
           device=new alloc_device_t();
         }else if(name=="fb0"){
           device=new framebuffer_device_t();
         }
   }

  •  支持2中类型的设备
     (1.) alloc_device_t   申请释放图像缓冲,保存了一堆函数指针,主要是
          申请内存
          alloc 

          释放内存
          free

         注意:
          alloc指向gralloc_alloc函数 ,支持在fb和共享内存中申请graphicbuffer
           if (usage & GRALLOC_USAGE_HW_FB) {
            //用fb中映射的显存
                err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);

            } else {
           //创建共享内存
                err = gralloc_alloc_buffer(dev, size, usage, pHandle);

            }


   (2.)framebuffer_device_t 渲染图像缓存,通过(/dev/fbx 驱动)显示到屏幕上 ,保存了一堆函数指针,主要是
          丢一个buffer,等vsync信号来了再渲染出来,这很重要的函数,调用post把输入buffer刷新到屏幕上(调用了fb驱动),屏幕的显示都是直接或间接调用了post
          post

          设置刷新间隔
          setswapinterval

          加载fb成功后,通过mmap把fb映射到进程的地址空间中,首地址保存到framebuffer->base中,   framebuffer->base就是显存了,
          会根据屏幕大小分成几段, 加载fb驱动后就会把显存整个映射到进程的内存中。



  • GraphicBuffer包装了底层的buffer
      graphicbuffer的初始化依赖 GraphicBufferAllocator
      
     //调用initsize后这个buffer就有效了
status_t GraphicBuffer :: initSize ( uint32_t w , uint32_t h , PixelFormat format ,
        uint32_t reqUsage )
{
    GraphicBufferAllocator & allocator = GraphicBufferAllocator :: get ();
    // handle 保存的底层的句柄
    status_t err = allocator . alloc ( w , h , format , reqUsage , & handle , & stride );
    if ( err == NO_ERROR ) {
        this -> width   = w ;
        this -> height = h ;
        this -> format = format ;
        this -> usage   = reqUsage ;
    }
    return err ;
}

继承关系
  GraphicBuffer
    : public ANativeObjectBase < ANativeWindowBuffer , GraphicBuffer , RefBase >,
      public Flattenable < GraphicBuffer >

Flattenable:序列化的接口,为了跨进程传递这个GraphicBuffer,这个不分析,就是吧一堆变量,句柄按格式从内存中读写
     ANativeObjectBase < ANativeWindowBuffer , GraphicBuffer , RefBase >:就是一个 ANativeWindowBuffer ,主要的就是保存了硬件抽象层中生成的句柄,handle是主要的东西

     //获取buffer的一堆属性 
    uint32_t getWidth () const            { return width ; }
    uint32_t getHeight () const           { return height ; }
    uint32_t getStride () const           { return stride ; }
    uint32_t getUsage () const            { return usage ; }
    PixelFormat getPixelFormat () const   { return format ; }
    Rect getBounds () const               { return Rect ( width , height ); }

      //lockbuffer返回可操作的内存地址,这就调用 GraphicBufferMapper的代码了
    status_t lock ( uint32_t usage , void ** vaddr );
    status_t unlock ();

  • GraphicBufferAllocator: 单例  (通过硬件抽象层进行图像缓存的申请,释放)
     GraphicBufferAllocator类初始化的时候加载硬件驱动层打开allocdev,以后就是通过allocdev进行图像缓存的申请释放
         allocdev 通过 HAL_MODULE_INFO_SYM的common.open打开的

    输入需要的buffer  宽度,高度,格式,用来干嘛(是否从fb中分配 ),返回的 buffer_handle_t就是硬件驱动层生成的图像缓存句柄
    status_t alloc ( uint32_t w , uint32_t h , PixelFormat format , int usage ,
            buffer_handle_t * handle , int32_t * stride );

     1.  a lloc ( uint32_t w , uint32_t h , PixelFormat format , int usage , buffer_handle_t * handle , int32_t * stride );
            2.mAllocDev -> alloc ( mAllocDev , w , h , format , usage , handle , stride );     (alloc指向 gralloc_alloc 函数指针 )               
              gralloc_alloc ( alloc_device_t * dev , int w , int h , int format , int usage , buffer_handle_t * pHandle , int * pStride )  //硬件抽象层的
                3. gralloc_alloc_framebuffer/ gralloc_alloc_buffer        

 
    //根据使用情况打开不同的buffer
    gralloc_alloc(){
         if ( usage & GRALLOC_USAGE_HW_FB ) {
            err = gralloc_alloc_framebuffer ( dev , size , usage , pHandle );
        } else {
             err = gralloc_alloc_buffer ( dev , size , usage , pHandle );
       }
    }


    分配显存
   gralloc_alloc_framebuffer         
       gralloc_alloc_framebuffer_locked

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 );

    if ( m -> framebuffer == NULL ) {
        // 第一次就进行fb的映射,以后就用这个了
        mapFrameBufferLocked ( m );
    }

    if ( numBuffers == 1) {
        // 如果显存只有1屏的大小则用共享内存吧
        int newUsage = ( usage & ~ GRALLOC_USAGE_HW_FB ) | GRALLOC_USAGE_HW_2D ;
        return gralloc_alloc_buffer ( dev , bufferSize , newUsage , pHandle );
    }


    private_handle_t * hnd = new private_handle_t
        // 看一下显存的有没有空闲的后台缓存
    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;
}
 
//打开fb驱动获取到显存的n多属性,初始化一下
int mapFrameBufferLocked ( struct private_module_t * module )
{
    if ( module -> framebuffer ) {
        return 0;
    }
       
    char const * const device_template [] = {
            "/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); //这个怎么写死的0呢,其他屏幕怎么处理啊,还没明白,明白后再说了
        fd = open ( name , O_RDWR , 0);
        i ++;
    }

    ....获取属性,初始化,然后映射到内存中
}

共享内存分配
static int gralloc_alloc_buffer ( alloc_device_t * dev ,
        size_t size , int usage , buffer_handle_t * pHandle )
{
    //对齐到页大小
    size = roundUpToPageSize ( size );
    //创建共享内存  
    fd = ashmem_create_region ( "gralloc-buffer" , size );
    //映射内存,内部会mmap()
    mapBuffer ( module , hnd );
}


    释放图像缓存句柄
    status_t free ( buffer_handle_t handle );


  • GraphicBufferMapper: 单例 (申请完图像缓冲后,Mapper进行图像缓存的映射(map映射到不同的进程内存中),lock)
         GraphicBufferMapper 类初始化的时候加载硬件驱动层打开  mAllocMod,这个是 gralloc_module_t,而GraphicBufferAllocator是通过allocMod打开了allocDev

     // buffer_handle_t是GraphicBuffer中的,GraphicBufferAllocator申请的,registerbuffer以后映射内存保存到hanle中
status_t GraphicBufferMapper :: registerBuffer ( buffer_handle_t handle )
{
     err = mAllocMod -> registerBuffer ( mAllocMod , handle );
}

看一下调用流程:
硬件抽象层导出的标准接口定义
HAL_MODULE_INFO_SYM = {
    base : {
        common : {
            tag : HARDWARE_MODULE_TAG ,
            ....          
        },
        registerBuffer : gralloc_register_buffer ,
        unregisterBuffer : gralloc_unregister_buffer ,
        lock : gralloc_lock ,
        unlock : gralloc_unlock ,
}

1.mAllocMod -> registerBuffer( gralloc_module_t, buffer_handle_t
      2. gralloc_register_buffer( gralloc_module_t const * module , buffer_handle_t handle)//验证一下有效性,然后map
                     3. gralloc_map ( gralloc_module_t const * module , buffer_handle_t handle , void ** vaddr )
              4.mmap()


gralloc_map(){
  private_handle_t * hnd = ( private_handle_t *) handle ;
    if (!( hnd -> flags & private_handle_t :: PRIV_FLAGS_FRAMEBUFFER )) {//如果不是famebuffer的则mmap,因为共享framebuffer开始打开的时候就已经映射过了
        size_t size = hnd -> size ;
        void * mappedAddress = mmap (0, size ,
                PROT_READ | PROT_WRITE , MAP_SHARED , hnd -> fd , 0);
        hnd -> base = intptr_t ( mappedAddress ) + hnd -> offset ;
    }
    * vaddr = ( void *) hnd -> base ;
}


//下面几个都差不多,都是调用硬件抽象层的函数
status_t GraphicBufferMapper :: unregisterBuffer ( buffer_handle_t handle )
{
    err = mAllocMod -> unregisterBuffer ( mAllocMod , handle );
}

status_t GraphicBufferMapper :: lock ( buffer_handle_t handle ,
        int usage , const Rect & bounds , void ** vaddr )
{
    mAllocMod -> lock
}

status_t GraphicBufferMapper :: unlock ( buffer_handle_t handle )
{
    mAllocMod ->un lock
}

最后

以上就是自觉小伙为你收集整理的GraphicBuffer和Gralloc模块的全部内容,希望文章能够帮你解决GraphicBuffer和Gralloc模块所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部