linux之framebuffer(1)
kernel版本:linux-4.19
1. 重要的即几个结构体
(a) struct fb_fix_screeninfo
(b) struct fb_var_screeninfo
头文件: <linux/fb.h>
源文件:drivers/video/fbmem.c
1. struct 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 类似ypanstep,当其显示到底部时,能回到显存的开始处进行显示 */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O 显存映射I/O首地址 */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O 显存映射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 */
};
2. struct fb_var_screeninfo
struct fb_var_screeninfo {
__u32 xres; /* visible resolution 可见分辨率宽度 */
__u32 yres; //可见分辨率高度
__u32 xres_virtual; /* virtual resolution 虚拟屏幕宽 */
__u32 yres_virtual; //虚拟屏幕高度
__u32 xoffset; /* offset from virtual to visible 从虚拟到可见偏移值x */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what 每个像素所占的比特位 */
__u32 grayscale; /* 0 = color, 1 = grayscale, 灰度级(默认0,彩色) */
/* >1 = FOURCC */
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 透明度 */
__u32 nonstd; /* != 0 Non standard pixel format 是否为标准像素格式(0:标准 非0:非标准) */
__u32 activate; /* see FB_ACTIVATE_* 设置生效的时刻 默认FB_ACTIVATE_NOW,立刻生效 */
__u32 height; /* height of picture in mm 屏幕高 */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags 加速标志 */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) 显示一个点需要的时间(像素时钟皮秒) */
__u32 left_margin; /* time from sync to picture 左消隐区 */
__u32 right_margin; /* time from picture to sync 右消隐区 */
__u32 upper_margin; /* time from sync to picture 上消隐区 */
__u32 lower_margin; //下消隐区
__u32 hsync_len; /* length of horizontal sync 水平同步长*/
__u32 vsync_len; /* length of vertical sync 垂直同步长*/
__u32 sync; /* see FB_SYNC_* 同步信号方式 */
__u32 vmode; /* see FB_VMODE_* 扫描模式 */
__u32 rotate; /* angle we rotate counter clockwise 顺时针旋转的角度 */
__u32 colorspace; /* colorspace for FOURCC-based modes 基于FOURCC模式的颜色空间 */
__u32 reserved[4]; /* Reserved for future compatibility */
};
struct fb_bitfield {
__u32 offset; /* beginning of bitfield 颜色分类起始比特位 */
__u32 length; /* length of bitfield 颜色分类所占比特长度 */
__u32 msb_right; /* != 0 : Most significant bit is 右边的比特是否为最高有效位 */
/* right */
};
在fbmem.c文件中, 初始化函数 fbmem_init 如下:
int __init fbmem_init(void)
{
//在/proc下创建名为fb的文件;
proc_create("fb",0, NULL, &fb_proc_fops);
//注册字符设备
register_chrdev(FB_MAJOR, "fb", &fb_fops);
//在/sys/class/下创建graphics
fb_class = class_create(THIS_MODULE, "graphics");
}
其中fb_fops 内容如下:
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = fb_compat_ioctl,
#endif
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync = fb_deferred_io_fsync,
#endif
.llseek = default_llseek,
};
其中 fb_ioctl 函数为应用层ioctl调用提供接口;
2. ioctl函数
1. 获取屏幕可变信息
int ioctl(int fd, FBIOGET_VSCREENINFO, struct fb_var_screeninfo *var);
主要包括分辨率和像素格式等;
2. 设置屏幕可变信息
int ioctl(int fd, FBIOPUT_VSCREENINFO, struct fb_var_screeninfo *var);
3. 获取屏幕固定信息
int ioctl(int fd, FBIOGET_FSCREENINFO, struct fb_fix_screeninfo *fix);
获取FrameBuffer固定信息,包括显存起始物理地址,显存大小和行间距等;
4. 设置PAN显示
int ioctl(int fd, FBIOPAN_DISPLAY, struct fb_var_screeninfo *var);
设置从虚拟分辨率中的不同偏移处开始显示;
其中xres_virtual,yres_virtual为虚拟分辨率, xres,yres为实际显示分辨率,xoffset,yoffset为显示的偏移量;
注:必须保证实际分辨率与偏移量和在虚拟分辨率范围内,否则设置不成功;另最好保证xoffset与yoffset形成的偏移地址是16byte对齐的;
代码示例:
//以下参数表示ARGB1555,A占1bit,RGB各占用5位,共16bit;
struct fb_bitfield r16 = {10, 5, 0}; //bit10~bit14
struct fb_bitfield g16 = {5, 5, 0}; //bit5~bit9
struct fb_bitfield b16 = {0, 5, 0}; //bit0~bit4
struct fb_bitfield b16 = {15, 1, 0};//bit15
struct fb_var_screeninfo vinfo;
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0){
return -1;
}
//虚拟分辨率等于实际显示分辨率;
vinfo.xres_virtual = 1280;
vinfo.yres_virtual = 960;
vinfo.xres = 1280;
vinfo.yres = 960;
vinfo.activate = FB_ACTIVATE_NOW;//设置后立即生效
vinfo.bits_per_pixel = 16;
vinfo.xoffset = 0;
vinfo.yoffset = 0;
vinfo.red = r16;
vinfo.green = g16;
vinfo.blue = b16;
vinfo.transp = a16;
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0){
return -1;
}
....
//偏移到320,160处;
vinfo.xoffset = 320;
vinfo.yoffset = 160;
if (ioctl(fd, FBIOPAN_DISPLAY, &vinfo) < 0){
return -1;
}