DirectFB学习之修改FrameBuffer驱动支持双缓冲
来源:互联网 发布:java 泛型 多继承 编辑:程序博客网 时间:2024/06/05 05:14
nuc972开发板购买地址,感谢支持
DirectFB学习之修改FrameBuffer驱动支持双缓冲
折腾了一段时间基于nuc972平台的2D硬件加速驱动终于在DirectFB上跑起来了,但是我发现只要我想在独占模式下创建Primary Sufrace并指定为Video memory时会失败,即使我在正常模式下创建成功了,绘图也并不会对Primary Sufrace进行硬件加速,提示失败的原因是Primary Sufrace的内存是来自system memory,创建Primary Sufrace的代码如下:
.............................................................................desc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT;desc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;desc.caps &= ~(DSCAPS_SYSTEMONLY);desc.caps |= DSCAPS_VIDEOONLY;desc.width = 800;desc.height = 480;if (dest_format != DSPF_UNKNOWN) { desc.flags |= DSDESC_PIXELFORMAT; desc.pixelformat = dest_format;}dfb->SetCooperativeLevel( dfb, DFSCL_FULLSCREEN );/* Create a primary surface. */ret = dfb->CreateSurface( dfb, &desc, &dest );.............................................................................
我有足够的video memory为什么Primary Sufrace的内存还会从system memory来呢,后面实在是没思路了,然后注意到DirectFB启动的时候有几条警告信息,心想先把这几条警告信息解决也许问题就解决了,果不其然,我注意到如下一条警告信息:
.............................................................................(!) DirectFB/DirectFBCreate: Setting desktop buffer mode failed! -> No virtual resolution support or not enough memory? Falling back to system back buffer..............................................................................
由上面这条警告信息一路看下去,最后找到是如下检测代码返回失败了。
.............................................................................static DFBResultdfb_fbdev_mode_to_var( const VideoMode *mode, DFBSurfacePixelFormat pixelformat, unsigned int vxres, unsigned int vyres, unsigned int xoffset, unsigned int yoffset, DFBDisplayLayerBufferMode buffermode, struct fb_var_screeninfo *ret_var ){............................................................................. /* Set buffer mode */ switch (buffermode) { case DLBM_TRIPLE: if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0) return DFB_UNSUPPORTED; var.yres_virtual *= 3; break; case DLBM_BACKVIDEO: if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0) return DFB_UNSUPPORTED; var.yres_virtual *= 2; break; case DLBM_BACKSYSTEM: case DLBM_FRONTONLY: break; default: return DFB_UNSUPPORTED; }.............................................................................}.............................................................................
当我的buffermode设置为DLBM_BACKVIDEO时结果因为条件if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
成立了而返回DFB_UNSUPPORTED了。
问题原因终于要浮现出来了,但fix.ypanstep
和fix.ywrapstep
是什么鬼,很显然他们是来自于FrameBuffer驱动返回的值,但我对FrameBuffer驱动了解比较少,一下不知道它们是做什么用的,上网查之,发现这两个变量的设置是和FrameBuffer驱动是否支持双缓冲有关的,它们在内核代码的fb_fix_screeninfo
结构体内,如下:
.............................................................................struct fb_fix_screeninfo { char id[16]; /* identification string eg "TT Builtin" */ unsigned long smem_start; /* Start of frame buffer mem */ /* (physical address) */ __u32 smem_len; /* Length of frame buffer mem */ __u32 type; /* see FB_TYPE_* */ __u32 type_aux; /* Interleave for interleaved Planes */ __u32 visual; /* see FB_VISUAL_* */ __u16 xpanstep; /* zero if no hardware panning */ __u16 ypanstep; /* zero if no hardware panning */ __u16 ywrapstep; /* zero if no hardware ywrap */ __u32 line_length; /* length of a line in bytes */ unsigned long mmio_start; /* Start of Memory Mapped I/O */ /* (physical address) */ __u32 mmio_len; /* Length of Memory Mapped I/O */ __u32 accel; /* Indicate to driver which */ /* specific chip/card we have */ __u16 capabilities; /* see FB_CAP_* */ __u16 reserved[2]; /* Reserved for future compatibility */};.............................................................................
虽然给了注释但我看完还是一脸茫然的,看了几篇帖子后才明白它们是用来配置显卡是否支持平移显示,即切换显示缓冲区,我们知道我们在LCD上看的内容多是对应的一块连续的内存的,硬件自动的根据行场时钟把这块内存的东西扫描到LCD上显示出来,所以假如我们改变扫描开始的内存地址是不是可以控制LCD上显示的内存区域,这样慢慢增加扫描起始地址,显示内容就好像是在平移了。是不是很酷,这好像是实现了动画的效果了,那xpanstep
和ypanstep
指定的就是可以支持水平的平移还是垂直的平移了,这貌似会跟LCD控制器的扫描方向有关,即先扫行还是先扫列这样,而至于ywrapstep
我还没搞明白,还希望大牛能指点下。
既然明白了其中的道理,那要怎么来实现它们呢,下面这篇文章给了我很大的帮助,感谢原作者。
Android图形系统的分析与移植–七、双缓冲framebuffer的实现从中我们大概知道我要做如下动作:
- 设置硬件支持的显示平移的方式
- 分配更多的显存以支持显示平移,或者说用于双缓冲
- 实现显示平移函数fb_pan_display
如下我是针对nuc972平台的实现如下我们设置平移方式为支持垂直平移,在FrameBuffer驱动的probe函数中设置。
.............................................................................fbinfo->fix.xpanstep = 0;fbinfo->fix.ypanstep = 1; fbinfo->fix.ywrapstep = 0;.............................................................................
这么一来我们的显示的区域应该相应的加大,这些信息在fb_var_screeninfo
结构体中设置,如上我们加大的y方向,所以我们要设置其中的yres_virtual
的值,这里我们加大一倍,即双缓冲其实是两块内存的切换。如下:
............................................................................./* it should be the same size as the display */var->xres_virtual = display->xres;var->yres_virtual = display->yres * 2;var->height = display->height;var->width = display->width;.............................................................................
当然还有显存的加大,即DirectFB中的video memory,这里就不描述了,下面看下怎么实现平移函数fb_pan_display,如下是它在nuc972平台上的实现:
............................................................................./* pan display */static int nuc970fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct nuc970fb_info *fbi = info->par; void __iomem *regs = fbi->io; u32 lcd_va_fbctrl = 0x00; unsigned long smem_start = (info->fix.smem_start + var->yoffset * info->fix.line_length + var->xoffset * info->var.bits_per_pixel / 8); lcd_va_fbctrl = readl(regs + REG_LCM_VA_FBCTRL); if(lcd_va_fbctrl & 0x40000000) { writel(smem_start, regs + REG_LCM_VA_BADDR1); lcd_va_fbctrl |= 0x40000000; } else { writel(smem_start, regs + REG_LCM_VA_BADDR0); lcd_va_fbctrl &= (~0x40000000); } writel(lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL); return 0x00;}.............................................................................
要搞明白它,我们主要明白数据手册中关于LCD控制器中关于VA_FBCTRL寄存器的描述,关于它的描述如下:
如上描述我们只要初始化时使能双缓冲切换功能,即置位DB_EN,然后操作位START_BUF即可实现LCD缓冲区的起始地址的切换了,它们分别存放在VA_BADDR0和VA_BADDR1中,转换为程序实现即是nuc970fb_pan_display函数的实现。
即使硬件上没有提供DB_EN、VA_BADDR0和VA_BADDR1这样的寄存器我们仍然是可以通过改变LCD控制器的framebuffer起始地址来实现这一点。
到这里双缓冲驱动终于欢快的跑起来了。
小结
从这里我们也发现DirectFB为每个创建的Sufrace多提供了双缓冲的支持,所以它在创建Primary Sufrace时会要求我们的FrameBuffer驱动支持双缓冲驱动,当它发现我们的FrameBuffer驱动不支持双缓冲驱动的时候,它就会自己从system memory里面分配出一块内存来实现双缓冲,而从system memory分配的内存是不支持2D硬件加速的,所以这也是为什么我之前对Primary Sufrace一直不能使用硬件加速的原因了。
- DirectFB学习之修改FrameBuffer驱动支持双缓冲
- 与afreez一起学习DirectFB之:framebuffer相关基础
- DirectFB学习之适配FreeType支持
- DirectFB学习之添加gfx驱动
- DirectFB学习之使用devmem驱动
- linux帧缓冲(framebuffer)驱动
- linux帧缓冲(framebuffer)驱动
- 双缓冲 framebuffer 切换
- framebuffer驱动学习之代码分析
- 与afreez一起学习DirectFB之:一个linux下的framebuffer例子的学问
- DirectFB学习之图形加速驱动的匹配
- FrameBuffer驱动学习
- framebuffer缓冲帧/dev/fb0学习
- Linux设备驱动之Framebuffer
- Linux中LCD设备驱动--framebuffer(帧缓冲)
- Linux中LCD设备驱动 framebuffer(帧缓冲)
- Linux 驱动学习-framebuffer-fb-LCD驱动
- 基于DirectFB的framebuffer底层驱动及应用程序架构原理分析
- /*二路归并排序,递归*/
- 排序算法概述java
- SRM589 Div1Medium GearsDiv1
- Machine Learning第三讲[Logistic回归] --(三)多元分类
- poj2342-Anniversary party(树形动规)
- DirectFB学习之修改FrameBuffer驱动支持双缓冲
- mybatis整理笔记MapperXML文件2 -- MapperXML文件中的insert, update and delete
- 51. N-Queens Hard
- java中TreeMap用例,并加入比较器排序
- 计算字符串长度
- apache下虚拟域名配置
- Django之admin 一
- finally在return前还是后进行 解析
- 2017.4.17