Framebuffer详解_第1页
Framebuffer详解_第2页
Framebuffer详解_第3页
Framebuffer详解_第4页
Framebuffer详解_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Framebuffer详解一、FrameBuffer的原理    FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。    Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,Linux抽象出 FrameBuffer这个设备来供用户态进程实现直接写屏。Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 Framebuffer的读写直接对显存进行操作。用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之

2、后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由 Framebuffer设备驱动来完成的。    但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池.CPU将运算后的结果放到这个水池,水池再将结果流到显示器. 中间不会对数据做处理. 应用程序也可以直接读写这个水池的内容.在这种机制下,尽管Framebuffer需要真正的显卡驱动的支持,但所有显示任务都有CPU完成,因此CPU 负担很重framebuffer的设备文件一般是 /dev/f

3、b0、/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 设备映射

4、到进程地址空间的方式使用,比如下面的程序就打开 /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可以执行 

5、   FrameBuffer 设备还提供了若干 ioctl 命令,通过这些命令,可以获得显示设备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分辨率、象素结构、每扫描线的字节宽度),以及伪彩色模式下的调色板信息等等。    通过 FrameBuffer 设备,还可以获得当前内核所支持的加速显示卡的类型(通过固定信息得到),这种类型通常是和特定显示芯片相关的。比如目前最新的内核(2.4.9)中,就包含有对 S3、Matrox、nVidia、3Dfx 等等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序就可以将 PCI

6、 设备的内存I/O(memio)映射到进程的地址空间。这些 memio 一般是用来控制显示卡的寄存器,通过对这些寄存器的操作,应用程序就可以控制特定显卡的加速功能。    PCI 设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问,给变成了对物理内存的访问。因此,这些寄存器又被称为"memio"。一旦被映射到物理内存,Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。    当然,因为不同的显示芯片具有不同的加速能力,对mem

7、io 的使用和定义也各自不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方式不同,这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。    FrameBuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在 FrameBuffer 之上进行图形编程,还需要自己动手完成其他许多工作。二、FrameBuffer在Linux中的实现和机制Framebuffer对应的源文件在linux/drivers/video

8、/目录下。总的抽象设备文件为fbcon.c,在这个目录下还有与各种显卡驱动相关的源文件。   /这个文件要好好看看(一)、分析Framebuffer设备驱动    需要特别提出的是在INTEL平台上,老式的VESA 1.2 卡,如CGA/EGA卡,是不能支持Framebuffer的,因为Framebuffer要求显卡支持线性帧缓冲,即CPU可以访问显缓冲中的每一位,但是VESA 1.2 卡只能允许CPU一次访问64K的地址空间。FrameBuffer设备驱动基于如下两个文件:1) linux/include/linux/fb.h2) linux

9、/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;

10、 /* 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 i

11、nstead 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 form

12、at */ 不是标准格式_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) */时序-_-这些部分就是显示器的显示方法了,可以找相关的资料

13、看看_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; /*

14、 length of vertical sync */   垂直可视区域_u32 sync; /* see FB_SYNC_* */_u32 vmode; /* see FB_VMODE_* */_u32 reserved6; /* Reserved for future compatibility */ 备用以后开发;2) fb_fix_screeninfon这个结构在显卡被设定模式后创建,它描述显示卡的属性,并且系统运行时不能被修改;比如FrameBuffer内存的起始地址。它依赖于被设定的模式,当一个模式被设定后,内存信息由显示卡硬件给出,内存的位置等信息就不可以修改

15、。struct fb_fix_screeninfo char id16; /* identification string eg "TT Builtin" */IDunsigned 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

16、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; /

17、* 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 reserved3; /* Reserved for future compatibility */;3) fb_cmap描述设备无关的颜色映射信息。可以通过FBIOGETCMAP 和 FBIOPUTCMAP 对应的ioctl

18、操作设定或获取颜色映射信息.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

19、 modename40; /* 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 */ 修正的信息stru

20、ct 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 fon

