概述
帧缓冲(framebuffer)设备应用于linux显示技术方面。因为linux的显示平台已经全部基于framebuffer,所以目前在linux环境下开发图形化界面、游戏、影视软件等可视化应用时都必须用到帧缓冲技术,而现在随着消费逐渐娱乐化的大趋势,可视化应用已经在产品开发中越来越重要,因此,对于帧缓冲技术的理解和掌握就非常重要了。
1 Frambuffer介绍
帧缓冲在linux体系中居于上层应用和底层显示设备之间,如下图所示。它的设计意图是对上层应用屏蔽掉低层不同硬件的操作细节:对于不同厂家不同类型的显示硬件,由于各自厂商在技术上扬长避短的需要,所以在具体的细节比如寄存器数量和种类的设计上就会存在相当大的差异,而且对于各个寄存器的初始化的定义和引脚信号的定义也不近相同,这样即便是两种性能相近的产品,例如夏普3.5寸LCD模块与三星的3.5寸模块其操作细节也截然不同。如果让擅长于开发图形界面的开发人员费尽心思去琢磨属于硬件范畴的液晶模块寄存器写入时序问题,无疑是很大的浪费。因此,需要在上层开发和底层设备之间加入一个中间层以节省开发人员的时间和精力。
2 Frambuffer显示原理
帧缓冲类似一个蓄水池,存放来自用户进程的数据,然后把这些数据再输入显示设备中。对于用户而言,帧缓冲就是内存中的一块区域,可以读、写、映射。只要在初始化阶段把显示设备映射到用户进程空间,可以理解为将屏幕中的每一点和帧缓冲的每一点一一对应起来。这样接下来就可以对这块内存区域填充任何已经定义的像素以及颜色,而屏幕也就可以根据刚才写入的像素及颜色呈现出五彩缤纷的画面。
3 2.6.25内核Frambuffer相关的数据结构
相关的数据结构从运行环境可以分为用户空间和内核空间两类。在用户空间内使用的数据结构主要有fb_fix_screeninfo和fb_var_screeninfo。在内核空间使用的主要数据结构为fb_info。
首先介绍fb_fix_screeninfo,该数据结构定义了一些系统运行期间不能改变的信息,例如设备名,屏幕的像素数量,缓冲区的首址和长度等。这类信息一般通过ioctl函数获得。下面列出了fb_fix_screeninfo 的主要内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
struct
fb_fix_screeninfo {
char
id[16];
/* 设备名*/
unsigned
long
smem_start;
/* frame buffer 缓冲区起始地址(物理地址)*/
__u32 smem_len;
/* 缓冲区长度*/
__u32 type;
/* 设备类型,例如TFT或STN*/
……
__u32 visual;
/* 色彩类型,真彩色、假彩色或单色*/
……
__u32 line_length;
/* 屏幕上每行的字节数 */
unsigned
long
mmio_start;
/* IO映射区起始地址(物理地址) */
__u32 mmio_len;
/* IO 映射区长度 */
__u32 accel;
/* 指出使用的加速卡是哪些特定的芯片 */
__u16 reserved[3];
/* 系统保留*/
};
|
相对应的,fb_var_screeninfo定义了一些在系统运行期间可以改变的信息。例如像素深度、灰度级、颜色格式、时序,屏幕边缘空白区等。下表中列出了fb_var_screeninfo的主要内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
struct
fb_var_screeninfo {
__u32 xres;
/* visible resolution 可见分辨率 */
__u32 yres;
__u32 xres_virtual;
/* virtual resolution 虚拟分辨率 */
__u32 yres_virtual;
__u32 xoffset;
/* 从虚拟分辨率到可见分辨率的偏移量*/
__u32 yoffset;
__u32 bits_per_pixel;
/* 像素深度 */
__u32 grayscale;
/* 灰度级 */
struct
fb_bitfield red;
struct
fb_bitfield green;
struct
fb_bitfield blue;
struct
fb_bitfield transp;
/* 透明度 */
__u32 nonstd;
/* 非标准像素格式 */
……
__u32 pixclock;
/* 像素时钟,单位是皮秒*/
__u32 left_margin;
/* 左侧边缘区*/
__u32 right_margin;
/*右侧边缘区 */
__u32 upper_margin;
/*顶部边缘区 */
__u32 lower_margin;
__u32 hsync_len;
/*水平扫描边缘区 */
__u32 vsync_len;
/*垂直扫描边缘区 */
…….
};
|
下图标出了各种边缘区在整个屏幕上的位置。
内核级Fb_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
struct
fb_info {
int
node;
/* 设备节点 */
int
flags;
struct
fb_var_screeninfo var;
/* 当前可变参数 */
struct
fb_fix_screeninfo fix;
/* 当前固定参数 */
struct
fb_monspecs monspecs;
/* 当前监视器特征 */
struct
work_struct queue;
/* 帧缓冲事件队列 */
struct
fb_pixmap pixmap;
/* 图象硬件映射变量 */
struct
fb_pixmap sprite;
/* 光标硬件映射变量 */
struct
fb_cmap cmap;
/* 当前颜色映射变量 */
struct
list_head modelist;
/* 模式列表*/
struct
fb_videomode *mode;
/* 当前模式*/
......
struct
fb_ops *fbops;
/* 该指针指向驱动函数集 */
……
struct
device *dev;
/* 代表此帧缓冲设备 */
……
char
__iomem *screen_base;
/* IO映射基址(虚地址) */
unsigned
long
screen_size;
/* Amount of ioremapped VRAM or 0 */
void
*pseudo_palette;
/* 调色板内存地址 */
……
};
|
fb_info是显示驱动工作的主要载体,它定义了当前显示驱动和控制台有关的全部信息。显示驱动的实现形式就是先初始化fb_info各项,用来设置LCD控制器。以后大部分工作是:应用层通过ioctl系统调用fb_ops中的函数,来获得或修改fix、var变量中值,再写到寄存器中;或修改调色板等操作。如果在应用层中将要显示的两帧图像使用的调色板不同,就由fb_ops中的函数实现,后者获得调色板在内存的地址,修改其中的像素值来实现。
Fb_ops里面的函数指针很多,这些函数指针所指向的一般是各个硬件显卡自带的底层驱动函数,如果读者要自己开发一种专门的显卡,在fb_ops这个结构里必然要用指针把这种显卡专用的那些函数列出来。我们这里只简单介绍其中两个函数指针:
1
|
int
(*fb_check_var)(
struct
fb_var_screeninfo *var,
struct
fb_info *info);
|
此指针指向的函数是用来检查前面提到的可变显示参数的,例如像素深度、边缘区宽度或深度等。注意这里的不会修改参数。
1
|
int
(*fb_set_par)(
struct
fb_info *info);
|
此处所指的函数就可以对显示参数作出实质性的修改了。
4 Frambuffer驱动实现框架
这里我们不再重复大家已经比较熟悉的驱动程序注册和注销两个过程。我们以fbmem.c中的几个重要函数为对象,解释一下在注册之后到注销之前帧缓冲驱动的大致步骤。之所以选择fbmem.c中的函数,还是因为这个文件中的函数具有一定的代表性,读者在了解它们的大致结构之后,就可以举一反三,来分析和理解其它具体显卡的驱动程序了。
这几个函数分别是fb_mmap,fb_set_var和 fb_ioctl。
Fb_mmap顾名思义其任务是完成设备到系统内存(虚拟地址)之间的映射。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
static
int
fb_mmap(
struct
file *file,
struct
vm_area_struct * vma)
{
int
fbidx = iminor(file->f_path.dentry->d_inode);
struct
fb_info *info = registered_fb[fbidx];
struct
fb_ops *fb = info->fbops;
unsigned
long
off;
unsigned
long
start;
u32 len;
if
(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return
-EINVAL;
off = vma->vm_pgoff << PAGE_SHIFT;
if
(!fb)
return
-ENODEV;
if
(fb->fb_mmap) {
//意思是:如果驱动程序自带了mmap函数,那就用它自己的
int
res;
lock_kernel();
//上大内核锁
res = fb->fb_mmap(info, vma);
//调用驱动程序自己的mmap函数
unlock_kernel();
return
res;
}
lock_kernel();
start = info->fix.smem_start;
//注意,这里指向了设备的物理地址
len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
//调整对齐后长度
if
(off >= len) {
/* 对应于I/O端口统一编址的情况 */
off -= len;
if
(info->var.accel_flags) {
unlock_kernel();
return
-EINVAL;
}
start = info->fix.mmio_start;
//当I/O端口统一编址时就使用端口的物理地址
len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
}
unlock_kernel();
start &= PAGE_MASK;
if
((vma->vm_end - vma->vm_start + off) > len)
//判断虚拟内存长度是否超越实际长度
return
-EINVAL;
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
/* 本内存页作为IO之用,已经保留 */
vma->vm_flags |= VM_IO | VM_RESERVED;
fb_pgprotect(file, vma, off);
//对帧缓冲的内存页进行标识,不要挪作它用
if
(io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
//实际的映射操作
return
-EAGAIN;
return
0;
}
|
这里的映射行为发生在驱动程序初始化阶段。请注意,这些行为是否被囊括在一个名为mmap的函数中并不是问题的关键,我们在开发中真正应该关心的是映射所需要的前提条件如设备物理地址的提取,映射长度的确认以及实际的映射操作。只要在驱动程序的初始化中完成了上述动作,那就算是成功了。因此,不少显卡的驱动程序里是找不到mmap这个函数的,但它们一样工作得很好,原因就是它们已经完成了实际的映射操作。
下面我们看看fb_set_var函数。它主要完成了显示模式、可变参数的设置。Fb_set_var这样的函数在不同的显示驱动中的具体名称也不一样,但基本上的功能都是完成对于模式和可变参数的控制。某些系统的驱动里fb_set_var是不含fb_check_var这样的函数的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
int
fb_set_var(
struct
fb_info *info,
struct
fb_var_screeninfo *var)
{
int
flags = info->flags;
int
ret = 0;
…….
if
(!info->fbops->fb_check_var) {
*var = info->var;
goto
done;
}
ret = info->fbops->fb_check_var(var, info);
//在这里对设备的诸多参数进行检查
if
(ret)
goto
done;
if
((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
struct
fb_videomode mode;
……
info->var = *var;
if
(info->fbops->fb_set_par)
//如果驱动程序自带fb_set_par函数就使用它
info->fbops->fb_set_par(info);
//这个函数设置例如控制寄存器等可变参数
fb_pan_display(info, &info->var);
//硬件虚拟显示
fb_set_cmap(&info->cmap, info);
//调色板设置
fb_var_to_videomode(&mode, &info->var);
//把可变参数转为显示模式参数
......
}
}
}
done:
return
ret;
}
|
Fb_ioctl函数汇集了很多的功能,包括从内核读取显示设备参数(可变的和固定的都有),设置参数(就是调用上面提到的fb_set_var函数)。这些功能一般没有什么分类方面的限制,开发人员可以把各种自己实现的功能都一古脑放进fb_ioctl中。而且,开发人员也完全可以抛开系统提供的这个fb_ioctl转而实现自己的fb_ioctl。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
static
int
fb_ioctl(
struct
inode *inode,
struct
file *file, unsigned
int
cmd,
unsigned
long
arg)
{
int
fbidx = iminor(inode);
struct
fb_info *info = registered_fb[fbidx];
//设备
struct
fb_ops *fb = info->fbops;
//设备函数指针
struct
fb_var_screeninfo var;
//可变参数
struct
fb_fix_screeninfo fix;
//固定参数
struct
fb_con2fbmap con2fb;
struct
fb_cmap_user cmap;
//调色板
struct
fb_event event;
void
__user *argp = (
void
__user *)arg;
int
i;
if
(!fb)
return
-ENODEV;
switch
(cmd) {
case
FBIOGET_VSCREENINFO:
return
copy_to_user(argp, &info->var,
sizeof
(var)) ? -EFAULT : 0;
//这里是读取可变参数
case
FBIOPUT_VSCREENINFO:
if
(copy_from_user(&var, argp,
sizeof
(var)))
return
-EFAULT;
//尝试是否可以设置参数?
acquire_console_sem();
//控制台上锁
info->flags |= FBINFO_MISC_USEREVENT;
i = fb_set_var(info, &var);
//设置可变参数
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
//解锁
if
(i)
return
i;
if
(copy_to_user(argp, &var,
sizeof
(var)))
return
-EFAULT;
return
0;
case
FBIOGET_FSCREENINFO:
return
copy_to_user(argp, &info->fix,
//读取固定参数
sizeof
(fix)) ? -EFAULT : 0;
case
FBIOPUTCMAP:
//设置调色板参数
if
(copy_from_user(&cmap, argp,
sizeof
(cmap)))
return
-EFAULT;
return
(fb_set_user_cmap(&cmap, info));
……
case
FBIOBLANK:
acquire_console_sem();
info->flags |= FBINFO_MISC_USEREVENT;
i = fb_blank(info, arg);
//关闭显示器
info->flags &= ~FBINFO_MISC_USEREVENT;
release_console_sem();
return
i;
default
:
if
(fb->fb_ioctl == NULL)
//如果存在自定义的fb_ioctl就使用它
return
-EINVAL;
return
fb->fb_ioctl(info, cmd, arg);
}
}
|
从上面的叙述过程中可以看到,对于帧缓冲驱动程序,尽管不同的显示设备可能有不同的特定功能,但是在向内核注册了驱动程序后运行的共同点都是要先进行物理设备与虚拟内存之间的映射(fb_mmap);在操作设备的过程中,fb_set_var由于可以对于设备的运行参数进行控制因而尤为重要。类似的设备参数读写函数还有fb_check_var等,这些函数一般会被包含在fb_ioctl 函数中并被调用。而上述参数的操作对象就是我们在上一节中已经介绍的 fb_info,fb_fix_screeninfo ,fb_var_screeninfo 等数据结构。
原文来自博客:http://bbs.csdn.net/topics/350121977
帧缓冲FrameBuffer相关知识补充:
1、framebuffer 帧缓冲
帧缓冲(framebuffer)是Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
framebuffer机制模仿显卡的功能,将显卡硬件结构抽象为一系列的数据结构,可以通过framebuffer的读写直接对显存进行操作。用户可以将framebuffer看成是显存的一个映像,将其映射到进程空间后,就可以直接进行读写操作,写操作会直接反映在屏幕上。
framebuffer是个字符设备,主设备号为29,对应于/dev/fb%d 设备文件。
通常,使用如下方式(前面的数字表示次设备号)
0 = /dev/fb0 第一个fb 设备
1 = /dev/fb1 第二个fb 设备
fb 也是一种普通的内存设备,可以读写其内容。例如,屏幕抓屏:cp /dev/fb0 myfilefb 虽然可以像内存设备(/dev/mem)一样,对其read,write,seek 以及mmap。但区别在于fb 使用的不是整个内存区,而是显存部分。
2、fb与应用程序的交互
对于用户程序而言,它和其他的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。fb的显示缓冲区位于内核空间,应用程序可以把此空间映射到自己的用户空间,在进行操作。
在应用程序中,操作/dev/fbn的一般步骤如下:
(1)打开/dev/fbn设备文件。
(2)用ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每
个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。
(3)用mmap()函数,将屏幕缓冲区映射到用户空间。
(4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。
3、fb的结构及其相关结构体
在linux中,fb设备驱动的源码主要在Fb.h (linux2.6.28includelinux)和Fbmem.c (linux2.6.28driversvideo)两个文件中,它们是fb设备驱动的中间层,为上层提供系统调用,为底层驱动提供接口。
在fb.h文件中有fb驱动需要使用的很多结构,我们先对这些结构体进行说明:
(1)、
一个帧缓冲区对应一个struct fb_info结构,它包括了帧缓冲设备的属性和操作的完整集合,每个帧设备都有一个fb_info结构体。源码如下:
struct fb_info {
int node;
int flags;
struct mutex lock;/* Lock for open/release/ioctl funcs */互斥锁
struct fb_var_screeninfo var;/* Current var */当前缓冲区的可变参数
struct fb_fix_screeninfo fix;/* Current fix */固定参数
struct fb_monspecs monspecs;/* Current Monitor specs */当前显示器标志
struct work_struct queue;/* Framebuffer event queue */帧缓冲事件队列
struct fb_pixmap pixmap;/* Image hardware mapper */图像硬件mapper
struct fb_pixmap sprite;/* Cursor hardware mapper */光标硬件mapper
struct fb_cmap cmap;/* Current cmap */当前的调色板
struct list_head modelist; /* mode list */
struct fb_videomode *mode;/* current mode */当前的视频模式
#ifdef CONFIG_FB_BACKLIGHT如果配置了LCD支持背光灯
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */背光调整
struct backlight_device *bl_dev;
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
struct fb_ops *fbops;帧缓冲操作函数集
struct device *device;/* This is the parent */父设备
struct device *dev;/* This is this fb device */fb设备
int class_flag; /* private sysfs flags */私有的sysfs标志
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */图块blitting
#endif
char __iomem *screen_base;/* Virtual address */虚拟基地址
unsigned long screen_size;/* Amount of ioremapped VRAM or 0 */ ioremap的虚拟内存大小
void *pseudo_palette;/* Fake palette of 16 colors */ 伪16位调色板
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */硬件的状态
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
};
(2)、
/*
* Frame buffer operations
*
* LOCKING NOTE: those functions must _ALL_ be called with the console
* semaphore held, this is the only suitable locking mechanism we have
* in 2.6. Some may be called at interrupt time at this point though.
*/
fb_ops结构体用来实现对帧缓冲设备的操作,这些函数需要驱动开发人员编写,
struct fb_ops {
/* open/release and usage marking */
struct module *owner;
打开和释放
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
这两个函数对于非线性布局的/常规内存映射无法工作的帧缓冲设备需要
/* For framebuffers with strange non linear layouts or that do not
* work with normal memory mapped access
*/
ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos);
ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos);
检测可变参数,并调整到支持的值
/* checks var and eventually tweaks it to something supported,
* DO NOT MODIFY PAR */
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
设置视频模式
/* set the video mode according to info->var */
int (*fb_set_par)(struct fb_info *info);
设置color寄存器的值
/* set color register */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
批量设置color寄存器,设置颜色表
/* set color registers in batch */
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
显示空白
/* blank display */
int (*fb_blank)(int blank, struct fb_info *info);
pan显示
/* pan display */
int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
填充矩形
/* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
数据复制
/* Copy data from area to another */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
图形填充
/* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
绘制光标
/* Draws cursor */
int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
旋转显示
/* Rotates the display */
void (*fb_rotate)(struct fb_info *info, int angle);
等待blit空闲
/* wait for blit idle, optional */
int (*fb_sync)(struct fb_info *info);
fb特定的ioctl操作
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
unsigned long arg);
处理32兼容的ioctl操作
/* Handle 32bit compat ioctl (optional) */
int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
unsigned long arg);
fb特定的mmap操作
/* perform fb specific mmap */
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
保存目前的硬件状态
/* save current hardware state */
void (*fb_save_state)(struct fb_info *info);
恢复被保存的硬件状态
/* restore saved state */
void (*fb_restore_state)(struct fb_info *info);
通过fb_info获得framebuffer的能力
/* get capability given var */
void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
struct fb_var_screeninfo *var);
};
(3)、
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) */
fb缓存的开始位置
__u32 smem_len;/* Length of frame buffer mem */
fb缓存的长度
__u32 type; /* see FB_TYPE_* */
FB_TYPE_*类型
__u32 type_aux;/* Interleave for interleaved Planes */
分界
__u32 visual; /* see FB_VISUAL_* */
屏幕使用的色彩模式
__u16 xpanstep;/* zero if no hardware panning */
如果没有硬件panning ,赋0
__u16 ypanstep;/* zero if no hardware panning */
__u16 ywrapstep;/* zero if no hardware ywrap */
1行的字节数
__u32 line_length;/* length of a line in bytes */
内存映射I/O的开始位置
unsigned long mmio_start;/* Start of Memory Mapped I/O */
/* (physical address) */
内存映射I/O的长度
__u32 mmio_len;/* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have*/
__u16 reserved[3];/* Reserved for future compatibility */
};
(4)、
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 */
__u32 yoffset;/* resolution */
虚拟到可见之间的偏移
__u32 bits_per_pixel;/* guess what */
每像素位数,BPP
__u32 grayscale;/* != 0 Graylevels instead of colors */
非0时指灰度
struct fb_bitfield red;/* bitfield in fb mem if true color, */
struct fb_bitfield green;/* else only length is significant */
struct fb_bitfield blue;
fb缓存的RGB位域
struct fb_bitfield transp;/* transparency */
透明度
__u32 nonstd; /* != 0 Non standard pixel format */
!= 0 非标准像素格式
__u32 activate;/* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
屏幕的高度
__u32 width; /* width of picture in mm */
屏幕的宽度
__u32 accel_flags;/* (OBSOLETE) see fb_info.flags */
fb_info的标志
/* 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 reserved[5];/* Reserved for future compatibility */
};
(5)、
fb_cmap结构体中记录了颜色板信息,即调色板信息。,用户空间可以通过ioctl()的FBIOGETCMAP和 FBIOPUTCMAP命令读取或设定颜色表。
struct fb_cmap {
__u32 start; /* First entry */第一个元素的入口
__u32 len; /* Number of entries */元素个数
__u16 *red; /* Red values */红色、绿色、蓝色
__u16 *green;
__u16 *blue;
__u16 *transp;/* transparency, can be NULL */透明度
};
上面这些结构体之间有什么关系呢?看下图:
(6)、
fb_bitfield 结构体描述每一像素显示缓冲区的组织方式,包含位域偏移、位域长度和MSB 指示,
struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
位域偏移
__u32 length; /* length of bitfield */
位域长度
__u32 msb_right;/* != 0 : Most significant bit is */
/* right */
MSB
};
本部分转子博客:http://www.linuxidc.com/Linux/2012-05/61024.htm
最后
以上就是高挑火车为你收集整理的Linux-2.6.25内核帧缓冲设备驱动分析的全部内容,希望文章能够帮你解决Linux-2.6.25内核帧缓冲设备驱动分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复