瑞芯微Rockchip开发者社区
直播中

杨福林

7年用户 1480经验值
私信 关注
[问答]

rk3288 单Buffer的缺点有哪些?怎样去改进呢

单Buffer的缺点
如果App速度很慢,可以看到它在LCD上缓慢绘制图案
计时App速度很高,LCD控制器不断从Framebuffer中读取数据来显示,而App不断把数据写入Framebuffer
假设App想把LCD显示为整屏幕的蓝色、红色
很大概率不限这种情况:
LCD控制器速度Framebuffer数据,读到一半时,在LCD上显示了半屏幕的蓝色
这是App非常高效地把整个Framebuffer地数据都改成了红色
LCD控制器继续读取数据,于是LCD上就会显示半屏幕蓝色、半屏幕红色
人眼就会感觉到屏幕闪烁、撕裂
使用多Buffer来改进
上述两个缺点地根源是一致地:Framebuffer中地数据还没准备好整帧数据,就被LCD控制器使用了。
使用双buffer甚至多buffer可以解决这个问题:
假设有2个Framebuffer: FB0、FB1
LCD控制器正在读取FB0
APP写FB1
写好FB1后,让LCD控制器切换到FB1
App写FB0
写好FB0后,让LCD控制器切换到FB0
内核驱动程序分析
驱动:分配多个buffer
  fb_info->fix.smem_len = SZ_32M; //设置smem_len的大小
  fbi->screen_base = dma_alloc_writecombine(fbi->device, //分配设置的大小
  fbi->fix.smem_len,
  (dma_addr_t *)&fbi->fix.smem_start,
  GFP_DMA | GFP_KERNEL);
驱动:保存buffer信息
  fb_info->fix.smem_len  // 含有总buffer大小
  fb_info->var           // 含有单个buffer信息
APP:读取buffer信息
  ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix);
  ioctl(fd_fb, FBIOGET_VSCREENINFO, &var);
  // 计算是否支持多buffer,有多少个buffer
  screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
  nBuffers = fix.smem_len / screen_size;
APP:使能多buffer
  var.yres_virtual = nBuffers * var.yres;
  ioctl(fd_fb, FBIOPUT_VSCREENINFO, &var);
APP:写buffer
  fb_base = (unsigned char *)mmap(NULL , fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
  /* get buffer */
  pNextBuffer =  fb_base + nNextBuffer * screen_size;
  /* set buffer */
  lcd_draw_screen(pNextBuffer, colors[i]);
APP:开始切换buffer
  /* switch buffer */
  var.yoffset = nNextBuffer * var.yres;
  ioctl(fd_fb, FBIOPAN_DISPLAY, &var);
驱动:切换buffer
  // fbmem.c
  fb_ioctl
      do_fb_ioctl
      fb_pan_display(info, &var);
  err = info->fbops->fb_pan_display(var, info) // 调用硬件相关的函数  
APP:等待切换完成(在驱动程序中已经等待切换完成了,所以这个调用并无必要)
  ret = 0;
  ioctl(fd_fb, FBIO_WAITFORVSYNC, &ret);

原作者:习惯就好zz

回帖(1)

刘桂英

2022-5-14 11:29:43
举报

更多回帖

发帖
×
20
完善资料,
赚取积分