21、tname40; /* 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

22、consoles */ 告诉fb选择consolesint (*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 */arg0的时候黑白模式/* arg > 0: VESA level (arg-1) */ arg>0时候选择VESA模式void *pseudo_pal

23、ette; /* Fake palette of 16 colors andthe cursor's color for nonpalette 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;i

24、nt (*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

25、 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,

26、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);/*

27、 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 mapstruct fb_info_gen | struct fb_info | fb_var_screeninfo    &#

28、160;              |                | fb_fix_screeninfo                 

29、0; |                | fb_cmap                   |              &#

30、160; | modename40                   |                | fb_ops -|->ops on var         &#

31、160;         |                | .       | fb_open                 

32、0; |                |           | fb_release                   |   

33、60;            |           | fb_ioctl                   |        

34、        |           | fb_mmap                   | struct fbgen_hwswitch         

35、                      /-|-> detect                          &#

36、160;         | encode_fix                                    | encode_var  

37、                                  | decode_fix               

38、;                     | decode_var                           

39、0;        | get_var                                    | set_var    &#

40、160;                               | getcolreg                 &#

41、160;                  | setcolreg                              &#

42、160;     | pan_display                                    | blank      

43、0;                             | set_disp编排有点困难,第一行的第一条竖线和下面的第一列竖线对齐,第一行的第二条竖线和下面的第二列竖线对齐就可以了这个结构 fbgen_hwswitch抽象了硬件的操作.虽然它不是必需的,但有时候很有用.2、 fbmem.cfbmem.c 处于Fr

44、amebuffer设备驱动技术的中心位置.它为上层应用程序提供系统调用也为下一层的特定硬件驱动提供接口;那些底层硬件驱动需要用到这儿的接口来向系统内核注册它们自己. fbmem.c 为所有支持FrameBuffer的设备驱动提供了通用的接口,避免重复工作.1) 全局变量struct fb_info *registered_fbFB_MAX;int num_registered_fb;这两变量记录了所有fb_info 结构的实例,fb_info 结构描述显卡的当前状态,所有设备对应的fb_info 结构都保存在这个数组中,当一个FrameBuffer设备驱动向系统注册自己时,其对应的fb_inf

45、o 结构就会添加到这个结构中,同时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,ioct

46、l: 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显示芯片的驱动实例 

47、   以Skeleton LCD 控制器驱动为例,在LINUX中存有一个/fb/skeleton.c的skeleton的Framebuffer驱动程序,很简单,仅仅是填充了 fb_info结构,并且注册/注销自己。设备驱动是向用户程序提供系统调用接口,所以我们需要实现底层硬件操作并且定义file_operations 结构来向系统提供系统调用接口,从而实现更有效的LCD控制器驱动程序。1)在系统内存中分配显存在fbmem.c文件中可以看到, file_operations 结构中的open()和release()操作不需底层支持,但read()、write()和 mmap(

48、)操作需要函数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是提供

49、给上层系统调用的接口,可以直接调用.  ioctl()系统调用在文件fbmem.c中实现,通过观察可以发现ioctl()命令与fb_opss 中函数的关系:FBIOGET_VSCREENINFO fb_get_varFBIOPUT_VSCREENINFO fb_set_varFBIOGET_FSCREENINFO fb_get_fixFBIOPUTCMAP fb_set_cmapFBIOGETCMAP fb_get_cmapFBIOPAN_DISPLAY fb_pan_display如果我们定义了fb_XXX_XXX 方法,用户程序就可以使用FBIOXXXX宏的ioctl()操作来操

50、作硬件。文件linux/drivers/video/fbgen.c或者linux/drivers/video目录下的其它设备驱动是比较好的参考资料。在所有的这些函数中fb_set_var()是最重要的,它用于设定显示卡的模式和其它属性,下面是函数fb_set_var()的执行步骤:1)检测是否必须设定模式2)设定模式3)设定颜色映射4) 根据以前的设定重新设置LCD控制器的各寄存器。第四步表明了底层操作到底放置在何处。在系统内存中分配显存后,显存的起始地址及长度将被设定到 LCD控制器的各寄存器中(一般通过fb_set_var() 函数),显存中的内容将自动被LCD控制器输出到屏幕上。另一方面

51、,用户程序通过函数mmap()将显存映射到用户进程地址空间中,然后用户进程向映射空间发送的所有数据都将会被显示到LCD显示器上。三、FrameBuffer的应用(一)、一个使用FrameBuffer的例子1.FrameBuffer主要是根据VESA标准的实现的,所以只能实现最简单的功能。 2.由于涉及内核的问题,FrameBuffer是不允许在系统起来后修改显示模式等一系列操作。(好象很多人都想要这样干,这是不被允许的,当然如果你自己写驱动的话,是可以实现的). 3.对FrameBuffer的操作,会直接影响到本机的所有控制台的输出,包括XWIN的图形界面。 4.

52、在struct fb_info 中的char fontname40; /* default font name */默认的字体就可以实现显示的中文化难道 篮点linux就是这样搞得?好,现在可以让我们开始实现直接写屏:1、打开一个FrameBuffer设备2、通过mmap调用把显卡的物理内存空间映射到用户空间3、直接写内存。/*File name : fbtools.h*/#ifndef _FBTOOLS_H_#define _FBTOOLS_H_#include <linux/fb.h>/a framebuffer device structure;typedef struct

53、fbdev       int fb;       unsigned long fb_mem_offset;       unsigned long fb_mem;       struct fb_fix_screeninfo fb_fix;       struct fb_var_screenin

54、fo fb_var;       char dev20; FBDEV, *PFBDEV;/open & init a frame buffer/to use this function,/you must set FBDEV.dev="/dev/fb0"/or "/dev/fbX"/it's your frame fb_open(PFBDEV pFbdev);/close a frame bufferint fb_close(PFBDEV pFbdev);/

55、get display depthint get_display_depth(PFBDEV pFbdev);/full screen clearvoid fb_memset(void *addr, int c, size_t len);#endif/*File name : fbtools.c*/#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>

56、#include <sys/mman.h>#include <asm/page.h>#include "fbtools.h"#define TRUE        1#define FALSE       0#define MAX(x,y)        (x)>(y)?(x)y)#define MIN(x,y)   

57、     (x)<(y)?(x)y)/open & init a frame bufferint fb_open(PFBDEV pFbdev)       pFbdev->fb = open(pFbdev->dev, O_RDWR);       if(pFbdev->fb < 0)          

