Gralloc 总结

从字面就可以看出来Gralloc接口是为了显示内存分配与释放 – Graphics Allocation。
它的主要目的有三个:
Ø  为应用分配显示用内存;
Ø  可以把显示内存在不同进程间进行映射;
Ø  同步

通过加载gralloc抽象层(gralloc.xxx.so),可以打开fb设备(/dev/fb0)和gpu设备(/dev/graphic/),
fb设备用于操作framebuffer,gpu设备负责图形缓冲区的分配和释放。
对于SurfaceFlinger服务端的本地窗口FramebufferNativeWindow将分别打开fb设备和gpu设备,
FramebufferNativeWindow通过gpu设备从Framebuffer中分配图形缓冲区,可用来GPU render。
通过fb设备来分配framebuffer,可以显示经SurfaceFlinger混合后的图像。
是在FrameBufferNativeWindow的构造代码中,可以看到打开fb0设备获取Framebuffer Info,然后使用gralloc为该FrameBufferNativeWindow分配两个或者三个Framebuffer,即双缓冲或者三缓冲。
而对于应用程序端的SurfaceTextureClient本地窗口,其需要的图形缓冲区也是由SurfaceFlinger服务端来分配,应用程序进程只需要将服务端分配的图形缓冲区映射到应用程序的虚拟地址空间,图形缓冲区的映射过程也是由Gralloc模块完成。

gpu设备
Gpu打开过程就是创建并初始化一个gralloc_context_t对象,gpu负责图形buffer的分配和释放。
fb设备
Fb设备打开过程就是创建并初始化一个fb_context_t对象,关于屏幕大小、格式、刷新频率等信息都是通过Framebuffer驱动来获取,最后将Framebuffer映射到SurfaceFlinger进程地址空间,并将映射后的首地址保持到private_module_t的framebuffer->base变量中。

可以认为Gralloc module中有两个设备gpu_alloc_device和fb_device,前者用于分配GPU0使用的内存和FB内存,GPU0内存管理使用ION allocator;后者用于获取分配Framebuffer Info并操作fb。
注意,在Android系统中,在系统帧缓冲区中分配的图形缓冲区是在SurfaceFlinger服务中使用的,
而在内存中分配的图形缓冲区既可以在SurfaceFlinger服务中使用,也可以在其它的应用程序中使用。
当其它的应用程序需要使用图形缓冲区的时候,它们就会请求SurfaceFlinger服务为它们分配。
因此,对于其它的应用程序来说,它们只需要将SurfaceFlinger服务返回来的图形缓冲区映射到自己的进程地址空间来使用就可以了。

