我是靠谱客的博主 背后夏天,最近开发中收集的这篇文章主要介绍linux下的framebuffer的例子(转) ,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

例子实现了直接写屏的功能,即把屏幕清空(变黑),程序的流程大致为:打开一个FrameBuffer设备;通过mmap调用把显卡的物理内存空间映射到用户空间;通过映射关系直接写内存。

头文件

/ fbtools.h

#ifndef _FBTOOLS_H_
#define _FBTOOLS_H_

#include <linux/fb.h>

//a framebuffer device structure;

typedef struct fbdev

{
int fb;
unsigned long fb_mem_offset;
unsigned long fb_mem;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char dev[20];
} 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 buffer.
int fb_open(PFBDEV pFbdev);

//close a frame buffer
int fb_close(PFBDEV pFbdev);

//get display depth
int get_display_depth(PFBDEV pFbdev);

//full screen clear
void fb_memset(void *addr, int c, size_t len);

#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"

#define TRUE 1
#define FALSE 0
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))

//open & init a frame buffer

int fb_open(PFBDEV pFbdev)

{
pFbdev->fb = open(pFbdev->dev, O_RDWR);// pFbdev->fb==3
if(pFbdev->fb < 0)
{
printf("Error opening %s: %m. Check kernel config ", pFbdev->dev);
return FALSE;
}

if (-1 == ioctl(pFbdev->fb,FBIOGET_VSCREENINFO,&(pFbdev->fb_var)))
{
printf("ioctl FBIOGET_VSCREENINFO ");
return FALSE;
}
if (-1 == ioctl(pFbdev->fb,FBIOGET_FSCREENINFO,&(pFbdev->fb_fix)))
{
printf("ioctl FBIOGET_FSCREENINFO ");
return FALSE;
}

//map physics address to virtual address
// pFbdev->fb_fix.smem_start=f0000000
pFbdev->fb_mem_offset = (unsigned long)(pFbdev->fb_fix.smem_start) & (~PAGE_MASK);
// pFbdev->fb_fix.smem_len=100 0000 pFbdev->fb_mem_offset=0
// pFbdev->fb_mem =0
pFbdev->fb_mem = (unsigned long int)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("mmap error! mem:%d offset:%d ", pFbdev->fb_mem,
pFbdev->fb_mem_offset);
return FALSE;
}
return TRUE;
}

//close frame buffer
int fb_close(PFBDEV pFbdev)
{
close(pFbdev->fb);
pFbdev->fb=-1;
}

//get display depth
int get_display_depth(PFBDEV pFbdev);
{
if(pFbdev->fb<=0)
{
printf("fb device not open, open it first ");
return FALSE;
}
return pFbdev->fb_var.bits_per_pixel;
}
//full screen clear
void fb_memset (void *addr, int c, size_t len)
{
memset(addr, c, len);
}

 

 

//use by test
#define DEBUG
#ifdef DEBUG
main()
{
FBDEV fbdev;
memset(&fbdev, 0, sizeof(FBDEV));
strcpy(fbdev.dev, "/dev/fb0");
if(fb_open(&fbdev)==FALSE)
{
printf("open frame buffer error ");
return;
}
//注意,下面一行有bug
fb_memset(fbdev.fb_mem + fbdev.fb_mem_offset, 0, fbdev.fb_fix.smem_len);
fb_close(&fbdev);
}
#endif

 

注意:如果对上述代码直接进行编译的话,是不能成功的,即会出现类似下面的编译错误
# gcc –o fbtools fbtools.c

fbtools.c: In function `main`
fbtools.c:89:warning:passing arg 1 of `fb_memset` makes pointer from integer without a cast


对有问题的fbtools.c中的第89行代码(即加粗的有注释的那一行)进行如下操作,修改为:


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


或者


unsigned long temp;
temp= fbdev.fb_mem+fbdev.fb_mem_offset;
fb_memset((void *)temp, 0, fbdev.fb_fix.smem_len);


可以成功编译成功

 

 


 

 

问题:/dev目录下找不到 fb0设备

解决方法:对于RedHat系列linux机器,修改 /boot/grub/menu.lst 文件,并在 kernel 打头的一行添加 vga=0x0317

然后:

# mknod /dev/fb0 c 29 0
# mknod /dev/fb1 c 29 1

 


最后

以上就是背后夏天为你收集整理的linux下的framebuffer的例子(转) 的全部内容,希望文章能够帮你解决linux下的framebuffer的例子(转) 所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部