58、0;          printf("Error opening %s: %m. Check kernel config/n", pFbdev->dev);              return FALSE;            

59、0; if (-1 = ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)                     printf("ioctl FBIOGET_VSCREENINFO/n");          

60、    return FALSE;              if (-1 = ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)                     print

61、f("ioctl FBIOGET_FSCREENINFO/n");              return FALSE;              /map physics address to virtual address       pFbdev->fb_m

62、em_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (PAGE_MASK);       pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len + pFbdev->fb_mem_offset,              PROT

63、_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);       if (-1L = (long) pFbdev->fb_mem)                     printf("mmap error! mem:%d offset:%d/n", pFbdev->

64、fb_mem, pFbdev->fb_mem_offset);              return FALSE;              return TRUE;/close frame bufferint fb_close(PFBDEV pFbdev)       close

65、(pFbdev->fb);       pFbdev->fb=-1;/get display depthint get_display_depth(PFBDEV pFbdev);       if(pFbdev->fb<=0)                    

66、 printf("fb device not open, open it first/n");              return FALSE;              return pFbdev->fb_var.bits_per_pixel;/full screen clearvoid fb_memset (voi

67、d *addr, int c, size_t len)    memset(addr, c, len);/use by test#define DEBUG#ifdef DEBUGmain()       FBDEV fbdev;       memset(&fbdev, 0, sizeof(FBDEV);       strcpy(fbdev.dev, "/dev/fb

68、0");       if(fb_open(&fbdev)=FALSE)                     printf("open frame buffer error/n");          

69、60;   return;              fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);              fb_close(&fbdev);(二)基于Linux核心的汉字显示的尝试我们以一个简单的例子来

