Android4.0之显示部分HAL

http://blog.csdn.net/tankai19880619/article/details/17379455

一、原理分析

  Android中显示屏设备被抽象成一个帧缓冲区;Linux内核创建的"/dev/graphics/fb0"设备、就是用来描述系统中的一个帧缓冲区(也就是一个显示屏),Android系统grallocHAL模块封装了对帧缓冲区的所有访问操作。

  grallocHAL模块包含两个设备alloc和fb。

  Android应用程序通过SurfaceFlinger服务操作这两个设备,完成显示;首先通过gralloc设备申请一个图形缓冲区、并将该图形缓冲区映射到应用程序的地址空间,然后通过fb设备将前边已经绘制好的图形缓冲区渲染到帧缓冲区上去、完成显示。

  总结:

1.grallocHAL模块中alloc设备使用结构体alloc_device_t来描述;完成对图形缓冲区的管理:

2.grallocHAL模块中fb设备使用结构体framebuffer_device_t来描述;完成对Linux内核帧缓冲区的管理。

成员函数setSwapInterval用来设置帧缓冲区交换前后两个图形缓冲区的最小和最大时间间隔;

成员函数setUpdateRect用来设置帧缓冲区的更新区域;

成员函数post用来将图形缓冲区buffer的内容渲染到帧缓冲区中去,即显示在设备的显示屏中去;

成员函数compositionComplete用来通知fb设备device,图形缓冲区的组合工作已经完成,目前没有使用这个成员函数。

二、服务端调用流程

1.整体流程

frameworks/base/services/surfaceflinger/surfaceflinger.cpp
  1. status_t SurfaceFlinger::readyToRun(){  
  2.   DisplayHardware* const hw = new DisplayHardware(this, dpy);  
  3. }  
frameworks/base/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
  1. DisplayHardware::DisplayHardware(  
  2.         const sp<SurfaceFlinger>& flinger,  
  3.         uint32_t dpy)  
  4.     : DisplayHardwareBase(flinger, dpy),  
  5.       mFlinger(flinger), mFlags(0), mHwc(0)  
  6. {  
  7.   init(dpy);  
  8. }  
  9. void DisplayHardware::init(uint32_t dpy){  
  10.   mNativeWindow = new FramebufferNativeWindow();  
  11.   framebuffer_device_t const * fbDev = mNativeWindow->getDevice();  
  12.   ......  
  13.   // initialize the H/W composer  
  14.   mHwc = new HWComposer(mFlinger);  
  15.   if (mHwc->initCheck() == NO_ERROR) {  
  16.     mHwc->setFrameBuffer(mDisplay, mSurface);  
  17.   }  
  18. }  
frameworks/base/libs/ui/FramebufferNativeWindow.cpp
  1. FramebufferNativeWindow::FramebufferNativeWindow()  
  2.     : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false){  
  3.   hw_module_t const* module;  
  4.   if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {  //获得gralloc模块  
  5.     err = framebuffer_open(module, &fbDev); //获得gralloc模块下的framebuffer设备,即屏幕  
  6.     err = gralloc_open(module, &grDev);  //获得gralloc模块下的gralloc设备,即显存  
  7.     // initialize the buffer FIFO  
  8.     mNumBuffers = NUM_FRAME_BUFFERS;  
  9.     mNumFreeBuffers = NUM_FRAME_BUFFERS;  
  10.     mBufferHead = mNumBuffers-1;  
  11.   
  12.   
  13.     for (i = 0; i < mNumBuffers; i++){  
  14.       buffers[i] = new NativeBuffer(fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);  
  15.     }  
  16.   
  17.   
  18.     for (i = 0; i < mNumBuffers; i++){  
  19.       err = grDev->alloc(grDev,  
  20.                         fbDev->width, fbDev->height, fbDev->format,  
  21.                         GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride); //申请帧缓冲区作为图形缓冲区  
  22.   
  23.   
  24.       LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",  
  25.                         i, fbDev->width, fbDev->height, strerror(-err));  
  26.   
  27.   
  28.       if (err){  
  29.         mNumBuffers = i;  
  30.         mNumFreeBuffers = i;  
  31.         mBufferHead = mNumBuffers-1;  
  32.         break;  
  33.       }  
  34.     }  
  35.   }  
  36. }  

2.fb设备流程

hardware/libhardware/include/hardware/fb.h

  1. static inline int framebuffer_open(const struct hw_module_t* module,  
  2.         struct framebuffer_device_t** device) {  
  3.     return module->methods->open(module,  
  4.             GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);  
  5. }  