下面是分配内存最核心的函数:

  1. static int gralloc_alloc(alloc_device_t* dev,  
  2.        int w, int h, int format, int usage,  
  3.        buffer_handle_t* pHandle, int* pStride)  
  4.   
  5.    if (!pHandle || !pStride)  
  6.        return -EINVAL;  
  7.    size_t size, stride;  
  8.    int align = 4;  
  9.    int bpp = 0;  
  10.    switch (format) {  
  11.        case HAL_PIXEL_FORMAT_RGBA_8888:  
  12.        case HAL_PIXEL_FORMAT_RGBX_8888:  
  13.        case HAL_PIXEL_FORMAT_BGRA_8888:  
  14.            bpp = 4;  
  15.            break;  
  16.        case HAL_PIXEL_FORMAT_RGB_888:  
  17.            bpp = 3;  
  18.            break;  
  19.        case HAL_PIXEL_FORMAT_RGB_565:  
  20.        case HAL_PIXEL_FORMAT_RAW_SENSOR:  
  21.            bpp = 2;  
  22.            break;  
  23.        default:  
  24.            return -EINVAL;  
  25.    }  
  26.    size_t bpr = (w*bpp + (align-1)) & ~(align-1);  
  27.    size = bpr * h;  
  28.    stride = bpr / bpp;  
  29.    int err;  
  30.    if (usage & GRALLOC_USAGE_HW_FB) {  
  31.        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); //申请图形缓冲区,用来render  
  32.    } else {  
  33.        err = gralloc_alloc_buffer(dev, size, usage, pHandle);   //申请帧缓冲区,用来显示  
  34.    }  
  35.    if (err < 0) {  
  36.        return err;  
  37.    }  
  38.    *pStride = stride;  
  39.    return 0;  

 在申请gralloc的时候,下面的enum表示要申请的buffer的用途
  1. {  
  2.     /* buffer is never read in software */  
  3.     GRALLOC_USAGE_SW_READ_NEVER         = 0x00000000,  
  4.     /* buffer is rarely read in software */  
  5.     GRALLOC_USAGE_SW_READ_RARELY        = 0x00000002,  
  6.     /* buffer is often read in software */  
  7.     GRALLOC_USAGE_SW_READ_OFTEN         = 0x00000003,  
  8.     /* mask for the software read values */  
  9.     GRALLOC_USAGE_SW_READ_MASK          = 0x0000000F,  
  10.       
  11.     /* buffer is never written in software */  
  12.     GRALLOC_USAGE_SW_WRITE_NEVER        = 0x00000000,  
  13.     /* buffer is rarely written in software */  
  14.     GRALLOC_USAGE_SW_WRITE_RARELY       = 0x00000020,  
  15.     /* buffer is often written in software */  
  16.     GRALLOC_USAGE_SW_WRITE_OFTEN        = 0x00000030,  
  17.     /* mask for the software write values */  
  18.     GRALLOC_USAGE_SW_WRITE_MASK         = 0x000000F0,  
  19.     /* buffer will be used as an OpenGL ES texture */  
  20.     GRALLOC_USAGE_HW_TEXTURE            = 0x00000100,  
  21.     /* buffer will be used as an OpenGL ES render target */  
  22.     GRALLOC_USAGE_HW_RENDER             = 0x00000200,  
  23.     /* buffer will be used by the 2D hardware blitter */  
  24.     GRALLOC_USAGE_HW_2D                 = 0x00000400,  
  25.     /* buffer will be used by the HWComposer HAL module */  
  26.     GRALLOC_USAGE_HW_COMPOSER           = 0x00000800,  
  27.     /* buffer will be used with the framebuffer device */  
  28.     GRALLOC_USAGE_HW_FB                 = 0x00001000,  
  29.     /* buffer will be used with the HW video encoder */  
  30.     GRALLOC_USAGE_HW_VIDEO_ENCODER      = 0x00010000,  
  31.     /* buffer will be written by the HW camera pipeline */  
  32.     GRALLOC_USAGE_HW_CAMERA_WRITE       = 0x00020000,  
  33.     /* buffer will be read by the HW camera pipeline */  
  34.     GRALLOC_USAGE_HW_CAMERA_READ        = 0x00040000,  
  35.     /* buffer will be used as part of zero-shutter-lag queue */  
  36.     GRALLOC_USAGE_HW_CAMERA_ZSL         = 0x00060000,  
  37.     /* mask for the camera access values */  
  38.     GRALLOC_USAGE_HW_CAMERA_MASK        = 0x00060000,  
  39.     /* mask for the software usage bit-mask */  
  40.     GRALLOC_USAGE_HW_MASK               = 0x00071F00,  
  41.     /* buffer will be used as a RenderScript Allocation */  
  42.     GRALLOC_USAGE_RENDERSCRIPT          = 0x00100000,  
  43.     GRALLOC_USAGE_HW_FIMC1        = 0x01000000,  
  44.     GRALLOC_USAGE_HW_ION          = 0x02000000,  
  45.     GRALLOC_USAGE_YUV_ADDR        = 0x04000000,  
  46.     /* SEC Private usage , for Overlay path at HWC */  
  47.     GRALLOC_USAGE_HWC_HWOVERLAY     = 0x20000000,  
  48.     /* buffer should be displayed full-screen on an external display when 
  49.      * possible 
  50.      */  
  51.     GRALLOC_USAGE_EXTERNAL_DISP         = 0x00002000,  
  52.     /* Must have a hardware-protected path to external display sink for 
  53.      * this buffer.  If a hardware-protected path is not available, then 
  54.      * either don't composite only this buffer (preferred) to the 
  55.      * external sink, or (less desirable) do not route the entire 
  56.      * composition to the external sink. 
  57.      */  
  58.     GRALLOC_USAGE_PROTECTED             = 0x00004000,  
  59.     /* implementation-specific private usage flags */  
  60.     GRALLOC_USAGE_PRIVATE_0             = 0x10000000,  
  61.     GRALLOC_USAGE_PRIVATE_1             = 0x20000000,  
  62.     GRALLOC_USAGE_PRIVATE_2             = 0x40000000,  
  63.     GRALLOC_USAGE_PRIVATE_3             = 0x80000000,  
  64.     GRALLOC_USAGE_PRIVATE_MASK          = 0xF0000000,  
  65. }  

