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

1、基础数据结构

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

[cpp] view plain copy
  1. structprivate_module_t{
  2. gralloc_module_tbase;
  3. private_handle_t*framebuffer;/*指向图形缓冲区的句柄*/
  4. uint32_tflags;/*用来标志系统帧缓冲区是否支持双缓冲*/
  5. uint32_tnumBuffers;/*表示系统帧缓冲的个数*/
  6. uint32_tbufferMask;/*记录系统帧缓冲的使用情况*/
  7. pthread_mutex_tlock;/*保护结构体private_module_t的并行访问*/
  8. buffer_handle_tcurrentBuffer;/*描述当前正在被渲染的图形缓冲区*/
  9. intpmem_master;/*pmem设备节点的描述符*/
  10. void*pmem_master_base;/*pmem的起始虚拟地址*/
  11. structfb_var_screeninfoinfo;/*lcd的可变参数*/
  12. structfb_fix_screeninfofinfo;/*lcd的固定参数*/
  13. floatxdpi;/*x方向上每英寸的像素数量*/
  14. floatydpi;/*y方向上每英寸的像素数量*/
  15. floatfps;/*lcd的刷新率*/
  16. intorientation;/*显示方向*/
  17. enum{
  18. PRIV_USAGE_LOCKED_FOR_POST=0x80000000/*flagtoindicatewe'llpostthisbuffer*/
  19. };
  20. };