hardware/mstar/gralloc/gralloc_module.cpp
  1. struct private_module_t HAL_MODULE_INFO_SYM = {  
  2.     base: {  
  3.         common: {  
  4.             tag: HARDWARE_MODULE_TAG,  
  5.             version_major: 1,  
  6.             version_minor: 0,  
  7.             id: GRALLOC_HARDWARE_MODULE_ID,  
  8.             name: "Graphics Memory Allocator Module",  
  9.             author: "ARM Ltd.",  
  10.             methods: &gralloc_module_methods,  
  11.             dso: NULL,  
  12.             reserved : {0,},  
  13.         },  
  14.         registerBuffer: gralloc_register_buffer,  
  15.         unregisterBuffer: gralloc_unregister_buffer,  
  16.         lock: gralloc_lock,  
  17.         unlock: gralloc_unlock,  
  18.         perform: NULL,  
  19.         reserved_proc: {0,},  
  20.     },  
  21.     framebuffer: NULL,  
  22.     flags: 0,  
  23.     numBuffers: 0,  
  24.     bufferMask: 0,  
  25.     lock: PTHREAD_MUTEX_INITIALIZER,  
  26.     currentBuffer: NULL,  
  27. };  
  28. static struct hw_module_methods_t gralloc_module_methods = {  
  29.   open: gralloc_device_open  
  30. };  
  31. static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device)  
  32. {  
  33.   int status = -EINVAL;  
  34.   
  35.   
  36.   if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {  
  37.     status = alloc_device_open(module, name, device);  
  38.   } else if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {  
  39.     status = framebuffer_device_open(module, name, device);  
  40.   }  
  41.   return status;  
  42. }  
hardware/mstar/gralloc/framebuffer_device.cpp
  1. int framebuffer_device_open(hw_module_t const* module, const char* name,  
  2.                             hw_device_t** device)  
  3. {  
  4.   private_module_t* m = (private_module_t*)module;  
  5.   status = init_frame_buffer(m);  
  6. }  
  7. static int init_frame_buffer(struct private_module_t* module)  
  8. {  
  9.   pthread_mutex_lock(&module->lock);  
  10.   int err = init_frame_buffer_locked(module);  
  11.   pthread_mutex_unlock(&module->lock);  
  12.   return err;  
  13. }  
  14. int init_frame_buffer_locked(struct private_module_t* module)  
  15. {  
  16.   char const * const device_template[] = {  
  17.     "/dev/graphics/fb%u",  
  18.     "/dev/fb%u",  
  19.     NULL  
  20.   };  
  21.   int fd = -1;  
  22.   int i = 0;  
  23.   char name[64];  
  24.   while ((fd == -1) && device_template[i]) {  
  25.     snprintf(name, 64, device_template[i], 0);  
  26.     fd = fbdev_open(name, O_RDWR);  
  27.     i++;  
  28.   }  
  29.   
  30.   
  31.   //获得  
  32.   struct fb_fix_screeninfo finfo;  
  33.   if (fbdev_ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)  
  34.     return -errno;  
  35.   struct fb_var_screeninfo info;  
  36.   if (fbdev_ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)  
  37.     return -errno;  
  38.   //设置  
  39.   uint32_t flags = PAGE_FLIP;  
  40.   if (fbdev_ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {  
  41.     info.yres_virtual = info.yres;  
  42.     flags &= ~PAGE_FLIP;  
  43.     LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");  
  44.   }  
  45.   //映射framebuffer  
  46.   size_t fbSize = round_up_to_page_size(finfo.smem_len);  
  47.   void* vaddr = fbdev_mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);  
  48.   int hw_base = static_cast<int>(unsigned(finfo.smem_start) & MASK_MIU_PHYSADDRESS);  
  49.   module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, fbSize, intptr_t(vaddr),  
  50.                                                0, hw_base, channel, 0);  
  51. }  
3.alloc设备流程

其他调用同上,不再分析

hardware/mstar/gralloc/alloc_device.cpp

  1. static int alloc_device_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride)  
  2. {  
  3.   if (usage & GRALLOC_USAGE_HW_FB)  
  4.     err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); //支持双framebuffer时  
  5.   else  
  6.     err = gralloc_alloc_buffer(dev, size, usage, pHandle);  //不支持时  
  7. }  

4.alloc渲染到fb

hardware/mstar/gralloc/framebuffer_device.cpp

  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.     m->base.lock(&m->base, buffer,  
  5.                      private_module_t::PRIV_USAGE_LOCKED_FOR_POST,  
  6.                      0, 0, m->info.xres, m->info.yres, NULL);  
  7.   
  8.   
  9.     const size_t offset = hnd->base - m->framebuffer->base;  
  10.     m->info.activate = FB_ACTIVATE_VBL;  
  11.     m->info.yoffset = offset / m->finfo.line_length;  
  12.   
  13.   
  14.     if (fbdev_ioctl(0, FBIOPUT_VSCREENINFO, &m->info) == -1) {  
  15.       LOGE("FBIOPUT_VSCREENINFO failed");  
  16.       m->base.unlock(&m->base, buffer);  
  17.       return -errno;  
  18.     }  
  19.     m->currentBuffer = buffer;  
  20.   }esle{ //如果显示设备不支持双帧缓冲区(也就是我们应用使用的图形缓冲区只是一块内存),则完成拷贝  
  21.     m->base.lock(&m->base, m->framebuffer,  
  22.                      GRALLOC_USAGE_SW_WRITE_RARELY,  
  23.                      0, 0, m->info.xres, m->info.yres,  
  24.                      &fb_vaddr);  
  25.   
  26.   
  27.     m->base.lock(&m->base, buffer,  
  28.                      GRALLOC_USAGE_SW_READ_RARELY,  
  29.                      0, 0, m->info.xres, m->info.yres,  
  30.                      &buffer_vaddr);  
  31.     //将buffer渲染到framebuffer  
  32.     memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);  
  33.   
  34.   
  35.     m->base.unlock(&m->base, buffer);  
  36.     m->base.unlock(&m->base, m->framebuffer);  
  37.   }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值