1.ramebuffer基础知识
Linux2.2以上的版本中使用了framebuffer技术,这使得用户对显示设备进行写入、控制时可以避免对内存映射区进行操作,因此用户可以在不了解底层图形硬件或没有使用过X Window的情况下进行图形程序的开发。framebuffer是一种驱动程序接口,用户需要编译内核来实现对framebuffer的支持。framebuffer的设备为/dev/fb0、/dev/fb1等。对Linux来讲周边都被视为一种文件设备来代表,放在/dev目录下,fb表示一种周边代号。
应用程序通过使用mmap()系统调用将显存映射到用户空间来实现对显存的直接操作。使用framebuffer主要会用到下面几个内核空间中的文件:(以RedHat9.0为例)
/usr/src/linux-2.4.20-8/include/linux/fb.h
/usr/src/linux-2.4.20-8/drivers/video/fbmem.c
/usr/src/linux-2.4.20-8/drivers/video/fbcmap.c
在fb.h中定义了几个重要的结构体,fb_info 、fb_fix_screeninfo、fb_var_screeninfo、fb_cmap等。在fbmem.c中则定义了对framebuffer的操作部分,诸如fb_read、fb_write、fb_ioctl、fb_mmap、fb_open、fb_release等,同时还在其中定义了一个fb_fops结构来实现这些操作:
static struct file_operations fb_fops = {
owner: THIS_MODULE,
read: fb_read,
write: fb_write,
ioctl: fb_ioctl,
mmap: fb_mmap,
open: fb_open,
release: fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
get_unmapped_area: get_fb_unmapped_area,
#endif
};
有关函数的具体定义可以参考阅读fbmem.c文件。fbcmap.c文件实现了对colormap的处理,其中包括如fb_alloc_cmap等函数。
下面我们来通过一个简单的例子来加深对framebuffer的理解,我们可以通过ioctl函数
来获得framebuffer的信息。
if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_vinfo))
{
printf("Can't get VSCREENINFO: %s\n"strerror(errno));
close(fb);
return -1;
}
if (ioctl(fb, FBIOGET_FSCREENINFO, &fb_finfo))
{
printf("Can't get FSCREENINFO: %s\n", strerror(errno));
return 1;
}
fbdev.fb_bpp = fb_vinfo.red.length + fb_vinfo.green.length
+ fb_vinfo.blue.length + fb_vinfo.transp.length;
fbdev.fb_width = fb_vinfo.xres;
fbdev.fb_height = fb_vinfo.yres;
fbdev.fb_line_len = fb_finfo.line_length;
fbdev.fb_size = fb_finfo.smem_len;
printf("frame buffer: %dx%d, %dbpp, 0x%xbyte\n", fbdev.fb_width, fbdev.fb_height, fbdev.fb_bpp, fbdev.fb_size);
在上面的代码中通过ioctl得到了framebuffer设备的分辨率、色深和显存大小,当然我们还可以得到其它信息。接下来使用mmap()调用,实现显示缓冲到用户空间。
fbdev.fb_mem=mmap(NULL,fbdev.fb_size,PROT_READ|PROT_WRITE,MAP_SHARED,
fb,0);
if(fbdev.fb_mem==NULL || (int)fbdev.fb_mem==-1)
{
fbdev.fb_mem=NULL;
printf("mmap failed\n");
close(fb);
return -1;
}
memset (fbdev.fb_mem, 0x0, fbdev.fb_size);
上面的fbdev.fb_mem是映射到用户空间的显存的起始地址,关于mmap和memset的详细使用可以使用man来查看手册。
对于bpp(色深)为8位或8位以下的设备,在进行绘图前需要对调色板进行设置,有关调色板的结构fb_cmap的结构定义在fb.h中,有关调色板的设置需要修改fbcmap.c。