Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1051650
  • 博文数量: 836
  • 博客积分: 43880
  • 博客等级: 大将
  • 技术积分: 5485
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-20 17:36
文章分类

全部博文(836)

文章存档

2011年(1)

2008年(835)

我的朋友

分类: LINUX

2008-08-20 18:24:59


因为Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里提供的中断调用来实现直接写屏,故Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。

在继续下面的之前,先说明几个背景知识:
  1. FrameBuffer主要是根据VESA标准的实现的,所以只能实现最简单的功能。
  2. 由于涉及内核的问题,FrameBuffer是不允许在系统起来后修改显示模式等一系列操作。(好象很多人都想要这样干,这是不被允许的,当然如果你自己与驱动的话,是可以实现的)
  3. 对FrameBuffer的操作,会直接影响到本机的所有控制台的输出,包括XWIN的图形界面。

  好,现在可以让我们开始实现直接写屏:

  1. 打开一个FrameBuffer设备
  2. 通过mmap调用把显卡的物理内存空间映射到用户空间
  3. 直接写内存。

  好象很简单哦~
  fbtools.h


#ifndef_FBTOOLS_H_
#define_FBTOOLS_H_

#include<linux/fb.h>

/*aframebufferdevicestructure*/
typedefstructfbdev{
intfb;
unsignedlongfb_mem_offset;
unsignedlongfb_mem;
structfb_fix_screeninfofb_fix;
structfb_var_screeninfofb_var;
chardev[20];
}FBDEV,*PFBDEV;

/*open&initaframebuffer*/
/*tousethisfunction,
youmustsetFBDEV.dev="/dev/fb0"
or"/dev/fbX"*/
/*it''syourframebuffer.*/
intfb_open(PFBDEVpFbdev);

/*closeaframebuffer*/
intfb_close(PFBDEVpFbdev);

/*getdisplaydepth*/
intget_display_depth(PFBDEVpFbdev);


/*fullscreenclear*/
voidfb_memset(void*addr,intc,size_tlen);

#endif


  fbtools.c

  代码:


#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<sys/ioctl.h>
#include<sys/mman.h>
#include<asm/page.h>

#include"fbtools.h"

#defineTRUE1
#defineFALSE0
#defineMAX(x,y)((x)>(y)?(x):(y))
#defineMIN(x,y)((x)<(y)?(x):(y))

/*open&initaframebuffer*/
intfb_open(PFBDEVpFbdev)
{
pFbdev->fb=open(pFbdev->dev,O_RDWR);
if(pFbdev->fb<0)
{
printf("Erroropening%s:%m.Checkkernelconfig\n",pFbdev->dev);
returnFALSE;
}
if(-1==ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
{
printf("ioctlFBIOGET_VSCREENINFO\n");
returnFALSE;
}
if(-1==ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
{
printf("ioctlFBIOGET_FSCREENINFO\n");
returnFALSE;
}

/*mapphysicsaddresstovirtualaddress*/
pFbdev->fb_mem_offset=(unsignedlong)(pFbdev->fb_fix.smem_start)&(~PAGE_MASK);
pFbdev->fb_mem=(unsignedlongint)mmap(NULL,pFbdev->fb_fix.smem_len
pFbdev->fb_mem_offset,
PROT_READ|PROT_WRITE,MAP_SHARED,pFbdev->fb,0);
if(-1L==(long)pFbdev->fb_mem)
{
printf("mmaperror!mem:%doffset:%d\n",pFbdev->fb_mem,
pFbdev->fb_mem_offset);
returnFALSE;
}

returnTRUE;
}

/*closeframebuffer*/
intfb_close(PFBDEVpFbdev)
{
close(pFbdev->fb);
pFbdev->fb=-1;
}

/*getdisplaydepth*/
intget_display_depth(PFBDEVpFbdev);
{
if(pFbdev->fb<=0)
{
printf("fbdevicenotopen,openitfirst\n");
returnFALSE;
}
returnpFbdev->fb_var.bits_per_pixel;
}

/*fullscreenclear*/
voidfb_memset(void*addr,intc,size_tlen)
{
memset(addr,c,len);
}

/*usebytest*/
#defineDEBUG
#ifdefDEBUG
main()
{
FBDEVfbdev;
memset(&fbdev,0,sizeof(FBDEV));
strcpy(fbdev.dev,"/dev/fb0");
if(fb_open(&fbdev)==FALSE)
{
printf("openframebuffererror\n");
return;
}

fb_memset(fbdev.fb_mem fbdev.fb_mem_offset,0,fbdev.fb_fix.smem_len);

fb_close(&fbdev);
}


(责任编辑:凌云通)


下载本文示例代码
阅读(228) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~