70、说明字符显示的过程。我们假设是在虚拟终端1(/dev/tty1)下运行一个如下的简单程序。main ( )puts("hello, world./n");puts 函数向缺省输出文件(/dev/tty1)发出写的系统调用write(2)。系统调用到linux核心里面对应的核心函数是console.c中的 con_write(),con_write()最终会调用do_con_write( )。在do_con_write( )中负责把"hello, world./n"这个字符串放到tty1对应的缓冲区中去。do_con_write( )还负责处理控制字符和光

71、标的位置。让我们来看一下do_con_write()这个函数的声明。static int do_con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count)    其中tty是指向tty_struct结构的指针,这个结构里面存放着关于这个tty的所有信息(请参照 linux/include/linux/tty.h)。Tty_struct结构中定义了通用(或高层)tty的属性(例如宽度和高度等)。在 do_con_write( )函数中用到了tty_str

72、uct结构中的driver_data变量。driver_data是一个vt_struct指针。在vt_struct结构中包含这个tty的序列号(我们正使用tty1,所以这个序号为1)。Vt_struct结构中有一个vc结构的数组vc_cons,这个数组就是各虚拟终端的私有数据。static int do_con_write(struct tty_struct * tty, int from_user,const unsigned char *buf, int count)struct vt_struct *vt = (struct vt_struct *)tty->driver_data

73、;/我们用到了driver_data变量. . . . .currcons = vt->vc_num; file:/我们在这里的vc_nums就是1. . . . .    要访问虚拟终端的私有数据,需使用vc_conscurrcons.d指针。这个指针指向的结构含有当前虚拟终端上光标的位置、缓冲区的起始地址、缓冲区大小等等。    "hello, world./n"中的每一个字符都要经过conv_uni_to_pc( )这个函数转换成位的显示字符。这要做的主要目的是使不同语言的国家能把位的UniCode码映

74、射到8位的显示字符集上,目前还是主要针对欧洲国家的语言,映射结果为8位,不包含对双字节(double byte)的范围。    这种UNICODE到显示字符的映射关系可以由用户自行定义。在缺省的映射表上,会把中文的字符映射到其他的字符上,这是我们不希望看到也是不需要的。所以我们有两个选择1.不进行conv_uni_to_pc( )的转换。 2.加载符合双字节处理的映射关系,即对非控制字符进行1对1的不变映射。我们自己定制的符合这种映射关系的UNICODE码表是direct.uni。要想查看/装载当前系统的unicode映射表,可使外部命令loadunim

75、ap。 经过conv_uni_to_pc( )转换之后,"hello, world./n"中的字符被一个一个地填写到tty1的缓冲区中。然后do_con_write( )调用下层的驱动,把缓冲区中的内容输出到显示器上(也就相当于把缓冲区的内容拷贝到VGA显存中去)。sw->con_putcs(vc_conscurrcons.d, (u16 *)draw_from, (u16*)draw_to-(u16 *)draw_from, y, draw_x);之所以要调用底层驱动,是因为存在不同的显示设备,其对应VGA显存的存取方式也不一样。上面的Sw->con

76、_putcs( )就会调用到fbcon.c中的fbcon_putcs()函数(con_putcs是一个函数的指针,在Framebuffer模式下指向 fbcon_putcs()函数)。也就是说在do_con_write( )函数中是直接调用了fbcon_putcs()函数来进行字符的绘制。比如说在256色模式下,真正负责输出的函数是void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,const unsigned short *s, int count, int yy, int xx)   显示中文

77、60;   比如说我们试图输出一句中文putcs(你好/n );(你好的内码为0xc4,0xe3,0xba,0xc3)。这时候会怎么样呢,有一点可以肯定,你好肯定不会出现在屏幕上,国为核心中没有汉字字库,中文显示就是无米之炊了    1 在负责字符显示的void fbcon_cfb8_putcs( )函数中,原有操作如下对于每个要显示的字符,依次从虚拟终端缓冲区中以WORD为单位读取(低位字节是ASCII码,高8位是字符的属性),由于汉字是双字节编码方式,所以这种操作是不可能显示出汉字的,只能显示出xxxx_putcs()是一个一个VGA字符要解决的问题确保在do_con_write( )时uni_pc转换不会改变原有

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论