新闻  |   论坛  |   博客  |   在线研讨会
Linux下FrameBuffer直接写屏
yanqin | 2009-04-16 14:28:19    阅读:1935   发布文章

作者:hotfire [文章出自: www.phpx.com]
%A
%A 因为Linux是工作在保护模式下,所以用户态进程是无法象DOS那样使用显卡BIOS里
%A 提供的中断调用来实现直接写屏,故Linux抽象出FrameBuffer这个设备来供用户态
%A 进程实现直接写屏。
%A
%A 在继续下面的之前,先说明几个背景知识:
%A 1、FrameBuffer主要是根据VESA标准的实现的,所以只能实现最简单的功能。
%A 2、由于涉及内核的问题,FrameBuffer是不允许在系统起来后修改显示模式等一系
%A 列操作。(好象很多人都想要这样干,这是不被允许的,当然如果你自己与驱动
%A 的话,是可以实现的)
%A 3、对FrameBuffer的操作,会直接影响到本机的所有控制台的输出,包括XWIN的图
%A 形界面。
%A
%A 好,现在可以让我们开始实现直接写屏:
%A 1、打开一个FrameBuffer设备
%A 2、通过mmap调用把显卡的物理内存空间映射到用户空间
%A 3、直接写内存。
%A
%A 好象很简单哦~
%A fbtools.h
%A
%A 代码:
%A #ifndef _FBTOOLS_H_
%A #define _FBTOOLS_H_
%A
%A #include <linux/fb.h>
%A
%A //a framebuffer device structure;
%A typedef struct fbdev{
%A int fb;
%A unsigned long fb_mem_offset;
%A unsigned long fb_mem;
%A struct fb_fix_screeninfo fb_fix;
%A struct fb_var_screeninfo fb_var;
%A char dev[20];
%A } FBDEV, *PFBDEV;
%A
%A //open & init a frame buffer
%A //to use this function,
%A //you must set FBDEV.dev=\"/dev/fb0\"
%A //or \"/dev/fbX\"
%A //it\‘s your frame buffer.
%A int fb_open(PFBDEV pFbdev);
%A
%A //close a frame buffer
%A int fb_close(PFBDEV pFbdev);
%A
%A //get display depth
%A int get_display_depth(PFBDEV pFbdev);
%A
%A
%A //full screen clear
%A void fb_memset(void *addr, int c, size_t len);
%A
%A #endif
%A
%A
%A
%A fbtools.c
%A
%A 代码:
%A #include <stdio.h>
%A #include <stdlib.h>
%A #include <fcntl.h>
%A #include <unistd.h>
%A #include <string.h>
%A #include <sys/ioctl.h>
%A #include <sys/mman.h>
%A #include <asm/page.h>
%A
%A #include \"fbtools.h\"
%A
%A #define TRUE 1
%A #define FALSE 0
%A #define MAX(x,y) ((x)>(y)?(x):(y))
%A #define MIN(x,y) ((x)<(y)?(x):(y))
%A
%A //open & init a frame buffer
%A int fb_open(PFBDEV pFbdev)
%A {
%A pFbdev->fb = open(pFbdev->dev, O_RDWR);
%A if(pFbdev->fb < 0)
%A {
%A printf(\"Error opening %s: %m. Check kernel config\\n\", pFbdev->dev);
%A return FALSE;
%A }
%A if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
%A {
%A printf(\"ioctl FBIOGET_VSCREENINFO\\n\");
%A return FALSE;
%A }
%A if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
%A {
%A printf(\"ioctl FBIOGET_FSCREENINFO\\n\");
%A return FALSE;
%A }
%A
%A //map physics address to virtual address
%A pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
%A pFbdev->fb_mem = (unsigned long int)mmap(NULL, pFbdev->fb_fix.smem_len +
%A pFbdev->fb_mem_offset,
%A PROT_READ | PROT_WRITE, MAP_SHARED, pFbdev->fb, 0);
%A if (-1L == (long) pFbdev->fb_mem)
%A {
%A printf(\"mmap error! mem:%d offset:%d\\n\", pFbdev->fb_mem,
%A pFbdev->fb_mem_offset);
%A return FALSE;
%A }
%A
%A return TRUE;
%A }
%A
%A //close frame buffer
%A int fb_close(PFBDEV pFbdev)
%A {
%A close(pFbdev->fb);
%A pFbdev->fb=-1;
%A }
%A
%A //get display depth
%A int get_display_depth(PFBDEV pFbdev);
%A {
%A if(pFbdev->fb<=0)
%A {
%A printf(\"fb device not open, open it first\\n\");
%A return FALSE;
%A }
%A return pFbdev->fb_var.bits_per_pixel;
%A }
%A
%A //full screen clear
%A void fb_memset (void *addr, int c, size_t len)
%A {
%A memset(addr, c, len);
%A }
%A
%A //use by test
%A #define DEBUG
%A #ifdef DEBUG
%A main()
%A {
%A FBDEV fbdev;
%A memset(&fbdev, 0, sizeof(FBDEV));
%A strcpy(fbdev.dev, \"/dev/fb0\");
%A if(fb_open(&fbdev)==FALSE)
%A {
%A printf(\"open frame buffer error\\n\");
%A return;
%A }
%A
%A fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
%A
%A fb_close(&fbdev);
%A }
%A
%A%A
%A

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客