文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>全面的framebuffer详解 -- 2

全面的framebuffer详解 -- 2

时间:2010-08-06  来源:fly123456789

二、FrameBuffer在Linux中的实现和机制

Framebuffer对应的源文件在linux/drivers/video/目录下。总的抽象设备文件为fbcon.c,在这个目录下还有与各种显卡驱动相关的源文件。   //这个文件要好好看看

 

(一)、分析Framebuffer设备驱动

    需要特别提出的是在INTEL平台上,老式的VESA 1.2 卡,如CGA/EGA卡,是不能支持Framebuffer的,因为Framebuffer要求显卡支持线性帧缓冲,即CPU可以访问显缓冲中的每一位,但是VESA 1.2 卡只能允 许CPU一次访问64K的地址空间。

FrameBuffer设备驱动基于如下两个文件:

1) linux/include/linux/fb.h

2) linux/drivers/video/fbmem.c

 

下面分析这两个文件。

1、fb.h

   几乎主要的结构都是在这个中文件定义的。这些结构包括:

1)fb_var_screeninfo

   这个结构描述了显示卡的特性:

NOTE::::   __u32 是表示 unsigned 不带符号的 32 bits 的数据 类型,其余类推。这是 Linux 内核中所用到的数据类型,如果是开发用户空间(user-space)的程序,可以根据具体计算机平台的情况,用 unsigned long 等等来 代替

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 resolution */ //可视区域的偏移

__u32 yoffset;

 

__u32 bits_per_pixel; /* guess what */  //每一象素的bit数

__u32 grayscale; /* != 0 Gray levels instead of colors *///等于零就成黑白

 

struct fb_bitfield red; /* bitfield in fb mem if true color, */真彩的bit机构

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 */ 不是标准格式

 

__u32 activate; /* see FB_ACTIVATE_* */

 

__u32 height; /* height of picture in mm */ 内存中的图像高度

__u32 width; /* width of picture in mm */ 内存中的图像宽度

 

__u32 accel_flags; /* acceleration flags (hints) */ 加速标志

 

/* 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 reserved[6]; /* Reserved for future compatibility */ 备用-以后开发

};

 

2) fb_fix_screeninfon

这个结构在显卡被设定模式后创建,它描述显示卡的属性,并且系统运行时不能被修改;比如FrameBuffer内存的起始地址。它依赖于被设定的模式,当一个模式被设定 后,内存信息由显示卡硬件给出,内存的位置等信息就不可以修改。

 

struct fb_fix_screeninfo {

char id[16]; /* identification string eg "TT Builtin" */ID

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 */

__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; /* Type of acceleration available */ 可用的加速类型

__u16 reserved[3]; /* Reserved for future compatibility */

};

 

3) fb_cmap

描述设备无关的颜色映射信息。可以通过FBIOGETCMAP 和 FBIOPUTCMAP 对应的ioctl操作设定或获取颜色映射信息.

 

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 */ 透明,可以为零

};

 

4) fb_info

定义当显卡的当前状态;fb_info结构仅在内核中可见,在这个结构中有一个fb_ops指针, 指向驱动设 备工作所需的函数集。

 

struct fb_info {

char modename[40]; /* default video mode */ 默认的视频卡类型

kdev_t node;

int flags;

int open; /* Has this been open already ? */ 被打开过么?

#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */

struct fb_var_screeninfo var; /* Current var */ 现在的视频信息

struct fb_fix_screeninfo fix; /* Current fix */ 修正的信息

struct fb_monspecs monspecs; /* Current Monitor specs */ 现在的显示器模式

struct fb_cmap cmap; /* Current cmap */ 当前优先级

struct fb_ops *fbops;

char *screen_base; /* Virtual address */ 物理基址

struct display *disp; /* initial display variable */初始化

struct vc_data *display_fg; /* Console visible on this display */

char fontname[40]; /* default font name */默认的字体

devfs_handle_t devfs_handle; /* Devfs handle for new name */

devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */兼容

int (*changevar)(int); /* tell console var has changed */ 告诉console变量修改了

int (*switch_con)(int, struct fb_info*);

/* tell fb to switch consoles */ 告诉fb选择consoles

int (*updatevar)(int, struct fb_info*);

/* tell fb to update the vars */ 告诉fb更新变量

void (*blank)(int, struct fb_info*); /* tell fb to (un)blank the screen */告诉fb使用黑白模式(或者不黑)

/* arg = 0: unblank */arg=0的时候黑白模式

/* arg > 0: VESA level (arg-1) */ arg>0时候选择VESA模式

void *pseudo_palette; /* Fake palette of 16 colors and

the cursor's color for non

palette mode */  修正调色板

/* From here on everything is device dependent */ 现在就可以使用了

void *par;

};

 

5) struct fb_ops

用户应用可以使用ioctl()系统调用来操作设备,这个结构就是用一支持ioctl()的这些操作的。

 

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);

/* get non settable parameters */

int (*fb_get_fix)(struct fb_fix_screeninfo *fix, int con,

struct fb_info *info);

/* get settable parameters */

int (*fb_get_var)(struct fb_var_screeninfo *var, int con,

struct fb_info *info);

/* set settable parameters */

int (*fb_set_var)(struct fb_var_screeninfo *var, int con,

struct fb_info *info);

/* get colormap */

int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con,

struct fb_info *info);

/* set colormap */

int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con,

struct fb_info *info);

/* pan display (optional) */

int (*fb_pan_display)(struct fb_var_screeninfo *var, int con,

struct fb_info *info);

/* perform fb specific ioctl (optional) */

int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,