该结构的成员记录了 gralloc 模块的各种参数,主要为模块自己使用,应用程序操作的 图形缓冲区的数据结构是 struct private_handle_t,定义如下:
[cpp] view plain copy
  1. #ifdef__cplusplus
  2. structprivate_handle_t:publicnative_handle{
  3. #else
  4. structprivate_handle_t{
  5. structnative_handlenativeHandle;/*用来描述一个本地句柄值*/
  6. #endif
  7. enum{
  8. PRIV_FLAGS_FRAMEBUFFER=0x00000001,
  9. PRIV_FLAGS_USES_PMEM=0x00000002,
  10. PRIV_FLAGS_USES_MMEM=0x00000004,
  11. PRIV_FLAGS_NEEDS_FLUSH=0x00000008,
  12. };
  13. enum{
  14. LOCK_STATE_WRITE=1<<31,
  15. LOCK_STATE_MAPPED=1<<30,
  16. LOCK_STATE_READ_MASK=0x3FFFFFFF
  17. };
  18. /*指向一个文件描述符,这个文件描述符要么指向帧缓冲区设备,要么指向一块匿名共享内存
  19. *取决于private_handle_t描述的图形缓冲区是在帧缓冲区分配的,还是在内存中分配的*/
  20. intfd;
  21. /*指向一个魔数,它的值由静态成员变量sMagic来指定,用来标识一个private_handle_t结构体*/
  22. intmagic;
  23. /*用来描述一个图形缓冲区的标志,它的值要么等于0,要么等于PRIV_FLAGS_FRAMEBUFFER
  24. *当一个图形缓冲区的标志值等于PRIV_FLAGS_FRAMEBUFFER的时候,就表示它是在帧缓冲区中分配的*/
  25. intflags;
  26. intsize;/*描述一个图形缓冲区的大小*/
  27. intoffset;/*描述一个图形缓冲区的偏移地址*/
  28. intphys;/*图形缓冲区或帧缓冲的起始物理地址*/
  29. intbase;/*图形缓冲区或帧缓冲的起始虚拟地址*/
  30. intlockState;
  31. intwriteOwner;
  32. intpid;/*描述一个图形缓冲区的创建者的PID*/
  33. #ifdef__cplusplus
  34. staticconstintsNumInts=9;/*有9个整数变量*/
  35. staticconstintsNumFds=1;/*有1个文件描述符*/
  36. staticconstintsMagic=0x3141592;
  37. private_handle_t(intfd,intsize,intflags):
  38. fd(fd),magic(sMagic),flags(flags),size(size),offset(0),
  39. phys(0),base(0),lockState(0),writeOwner(0),pid(getpid())
  40. {
  41. version=sizeof(native_handle);
  42. numInts=sNumInts;
  43. numFds=sNumFds;
  44. }
  45. ~private_handle_t(){
  46. magic=0;
  47. }
  48. boolusesPhysicallyContiguousMemory(){
  49. return(flags&PRIV_FLAGS_USES_PMEM)!=0;
  50. }
  51. /*用来验证一个native_handle_t指针是否指向了一个private_handle_t结构体*/
  52. staticintvalidate(constnative_handle*h){
  53. constprivate_handle_t*hnd=(constprivate_handle_t*)h;
  54. if(!h||h->version!=sizeof(native_handle)||
  55. h->numInts!=sNumInts||h->numFds!=sNumFds||
  56. hnd->magic!=sMagic)
  57. {
  58. LOGE("invalidgrallochandle(at%p)",h);
  59. return-EINVAL;
  60. }
  61. return0;
  62. }
  63. staticprivate_handle_t*dynamicCast(constnative_handle*in){
  64. if(validate(in)==0){
  65. return(private_handle_t*)in;
  66. }
  67. returnNULL;
  68. }
  69. #endif
  70. };

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

[cpp] view plain copy
  1. typedefstructgralloc_module_t{
  2. structhw_module_tcommon;
  3. /*注册一个图形缓冲区,这个指定的图形缓冲区使用一个buffer_handle_t句柄来描述*/
  4. int(*registerBuffer)(structgralloc_module_tconst*module,
  5. buffer_handle_thandle);
  6. /*注销一个图形缓冲区*/
  7. int(*unregisterBuffer)(structgralloc_module_tconst*module,
  8. buffer_handle_thandle);
  9. /*用来锁定一个图形缓冲区并将缓冲区映射到用户进程
  10. *在锁定一块图形缓冲区的时候,可以指定要锁定的图形绘冲区的位置以及大小
  11. *这是通过参数l、t、w和h来指定的,其中,参数l和t指定的是要访问的图形缓冲区的左上角位置
  12. *而参数w和h指定的是要访问的图形缓冲区的宽度和长度
  13. *锁定之后,就可以获得由参数参数l、t、w和h所圈定的一块缓冲区的起始地址,保存在输出参数vaddr中
  14. *另一方面,在访问完成一块图形缓冲区之后,需要解除这块图形缓冲区的锁定*/
  15. int(*lock)(structgralloc_module_tconst*module,
  16. buffer_handle_thandle,intusage,
  17. intl,intt,intw,inth,
  18. void**vaddr);
  19. int(*unlock)(structgralloc_module_tconst*module,
  20. buffer_handle_thandle);
  21. int(*perform)(structgralloc_module_tconst*module,
  22. intoperation,...);
  23. /*reservedforfutureuse*/
  24. void*reserved_proc[7];
  25. }gralloc_module_t;

gralloc 设备则用结构struct alloc_device_t 来描述,其定义如下:

[cpp] view plain copy
  1. typedefstructalloc_device_t{
  2. structhw_device_tcommon;
  3. /*申请图形缓冲区的内存空间*/
  4. int(*alloc)(structalloc_device_t*dev,intw,inth,intformat,intusage,buffer_handle_t*handle,int*stride);
  5. /*释放图形缓冲区的内存空间*/
  6. int(*free)(structalloc_device_t*dev,buffer_handle_thandle);
  7. }alloc_device_t;
帧缓冲设备则采用结构 struct framebuffer_device_t 描述: [cpp] view plain copy
  1. typedefstructframebuffer_device_t{
  2. structhw_device_tcommon;
  3. constuint32_tflags;/*用来记录系统帧缓冲区的标志*/
  4. constuint32_twidth;/*lcd显示区域的像素点数*/
  5. constuint32_theight;
  6. constintstride;/*描述设备显示屏的一行有多少个像素点*/
  7. /*描述系统帧缓冲区的像素格式,主要有HAL_PIXEL_FORMAT_RGBX_8888和HAL_PIXEL_FORMAT_RGB_565两种*/
  8. constintformat;
  9. constfloatxdpi;
  10. constfloatydpi;
  11. constfloatfps;/*lcd刷新率*/
  12. constintminSwapInterval;/*交换两帧图像的最小间隔时间*/
  13. constintmaxSwapInterval;/*交换两帧图像的最大间隔时间*/
  14. intreserved[8];
  15. /*设置帧交换间隔*/
  16. int(*setSwapInterval)(structframebuffer_device_t*window,intinterval);
  17. /*设置帧缓冲区的更新区域*/
  18. int(*setUpdateRect)(structframebuffer_device_t*window,intleft,inttop,intwidth,intheight);
  19. /*用来将图形缓冲区buffer的内容渲染到帧缓冲区中去,即显示在设备的显示屏中去*/
  20. int(*post)(structframebuffer_device_t*dev,buffer_handle_tbuffer);
  21. /*用来通知fb设备device,图形缓冲区的组合工作已经完成*/
  22. int(*compositionComplete)(structframebuffer_device_t*dev);
  23. void*reserved_proc[8];
  24. }framebuffer_device_t;
其中成员函数 post 对应用程序来说是最重要的接口,它将完成数据写入显存的工作。

2、gralloc 模块

HAL 中通过hw_get_module 接口加载指定 id 的模块,并获得一个hw_module_t 结构来打开设备,流程如下:

[cpp] view plain copy
  1. #defineHAL_LIBRARY_PATH1"/system/lib/hw"
  2. #defineHAL_LIBRARY_PATH2"/vendor/lib/hw"
  3. staticconstchar*variant_keys[]={
  4. "ro.hardware",/*Thisgoesfirstsothatitcanpickupadifferentfileontheemulator.*/
  5. "ro.product.board",
  6. "ro.board.platform",
  7. "ro.arch"
  8. };
  9. staticconstintHAL_VARIANT_KEYS_COUNT=
  10. (sizeof(variant_keys)/sizeof(variant_keys[0]));
  11. inthw_get_module(constchar*id,conststructhw_module_t**module)
  12. {
  13. intstatus;
  14. inti;
  15. conststructhw_module_t*hmi=NULL;
  16. charprop[PATH_MAX];
  17. charpath[PATH_MAX];
  18. /*
  19. *Herewerelyonthefactthatcallingdlopenmultipletimeson
  20. *thesame.sowillsimplyincrementarefcount(andnotload
  21. *anewcopyofthelibrary).
  22. *Wealsoassumethatdlopen()isthread-safe.
  23. */
  24. /*Loopthroughtheconfigurationvariantslookingforamodule*/
  25. for(i=0;i<HAL_VARIANT_KEYS_COUNT+1;i++){
  26. if(i<HAL_VARIANT_KEYS_COUNT){
  27. if(property_get(variant_keys[i],prop,NULL)==0){/*读取variant_keys数组指定的属性值*/
  28. continue;
  29. }
  30. snprintf(path,sizeof(path),"%s/%s.%s.so",/*格式化模块名和路径,如:/system/lib/hw/gralloc.xxx.so*/
  31. HAL_LIBRARY_PATH1,id,prop);
  32. if(access(path,R_OK)==0)break;
  33. snprintf(path,sizeof(path),"%s/%s.%s.so",
  34. HAL_LIBRARY_PATH2,id,prop);
  35. if(access(path,R_OK)==0)break;
  36. }else{
  37. snprintf(path,sizeof(path),"%s/%s.default.so",
  38. HAL_LIBRARY_PATH1,id);
  39. if(access(path,R_OK)==0)break;
  40. }
  41. }
  42. status=-ENOENT;
  43. if(i<HAL_VARIANT_KEYS_COUNT+1){
  44. /*loadthemodule,ifthisfails,we'redoomed,andweshouldnottrytoloadadifferentvariant.*/
  45. status=load(id,path,module);/*加载模块*/
  46. }
  47. returnstatus;
  48. }

函数会在/system/lib/hw 或者/vendor/lib/hw 目录中去寻找gralloc.xxx.so 文件,如果找到了就调用load接口完成加载。最终会调用gralloc_device_open完成 gralloc 设备成员的初始化:

[cpp] view plain copy
  1. intgralloc_device_open(consthw_module_t*module,constchar*name,
  2. hw_device_t**device)
  3. {
  4. intstatus=-EINVAL;
  5. if(!strcmp(name,GRALLOC_HARDWARE_GPU0)){
  6. gralloc_context_t*dev;
  7. dev=(gralloc_context_t*)malloc(sizeof(*dev));
  8. /*initializeourstatehere*/
  9. memset(dev,0,sizeof(*dev));
  10. /*initializetheprocs*/
  11. dev->device.common.tag=HARDWARE_DEVICE_TAG;
  12. dev->device.common.version=0;
  13. dev->device.common.module=const_cast<hw_module_t*>(module);
  14. dev->device.common.close=gralloc_close;
  15. dev->device.alloc=gralloc_alloc;
  16. dev->device.free=gralloc_free;
  17. *device=&dev->device.common;
  18. status=0;
  19. }else{
  20. status=fb_device_open(module,name,device);
  21. }
  22. returnstatus;
  23. }
在 android 系统中,所有的图形缓冲区都是由 SurfaceFlinger 服务分配的,在系统帧缓冲区中分配的图形缓冲区只在 SurfaceFlinger 服务中使用,而在内存中分配的图形缓冲区既可以在 SurfaceFlinger 服务中使用,也可以在其它的应用程序中使用,当应用程序请求 SurfaceFlinger 服务分配图形缓冲区时会发生 两次映射:服务所在的进程首先会将申请到的缓冲区映射至服务的地址空间,然后应用程序使用这个图形缓冲时再将其映射至应用程序的地址空间。分配函数的实现如下: [cpp] view plain copy
  1. staticintgralloc_alloc_framebuffer(alloc_device_t*dev,size_tsize,intusage,buffer_handle_t*pHandle)
  2. {
  3. private_module_t*m=reinterpret_cast<private_module_t*>(
  4. dev->common.module);
  5. pthread_mutex_lock(&m->lock);
  6. interr=gralloc_alloc_framebuffer_locked(dev,size,usage,pHandle);
  7. pthread_mutex_unlock(&m->lock);
  8. returnerr;
  9. }
  10. staticintgralloc_alloc_buffer(alloc_device_t*dev,size_tsize,intusage,buffer_handle_t*pHandle)
  11. {
  12. interr=0;
  13. intfd=-1;
  14. size=roundUpToPageSize(size);
  15. fd=ashmem_create_region("gralloc-buffer",size);
  16. if(fd<0){
  17. LOGE("couldn'tcreateashmem(%s)",strerror(-errno));
  18. err=-errno;
  19. }
  20. if(err==0){
  21. private_handle_t*hnd=newprivate_handle_t(fd,size,0);
  22. gralloc_module_t*module=reinterpret_cast<gralloc_module_t*>(
  23. dev->common.module);
  24. err=mapBuffer(module,hnd);
  25. if(err==0){
  26. *pHandle=hnd;
  27. }
  28. }
  29. LOGE_IF(err,"grallocfailederr=%s",strerror(-err));
  30. returnerr;
  31. }
  32. /*****************************************************************************/
  33. staticintgralloc_alloc(alloc_device_t*dev,intw,inth,intformat,intusage,
  34. buffer_handle_t*pHandle,int*pStride)
  35. {
  36. if(!pHandle||!pStride)
  37. return-EINVAL;
  38. size_tsize,stride;
  39. intalign=4;
  40. intbpp=0;
  41. switch(format){/*一个像素点占用的字节数*/
  42. caseHAL_PIXEL_FORMAT_RGBA_8888:
  43. caseHAL_PIXEL_FORMAT_RGBX_8888:
  44. caseHAL_PIXEL_FORMAT_BGRA_8888:
  45. bpp=4;
  46. break;
  47. caseHAL_PIXEL_FORMAT_RGB_888:
  48. bpp=3;
  49. break;
  50. caseHAL_PIXEL_FORMAT_RGB_565:
  51. caseHAL_PIXEL_FORMAT_RGBA_5551:
  52. caseHAL_PIXEL_FORMAT_RGBA_4444:
  53. bpp=2;
  54. break;
  55. default:
  56. return-EINVAL;
  57. }
  58. size_tbpr=(w*bpp+(align-1))&~(align-1);
  59. size=bpr*h;
  60. stride=bpr/bpp;
  61. interr;
  62. if(usage&GRALLOC_USAGE_HW_FB){
  63. err=gralloc_alloc_framebuffer(dev,size,usage,pHandle);/*在系统帧缓冲中分配图形缓冲区*/
  64. }else{
  65. err=gralloc_alloc_buffer(dev,size,usage,pHandle);/*在内存中分配图形缓冲区*/
  66. }
  67. if(err<0){
  68. returnerr;
  69. }
  70. *pStride=stride;
  71. return0;
  72. }
3、fb 模块

在gralloc_device_open 中会根据传递的参数分别初始化两个设备,定义如下:

[cpp] view plain copy
  1. #defineGRALLOC_HARDWARE_FB0"fb0"
  2. #defineGRALLOC_HARDWARE_GPU0"gpu0"
如果参数不是 "gpu0" 则会调用 fb_device_open初始化 fb 设备,主要流程和打开 gralloc 基本一致,在函数中会通过调用 mapFrameBuffer->mapFrameBufferLocked 获取帧缓存设备的参数并将其设备节点映射到用户空间,流程如下: [cpp] view plain copy
  1. intmapFrameBufferLocked(structprivate_module_t*module)
  2. {
  3. if(module->framebuffer){
  4. return0;
  5. }
  6. charconst*constdevice_template[]={
  7. "/dev/graphics/fb%u",
  8. "/dev/fb%u",
  9. 0};
  10. intfd=-1;
  11. inti=0;
  12. charname[64];
  13. while((fd==-1)&&device_template[i]){
  14. snprintf(name,64,device_template[i],0);
  15. fd=open(name,O_RDWR,0);
  16. i++;
  17. }
  18. if(fd<0)
  19. return-errno;
  20. structfb_fix_screeninfofinfo;
  21. if(ioctl(fd,FBIOGET_FSCREENINFO,&finfo)==-1)/*获取帧缓冲的固定参数*/
  22. return-errno;
  23. structfb_var_screeninfoinfo;
  24. if(ioctl(fd,FBIOGET_VSCREENINFO,&info)==-1)/*获取帧缓冲的可变参数*/
  25. return-errno;
  26. info.reserved[0]=0;
  27. info.reserved[1]=0;
  28. info.reserved[2]=0;
  29. info.xoffset=0;
  30. info.yoffset=0;
  31. info.activate=FB_ACTIVATE_NOW;
  32. info.bits_per_pixel=32;
  33. info.red.offset=16;
  34. info.red.length=8;
  35. info.green.offset=8;
  36. info.green.length=8;
  37. info.blue.offset=0;
  38. info.blue.length=8;
  39. info.transp.offset=24;
  40. info.transp.length=8;
  41. /*
  42. *RequestNUM_BUFFERSscreens(atlest2forpageflipping)
  43. */
  44. info.yres_virtual=info.yres*NUM_BUFFERS;/*帧缓冲总长度*/
  45. uint32_tflags=PAGE_FLIP;/*支持缓冲交换*/
  46. if(ioctl(fd,FBIOPAN_DISPLAY,&info)==-1){
  47. info.yres_virtual=info.yres;
  48. flags&=~PAGE_FLIP;
  49. LOGW("FBIOPAN_DISPLAYfailed,pageflippingnotsupported");
  50. }
  51. if(info.yres_virtual<info.yres*2){
  52. /*weneedatleast2forpage-flipping*/
  53. info.yres_virtual=info.yres;
  54. flags&=~PAGE_FLIP;
  55. LOGW("pageflippingnotsupported(yres_virtual=%d,requested=%d)",
  56. info.yres_virtual,info.yres*2);
  57. }
  58. if(ioctl(fd,FBIOGET_VSCREENINFO,&info)==-1)
  59. return-errno;
  60. intrefreshRate=1000000000000000LLU/
  61. (
  62. uint64_t(info.upper_margin+info.lower_margin+info.yres)
  63. *(info.left_margin+info.right_margin+info.xres)
  64. *info.pixclock
  65. );/*计算lcd刷新率*/
  66. if(refreshRate==0){
  67. /*bleagh,badinfofromthedriver*/
  68. refreshRate=60*1000;//60Hz
  69. }
  70. if(int(info.width)<=0||int(info.height)<=0){
  71. /*thedriverdoesn'treturnthatinformation,defaultto160dpi*/
  72. info.width=((info.xres*25.4f)/160.0f+0.5f);
  73. info.height=((info.yres*25.4f)/160.0f+0.5f);
  74. }
  75. floatxdpi=(info.xres*25.4f)/info.width;
  76. floatydpi=(info.yres*25.4f)/info.height;
  77. floatfps=refreshRate/1000.0f;
  78. LOGI("using(fd=%d)\n"
  79. "id=%s\n"
  80. "xres=%dpx\n"
  81. "yres=%dpx\n"
  82. "xres_virtual=%dpx\n"
  83. "yres_virtual=%dpx\n"
  84. "bpp=%d\n"
  85. "r=%2u:%u\n"
  86. "g=%2u:%u\n"
  87. "b=%2u:%u\n",
  88. fd,
  89. finfo.id,
  90. info.xres,
  91. info.yres,
  92. info.xres_virtual,
  93. info.yres_virtual,
  94. info.bits_per_pixel,
  95. info.red.offset,info.red.length,
  96. info.green.offset,info.green.length,
  97. info.blue.offset,info.blue.length
  98. );
  99. LOGI("width=%dmm(%fdpi)\n"
  100. "height=%dmm(%fdpi)\n"
  101. "refreshrate=%.2fHz\n",
  102. info.width,xdpi,
  103. info.height,ydpi,
  104. fps
  105. );
  106. if(ioctl(fd,FBIOGET_FSCREENINFO,&finfo)==-1)
  107. return-errno;
  108. if(finfo.smem_len<=0)
  109. return-errno;
  110. module->flags=flags;
  111. module->info=info;
  112. module->finfo=finfo;
  113. module->xdpi=xdpi;
  114. module->ydpi=ydpi;
  115. module->fps=fps;
  116. /*
  117. *maptheframebuffer
  118. */
  119. interr;
  120. size_tfbSize=roundUpToPageSize(finfo.line_length*info.yres_virtual);/*帧缓冲大小*/
  121. module->framebuffer=newprivate_handle_t(dup(fd),fbSize,
  122. private_handle_t::PRIV_FLAGS_USES_PMEM);
  123. module->numBuffers=info.yres_virtual/info.yres;/*计算系统帧缓冲的个数*/
  124. module->bufferMask=0;
  125. void*vaddr=mmap(0,fbSize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);/*将fb映射到用户空间*/
  126. if(vaddr==MAP_FAILED){
  127. LOGE("Errormappingtheframebuffer(%s)",strerror(errno));
  128. return-errno;
  129. }
  130. module->framebuffer->base=intptr_t(vaddr);/*帧缓冲的起始虚拟地址*/
  131. memset(vaddr,0,fbSize);
  132. return0;
  133. }

fb 模块最重要的工作就是将应用程序指定的内容写入显存中,是通过函数fb_post 完成的,流程如下:

[cpp] view plain copy
  1. /*将图形缓冲区buffer的内容渲染到帧缓冲区中去*/
  2. staticintfb_post(structframebuffer_device_t*dev,buffer_handle_tbuffer)
  3. {
  4. unsignedintphys;
  5. void*virt;
  6. intpitch;
  7. intformat;
  8. /*首先验证参数handle指向的一块图形缓冲区的确是由Gralloc模块分配的*/
  9. if(private_handle_t::validate(buffer)<0)
  10. return-EINVAL;
  11. fb_context_t*ctx=(fb_context_t*)dev;
  12. private_handle_tconst*hnd=reinterpret_cast<private_handle_tconst*>(buffer);/*图形缓冲区*/
  13. private_module_t*m=reinterpret_cast<private_module_t*>(dev->common.module);/*帧缓冲区*/
  14. if(m->currentBuffer){/*当前正在渲染的图形缓冲区*/
  15. m->base.unlock(&m->base,m->currentBuffer);
  16. m->currentBuffer=0;
  17. }
  18. if(hnd->flags&private_handle_t::PRIV_FLAGS_FRAMEBUFFER){/*如果图形缓冲区是在系统帧缓冲中分配的*/
  19. m->base.lock(&m->base,buffer,/*锁定图像缓冲区*/
  20. private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
  21. 0,0,m->info.xres,m->info.yres,NULL);
  22. constsize_toffset=hnd->base-m->framebuffer->base;/*计算图形缓冲区与帧缓冲的偏移*/
  23. /*将作为参数的fb_var_screeninfo结构体的成员变量activate的值设置FB_ACTIVATE_VBL
  24. *表示要等到下一个垂直同步事件出现时,再将当前要渲染的图形缓冲区的内容绘制出来
  25. *这样做的目的是避免出现屏幕闪烁,即避免前后两个图形缓冲区的内容各有一部分同时出现屏幕中*/
  26. m->info.activate=FB_ACTIVATE_VBL;
  27. m->info.yoffset=offset/m->finfo.line_length;/*得到偏移的起始行*/
  28. if(ioctl(m->framebuffer->fd,FBIOPAN_DISPLAY,&m->info)==-1){/*刷新显示内容*/
  29. LOGE("FBIOPAN_DISPLAYfailed");
  30. m->base.unlock(&m->base,buffer);
  31. return-errno;
  32. }
  33. if(UNLIKELY(mDebugFps)){
  34. debugShowFPS();
  35. }
  36. #ifdefSNAPSHOT
  37. dumpfile((void*)hnd->base,m->info.xres,m->info.yres);/*dump帧缓冲*/
  38. #endif
  39. m->currentBuffer=buffer;/*设置当前图形缓冲区*/
  40. }else{/*如果图形缓冲区是在内存中分配的*/
  41. /*Ifwecan'tdothepage_flip,justcopythebuffertothefront
  42. *FIXME:usecopybitHALinsteadofmemcpy*/
  43. LOGD("copybit.\n");
  44. void*fb_vaddr;
  45. void*buffer_vaddr;
  46. /*将帧缓冲整个锁定*/
  47. m->base.lock(&m->base,m->framebuffer,
  48. GRALLOC_USAGE_SW_WRITE_RARELY,
  49. 0,0,m->info.xres,m->info.yres,
  50. &fb_vaddr);
  51. /*将图形缓冲整个锁定*/
  52. m->base.lock(&m->base,buffer,
  53. GRALLOC_USAGE_SW_READ_RARELY,
  54. 0,0,m->info.xres,m->info.yres,
  55. &buffer_vaddr);
  56. /*将图形缓冲的内容拷贝到帧缓冲中即显示到lcd*/
  57. memcpy(fb_vaddr,buffer_vaddr,m->finfo.line_length*m->info.yres);
  58. m->base.unlock(&m->base,buffer);/*解锁*/
  59. m->base.unlock(&m->base,m->framebuffer);
  60. }
  61. return0;
  62. }

更多相关文章

  1. Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原
  2. Android(安卓)直接显示yuv数据 通过Awesomeplayer方式直接显示(三
  3. android-opengles3.0开发-2-绘制图形
  4. 我是一只忍者神龟.
  5. Android图形图画学习(11)——颜色相关
  6. 视频学习笔记:Android(安卓)ffmpeg解码多路h264视频并显示
  7. android立体图形——三棱锥
  8. android 解决java.nio.BufferOverflowException 异常
  9. Android——图形系统

随机推荐

  1. 【Android】保存Fragment切换状态
  2. Android(安卓)Framework 调试 (java)
  3. android:用getIdentifier()获取资源Id
  4. 上官网学android之五(Managing the Activi
  5. Android(安卓)MIFARE读写器详解2
  6. android 自定义命名空间
  7. 搬砖:深入浅出 - Android系统移植与平台开
  8. Android(安卓)Glide图片加载框架图片变色
  9. android 客户端上传到第三方应用市场
  10. ImageLoader源码解析