上面参数usage用来描述要分配的图形缓冲区的用途。
如果是用来在系统帧缓冲区中渲染的,GRALLOC_USAGE_HW_FB,那么就必须要系统帧缓冲区中分配,即framebuffer中。
否则的话,就在内存中分配。目前大多数采用android的ION机制分配共享的graphicbuffer。如果GPU为MALI,还可以采用MALI的UMP机制。
或者注意,在内存中分配的图形缓冲区,最终是需要渲染到系统帧缓冲区去的,以便可以将它所描述的图形显示出来。
 
申请好的图形缓冲区或者framebuffer,都是采用了bufferqueue的方式来管理的。 
网上很多大牛写的很好。我就不赘述了。
 
 
 
 最后大体讲一下显示:

 下面是framebuffer显示使用的函数

  1. static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)  
  2. {  
  3.     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)  
  4.     {  
  5.         m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST,   
  6.                 0, 0, m->info.xres, m->info.yres, NULL);  
  7.         const size_t offset = hnd->base - m->framebuffer->base;  
  8.         int interrupt;  
  9.         m->info.activate = FB_ACTIVATE_VBL;  
  10.         m->info.yoffset = offset / m->finfo.line_length;  
  11. #ifdef STANDARD_LINUX_SCREEN  
  12. #define FBIO_WAITFORVSYNC       _IOW('F', 0x20, __u32)  
  13. #define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int)  
  14.         if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) == -1)   
  15.         {  
  16.             AERR( "FBIOPAN_DISPLAY failed for fd: %d", m->framebuffer->fd );  
  17.             m->base.unlock(&m->base, buffer);   
  18.             return 0;  
  19.         }  
  20.         {  
  21.             // enable VSYNC  
  22.             interrupt = 1;  
  23.             if(ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0)   
  24.             {  
  25.                 AERR( "S3CFB_SET_VSYNC_INT enable failed for fd: %d", m->framebuffer->fd );  
  26.                 return 0;  
  27.             }  
  28.             // wait for VSYNC  
  29. #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE  
  30.             gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT);  
  31. #endif  
  32.             int crtc = 0;  
  33.             if(ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0)  
  34.             {  
  35.                 AERR( "FBIO_WAITFORVSYNC failed for fd: %d", m->framebuffer->fd );  
  36. #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE  
  37.                 gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);  
  38. #endif  
  39.                 return 0;  
  40.             }  
  41. #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE  
  42.             gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);  
  43. #endif  
  44.             // disable VSYNC  
  45.             interrupt = 0;  
  46.             if(ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0)   
  47.             {  
  48.                 AERR( "S3CFB_SET_VSYNC_INT disable failed for fd: %d", m->framebuffer->fd );  
  49.                 return 0;  
  50.             }  
  51.         }  
  52. #else   
  53.         /*Standard Android way*/  
  54. #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE  
  55.         gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT);  
  56. #endif  
  57.         if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1)   
  58.         {  
  59.             AERR( "FBIOPUT_VSCREENINFO failed for fd: %d", m->framebuffer->fd );  
  60. #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE  
  61.             gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);  
  62. #endif  
  63.             m->base.unlock(&m->base, buffer);   
  64.             return -errno;  
  65.         }  
  66. #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE  
  67.         gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT);  
  68. #endif  
  69. #endif  
  70.         m->currentBuffer = buffer;  
  71.     }   
  72.     return 0;  
  73. }  
  1. 注意:  

 这个函数只有在离线合成的方式下,由openGL调用eglSwapbuffer,才会被调用到。

参考:

http://blog.csdn.NET/wan8180192/article/details/50269405

在线合成的方式下,会调用HWC->set 函数,即exynos4_set--->exynos4_post_fimd ---> window_pan_display最终显示

参考:

http://blog.csdn.Net/wan8180192/article/details/50719123


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值