您的位置:华清远见教育科技集团 >> Android资料 >> Android 双缓冲局部渲染  
 
Android 双缓冲局部渲染
分享到:

在Linux中,所有的设备被映射成文件进行操作,为了更方便地操作显存。Linux 2.2引入了帧缓冲设备这一特性。

帧缓冲设备提供了显存的抽象描述。作为字符型设备,应用程序通过定义好的接口可以访问显卡,而不必知道底层的物理显存位置、换页机制等操作细节。该设备使用特定的设备节点,通常位于/dev目录,如/dev/fb*。通常主设备号是29,次设备号定义帧缓冲的个数。Linux多支持32个帧缓冲设备,/dev/fb则为当前默认的帧缓冲设备,通常指向/dev/fb0,但在Android中,通常指向/dev/graphics/fb0。

目前的两种帧缓冲设备标准为TGA、VESA。其中VESA采用更为广泛。帧缓冲功能初被加入到Linux内核,是为了显示Linux的“企鹅”图标。

通过帧缓冲设备,用户可以执行读写屏幕、抓屏、mmap、I/O控制等操作。通过mmap操作,可以将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,这将提高渲染效率。通过I/O控制,用户可以读取/设定显示设备的参数,如分辨率、显示颜色数、屏幕大小等。

在Android中,没有采用X Server等解决方案,而是采用了直接操作帧缓冲的方式,同时引入了双缓冲的概念(前端缓冲和后端缓冲),这有效地减少了通信间的开销。

在帧缓冲中,有个关键的特性需要了解。通常对于屏幕的渲染是采用整屏的方式来渲染的,但很多时候,内容只是在局部区域发生了变化,整屏的重绘在工作量上就显得有些冗余。为了能进行局部渲染,Android引入了copybit类(效果并不明显),而双缓冲的切换在位于fb_post函数中,如果由于某种原因无法完成前端缓冲和后端缓冲的切换,则直接将后端缓冲的内容复制到前端缓冲中,在Android中的实现过程如下:

代码:fb_post函数的实现

static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
    {
    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_t const*>(buffer);
    private_module_t* m=reinterpret_cast< private_module_t*>(dev->common.module);
    if (m->currentBuffer) {
      m->base.unlock(&m->base, m->currentBuffer);
      m->currentBuffer=0;
    }
    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
    m->base.lock(&m->base, buffer,
      private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
      0, 0, m->info.xres, m->info.yres, NULL);
    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 {
    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;
    }

如果前端缓冲和后端缓冲切换有问题,容易引起界面出现闪烁现象。

在Aurora中,帧缓冲的驱动实现被放置在aurora\msm\msm\drivers\video\msm目录下。在Android中,帧缓冲的驱动实现被放置在hardware\libhardware\modules\gralloc目录下。

 更多相关文章

·Android Overlay硬件加速
·Android OpenGL ES渲染方式
·Android Skia UI控件架构
·Android Skia图形渲染
·Android Skia 渲染概述