unsigned long arg, int con, struct fb_info *info);

/* perform fb specific mmap */

int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);

/* switch to/from raster image mode */

int (*fb_rasterimg)(struct fb_info *info, int start);

};

 

6) structure map

struct fb_info_gen | struct fb_info | fb_var_screeninfo

                   |                | fb_fix_screeninfo

                   |                | fb_cmap

                   |                | modename[40]

                   |                | fb_ops ---|--->ops on var

                   |                | ...       | fb_open

                   |                |           | fb_release

                   |                |           | fb_ioctl

                   |                |           | fb_mmap

                   | struct fbgen_hwswitch 

 

                              \-----|-> detect

                                    | encode_fix

                                    | encode_var

                                    | decode_fix

                                    | decode_var

                                    | get_var

                                    | set_var

                                    | getcolreg

                                    | setcolreg

                                    | pan_display

                                    | blank

                                    | set_disp

 

 

[编排有点困难,第一行的第一条竖线和下面的第一列竖线对 齐,第一行的第二条竖线和下面的第二列竖线对齐就可以了]

这个结构 fbgen_hwswitch抽象了硬件的操作.虽然它不是必需的,但有时候很有用.

2、 fbmem.c

fbmem.c 处于Framebuffer设备驱动技术的中心位置.它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供 接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己. fbmem.c 为 所有支持FrameBuffer的设备驱动提供了通用的接口,避免重复工作.

 

1) 全局变量

 

struct fb_info *registered_fb[FB_MAX];

int num_registered_fb;

 

 

这两变量记录了所有fb_info 结构的实例,fb_info 结构描述显卡的当前状态,所有设备对应的fb_info 结构都保存在这个数组中,当一个FrameBuffer设备驱动向系统注册自己时,其对应的fb_info 结构就会添加到这个结构中,同时num_registered_fb 为自动加1.

 

static struct {

const char *name;

int (*init)(void);

int (*setup)(void);

} fb_drivers[] __initdata= { ....};

 

如果FrameBuffer设备被静态链接到内核,其对应的入口就会添加到这个表中; 如果是动态加载的,即使用insmod/rmmod,就不需要关心这个表。

 

static struct file_operations fb_ops ={

owner: THIS_MODULE,

read: fb_read,

write: fb_write,

ioctl: fb_ioctl,

mmap: fb_mmap,

open: fb_open,

release: fb_release

};

这是一个提供给应用程序的接口.

 

2)fbmem.c 实现了如下函数.

 

register_framebuffer(struct fb_info *fb_info);

unregister_framebuffer(struct fb_info *fb_info);

 

这两个是提供给下层FrameBuffer设备驱动的接口,设备驱动通过这两函数向系统注册或注销自 己。几乎底层设备驱动所要做的所有事情就是填充fb_info结构然后向系统注册或注销它。

 

(二)一个LCD显示芯片的驱动实例

    以Skeleton LCD 控制器驱 动为例,在LINUX中存有一个/fb/skeleton.c的skeleton的Framebuffer驱动程序,很简单,仅仅是填充了 fb_info结构,并且注册/注销自己。设备驱动是向用户程序提供系统调用接口,所以我们 需要实现底层硬件操作并且定义file_operations 结构来向系统提供系统调用接口,从而实现更有效的LCD控制器驱动程序。

 

1)在系统内存中分配显存

在fbmem.c文件中可以看到, file_operations 结构中的open()和release()操作不需底层支持,但read()、write()和 mmap()操作需要函数fb_get_fix()的支持.因此需要重新实现函数fb_get_fix()。另外还需要在系统内存中分配显存空间,大多数的LCD控制器都没有自己的显存空间,被分配的地址空间的起始地址与 长度将会被填充到fb_fix_screeninfo 结构的smem_start 和smem_len 的两个变量中.被分配的空间必须是物理连续的。

 

 

2)实现 fb_ops 中的函数

用户应用程序通过ioctl()系统调用操作硬件,fb_ops 中的函数就用于支持这些操作。(注: fb_ops结构与file_operations 结构不同,fb_ops是底层操作的抽象,而file_operations是提供给上层系统调用的接口,可以直接调用.

  ioctl()系统调用在文件fbmem.c中实现,通过观察可以发现ioctl()命令与fb_ops’s 中函数的关系:

FBIOGET_VSCREENINFO fb_get_var

FBIOPUT_VSCREENINFO fb_set_var

FBIOGET_FSCREENINFO fb_get_fix

FBIOPUTCMAP fb_set_cmap

FBIOGETCMAP fb_get_cmap

FBIOPAN_DISPLAY fb_pan_display

 

 

如果我们定义了fb_XXX_XXX 方法,用户程序就可以使用FBIOXXXX宏的ioctl()操作来操作硬件。

 

文件linux/drivers/video/fbgen.c或者linux/drivers/video目录下的其它设备驱动是比较好的参考资料。在所有的这些函数 中fb_set_var()是最重要的,它用于设定显示卡的模式和其它属性,下面是函 数fb_set_var()的执行步骤:

 

1)检测是否必须设定模式

2)设定模式

 

3)设定颜色映射

 

4) 根据以前的设定重新设置LCD控制器的各寄存器。

 

第四步表明了底层操作到底放置在何处。在系统内存中分配显存后,显存的起始地址及长度将被设定到 LCD控制器的各寄存器中(一般通过fb_set_var() 函数),显存中的内容将自动被LCD控制器输出到屏幕上。另一方面,用户程序通过函数mmap()将显存映射到用户进程地址空间中,然后用户进程向映射空间发 送的所有数据都将会被显示到LCD显示器上。

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载