全面的framebuffer详解一

全⾯的framebuffer详解⼀
转:blog.chinaunix/uid-20628575-id-72534.html
⼀、FrameBuffer的原理
FrameBuffer 是出现在 内核当中的⼀种驱动程序接⼝。
Linux是⼯作在保护模式下,所以⽤户态进程是⽆法象DOS那样使⽤显卡BIOS⾥提供的中断调⽤来实现直接写
屏,Linux抽象出 FrameBuffer这个设备来供⽤户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 Framebuffer的读写直接对显存进⾏操作。⽤户可以将Framebuffer看成是显⽰内存的⼀个映像,将其映射到进程地址空间之后,就可以直接进⾏读写操作,⽽写操作可以⽴即反应在屏幕上。这种操作是抽象的,统⼀的。⽤户不必关⼼物理显存的位置、换页机制等等具体细节。这些都是由 Framebuffer设备驱动来完成的。
但Framebuffer本⾝不具备任何运算数据的能⼒,就只好⽐是⼀个暂时存放⽔的⽔池.CPU将运算后的结果放到这个⽔池,⽔池再将结果流到显⽰器. 中间不会对数据做处理. 应⽤程序也可以直接读写这个⽔池的内容.在这种机制下,尽管Framebuffer需要真正的显卡驱动的⽀持,但所有显⽰任务都有CPU完成,因
此CPU 负担很重
framebuffer的设备⽂件⼀般是 /dev/fb0、/dev/fb1 等等。
可以⽤命令: #dd if=/dev/zero of=/dev/fb 清空屏幕.
如果显⽰模式是 1024x768-8 位⾊,⽤命令:$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768 清空屏幕;
⽤命令: #dd if=/dev/fb of=fbfile  可以将fb中的内容保存下来;
可以重新写回屏幕: #dd if=fbfile of=/dev/fb;
在使⽤Framebuffer时,Linux是将显卡置于图形模式下的.
在应⽤程序中,⼀般通过将 FrameBuffer 设备映射到进程地址空间的⽅式使⽤,⽐如下⾯的程序就打开 /dev/fb0 设备,并通过 mmap 系统调⽤进⾏地址映射,随后⽤ memset 将屏幕清空(这⾥假设显⽰模式是 1024x768-8 位⾊模式,线性内存模式):
int fb;
unsigned char* fb_mem;
fb = open ("/dev/fb0", O_RDWR);
fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
memset (fb_mem, 0, 1024*768); //这个命令应该只有在root可以执⾏
FrameBuffer 设备还提供了若⼲ ioctl 命令,通过这些命令,可以获得显⽰设备的⼀些固定信息(⽐如显⽰内存⼤⼩)、与显⽰模式相关的可变信息(⽐如分辨率、象素结构、每扫描线的字节宽度),以及伪彩⾊模式下的调⾊板信息等等。
通过 FrameBuffer 设备,还可以获得当前内核所⽀持的加速显⽰卡的类型(通过固定信息得到),这种类型通常是和特定显⽰芯⽚相关的。⽐如⽬前最新的内核(2.4.9)中,就包含有对 S3、Matrox、nVidia、3Dfx 等等流⾏显⽰芯⽚的加速⽀持。在获得了加速芯⽚类型之后,应⽤程序就可以将 PCI 设备的内存I/O(memio)映射到进程的地址空间。这些 memio ⼀般是⽤来控制显⽰卡的寄存器,通过对这些寄存器的操作,应⽤程序就可以控制特定显卡的加速功能。
PCI 设备可以将⾃⼰的控制寄存器映射到物理内存空间,⽽后,对这些控制寄存器的访问,给变成了对物理内存的访问。因此,这些寄存器⼜被称为"memio"。⼀旦被映射到物理内存,Linux 的普通进程
就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。
当然,因为不同的显⽰芯⽚具有不同的加速能⼒,对memio 的使⽤和定义也各⾃不同,这时,就需要针对加速芯⽚的不同类型来编写实现不同的加速功能。⽐如⼤多数芯⽚都提供了对矩形填充的硬件加速⽀持,但不同的芯⽚实现⽅式不同,这时,就需要针对不同的芯⽚类型编写不同的⽤来完成填充矩形的函数。
FrameBuffer 只是⼀个提供显⽰内存和显⽰芯⽚寄存器从物理内存映射到进程地址空间中的设备。所以,对于应⽤程序⽽⾔,如果希望在 FrameBuffer 之上进⾏图形编程,还需要⾃⼰动⼿完成其他许多⼯作。
⼆、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
充电保暖鞋
这个结构在显卡被设定模式后创建,它描述显⽰卡的属性,并且系统运⾏时不能被修改;⽐如Frame
Buffer内存的起始地址。它依赖于被设定的模式,当⼀个模式被设定后,内存信息由显⽰卡硬件给出,内存的位置等信息就不可以修改。
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;

本文发布于:2024-09-21 05:37:02,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/274111.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:显卡   内存   设备   模式   映射
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议