Chinaunix首页 | 论坛 | 博客
  • 博客访问: 765275
  • 博文数量: 370
  • 博客积分: 2334
  • 博客等级: 大尉
  • 技术积分: 3222
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-06 16:56
文章分类

全部博文(370)

文章存档

2013年(2)

2012年(368)

分类:

2012-06-26 20:45:41

Andrew Huang  转载请注明作者及联络方式

FB最重要的操作绘制显存并且在LCD显示.显存是由LCD驱动在内核中分配的可以进行DMA的SDRAM空间.如果用户进程需要操作显存,必须用mmap将内核空间映射到用户进程来可操作.

而映射的操作主要通过mmap来完成
 void *mmap(void *start, size_t length, int prot, int flags,int fd, off_t offset);
参数含意
  • start要求空间起始地址,一般为NULL,表示自动分配.
  • Length,映射区域的长度,
  • Prot是映射区域的属性,一般设为可读可写
  • fd是open("/dev/fb0")
  • flags,这里必须设为共享 MAP_SHARED.
  • Offset表示返回地址在映射空间的偏移量,一般是0

如果成功将返回一个地址,大体位于进程的堆与栈中间的空间地区,否则返回-1

mmap的映射的功能主要有如下三大类
 1.用户用内存映射方式打开文件。
 2.在进程间共享内存
 3.在进程与驱动间共享内核空间。

因此fb驱动映射显存只是mmap其中一个应用.不同的应用主要区别在mmap的参数fd来源不同.
1.如果打开文件,则fd为打开文件的
2.哪果打开共享内存,则为shm_open()返回值
3.如果与驱动共享,则用open打开设备结点的返回值

显存内数据组织

 显存内的数据组织高度依赖于分辩率和BPP,因为其大小就为  xres*yres*BPP.
 不同的分辩率下有不同组织形式。

对于不同分辩率的分布可以查看fb_var_screeninfo结构下的的fb_bitfield,这是驱动用于告诉应用程序RGB数据排列的数据
  
   

struct fb_bitfield red;        /* bitfield in fb mem if true color, */
    struct fb_bitfield green;    /* else only length is significant */
    struct fb_bitfield blue;
    struct fb_bitfield transp;    /* transparency            */    


它有如下定义


struct fb_bitfield {
    __u32 offset;            /* beginning of bitfield    */
    __u32 length;            /* length of bitfield        */
    __u32 msb_right;        /* != 0 : Most significant bit is */
                    /* right */
};


即标明R,G,B三个分量和透明通道分量数据在Pixel数据如何排列的问题。
offset是以起始点的偏移量,lenght是其长度。MSB即最高有效位所在方向,msg_right 为 1表示从左边算起, 为0表示从左边算起.(注:MSB在左边,实际上是小端字节序要求)

我们可以用ioctl接口来读相关参数实测一下。
  
24bpp
   
red length 8,offset 16 msb_right 0
green length 8,offset 8 msb_right 0
 blue length 8,offset 0 msb_right 0 
可以看到24bpp占用3个byte,并且是按 8:8:8的排列顺序,最高位有一个byte用于对齐,BPP是4个byte


16bpp
  
red length 5,offset 11 msb_right 0
green length 6,offset 5 msb_right 0
 blue length 5,offset 0 msb_right 0

可以看到16bpp占用两个byte,并且是按 5:6:5的排列顺序,注意从offset可以明显看到,蓝色在最前面

18bpp
   
red length 6,offset 12 msb_right 0
        green length 6,offset 6 msb_right 0
        blue length 6,offset 0 msb_right 0
        transp length 0,offset 0 msb_right 0

18bpp是按 6:6:6的排列,并且大约14bit的空间只用于占位。一个点占用4byte空间


软件操作显存
   软件可以把mmap映射的空间看成是一个二维数组来操作,绘制图像相当于操作显存相应的点的数据。
在16bpp下,一个显存相当是一个unsigned short的二维数组,而18bpp,24bpp相当于是unsigned long的二维数组。从编程的角度,用整数去操作更为简单。

  用整数操作就牵涉到字节序问题了,因为显存对于物理编移量有要求,因此用数字来表示颜色要保存值正好是放在对应分量位置上。

  以24bpp为例,在小端字节序下,正好是一一对应的,一个数字的即数字高位正好在内存的MSB这一侧。这样,fb_bitfield.offset正好是数字的偏移量。而且大端字节序正好相反。

 以红色为例,24bpp 最大值为0xFF,这样在小端字节序下,红点的数据是 0x00FF0000,(大端字节序是0x0000FF00)

  为了简化,我设计小端字节序三个宏.
  #define RGB_16BPP_565(r,g,b)  (((r & 0x1F)>>11) | ((g & 0x3F)>>5) | ((b & 0x1F)))
#define RGB_24_888(r,g,b)  (  ((r & 0xff)<<16) | ((g & 0xff ) << 8) | ((b & 0xff) << 0) )
#define RGB_18_666(r,g,b)  (  ((r & 0x3f)<<16) | ((g & 0x3f ) << 8) | ((b & 0x3f) << 0) )

把r,g,b三个分量传入即可得出相应值

以下是三种bpp的全屏绘制函数


#define RGB_18_666(r,g,b) ( ((r & 0x3f)<<16) | ((g & 0x3f ) << 8) | ((b & 0x3f) << 0) )

int fill_screen_18bpp(unsigned char * fb_buf,RGB_PIXEL *pp,struct fb_var_screeninfo * pvar)
{
  unsigned int x,y;
  unsigned long * p = (unsigned long *)fb_buf;

  if(pvar->bits_per_pixel != 18)
      return -1;
  
// for(x=0; x
//     for(y=0; y
       for(x=0; x<pvar->xres*pvar->yres;x++)
           {
            *p = RGB_18_666(pp->red,pp->green,pp->blue);
         p++;
           }

    return 0;
}
#define RGB_16_565(r,g,b) ( ((r & 0x1f)<<11) | ((g & 0x3f ) << 6) | ((b & 0x1f) << 0) )
int fill_screen_16bpp(unsigned char * fb_buf,RGB_PIXEL *pp,struct fb_var_screeninfo * pvar)
{
  unsigned int x,y;
  unsigned short * p = (unsigned short *)fb_buf;

  if(pvar->bits_per_pixel != 16)
      return -1;
  
// for(x=0; x
//     for(y=0; y
       for(x=0; x<pvar->xres*pvar->yres;x++)
           {
            *p = RGB_16_565(pp->red,pp->green,pp->blue);
         p++;
           }

    return 0;
}

//msb_right =0 表示最左边,左边16位,按小端字节序正好反过来

#define RGB_24_888(r,g,b) ( ((r & 0xff)<<16) | ((g & 0xff ) << 8) | ((b & 0xff) << 0) )
int fill_screen_24bpp(unsigned char * fb_buf,RGB_PIXEL *pp,struct fb_var_screeninfo * pvar)
{
  unsigned int x,y;
  unsigned long * p = (unsigned long *)fb_buf;

// if(pvar->bits_per_pixel != 24)

//     return -1;

  
  printf("%s:show red %d green %d blue %d \n",__FUNCTION__,pp->red,pp->green,pp->blue);
  
       for(x=0; x<pvar->xres*pvar->yres;x++)
           {
            *p = RGB_24_888(pp->red,pp->green,pp->blue);
         p++;
           }

    return 0;

}

文件:test_fb.zip
大小:1KB
下载:下载
阅读(1453) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~