首页 > 程序开发 > 移动开发 > 其他 >

linux驱动之显示子系统

2017-03-04

linux驱动之显示子系统:显示子系统对应用层提供的接口叫做framebuffer,一般位于 dev fb0(下文示例运行于adroid的平台位于 dev graphics fb0,不过它们都是一样的),它为上层提供了统一的对显卡的描述。

linux驱动之显示子系统显示子系统对应用层提供的接口叫做framebuffer,一般位于/dev/fb0(下文示例运行于adroid的平台位于/dev/graphics/fb0,不过它们都是一样的),它为上层提供了统一的对显卡的描述。

首先要明确的是lcd显示子系统虽然复杂,但其任然是基本的字符设备,fb0就是其设备节点,主设备号29。不同之处在于,可以通过mmap(mmap将一个文件或者其它对象映射进内存。)

对其进行地址映射,将内核中的显存空间直接映射到用户空间,这样用户空间填入需要显示的数据就能直接显示在lcd上。其余的参数查询与设置通过ioctl都可以完成。

我们先从第一个应用层测试开始讲起:

1, 保持屏幕上有一帧画面,进入fb0对应的目录(/dev/ 或/dev/graphics/)执行:

cat fb0 > fb_test

这样就可以对framebuffer的一帧原始数据进行暂存

2, 切换一帧屏幕画面,执行

cat fb_test > fb0

可以看到之前暂存的一帧画面重新出现了。adroid有自身的刷新频率,所以我们刷入的一帧画面会很快被覆盖,看到的现象可能是一闪即逝。

从上面的测试我们理解了fb0的基本作用,下面我们写一个测试程序画一个自己的图形:

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
   int fbfd=0;//framebuffer 文件句柄
   struct fb_var_screeninfo vinfo;
   unsigned long screen_size=0;
   char *fbp=0;//framebuffer 在用户空间映射的虚拟地址指针
   int x=0,y=0,i=0;

   fbfd=open("/dev/graphics/fb0",O_RDWR);  //打开framebuffer 文件节点
   if(!fbfd){
		  printf("error\n");
		  exit(1);
   }

   if(ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo)){  //获取屏幕可变参数
		  printf("error\n");
		  exit(1);
   }

   //打印屏幕可变参数:x轴像素个数,y轴像素个数,每个像素点数
   printf("%dx%d,%dbpp\n",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
   screen_size=vinfo.xres*vinfo.yres*12;  //framebuffer大小
   fbp=(char *)mmap(0,screen_size,PROT_READ|PROT_WRITE,MAP_SHARED,fbfd,0);//映射
   if((int)fbp==-1){
		  printf("error\n");
		  exit(4);
   }

   for(i = 0; i < screen_size/2; i++)
   {
	   unsigned short rgb;
	   rgb=(31<<11)|(0<<5)|0;
	   *((unsigned short *)(fbp+i*2))=rgb;
   }

   munmap(fbp,screen_size);
   close(fbfd);
   return 0;
}

分析:

上述程序比较简洁,先打开了fb0节点,获取了相关参数,然后进行framebuffer地址映射。之后直接向framebuffer中写入数据,画面就会出现在屏幕上。

其中framebuffer的大小是从驱动程序中获知的,下一篇文章将会就驱动层展开分析。

framebuffer中数据格式有rgb565、rgb888,上面示例为rgb565。运行后全屏为红色。

相关文章
最新文章
热点推荐