Linux FB 的学习

linux FB 是CPU 到显示器中的中间人,像一个池子一样。CPU 将操作好的数据项放到池子中,然后再将这些数据显示到屏幕上。

它的好处在于 用户可以将FB看成一个显示内存的映射,当将其映射到用户进程空间是可以直接进行读写操作。操作的方式是通过ioctl的方式,有底层驱动实现。

直接使用命令行操作FB 的方式

  1. 用命令:$ dd if=/dev/zero of=/dev/fb 清空屏幕
  2. 用命令:#dd if=/dev/fb of=fbfile可以将fb中的内容保存下来;
  3. 可以重新写回屏幕: #dd if=fbfile of=/dev/fb

值得一提的是 fbfile 文件大小为6MB。

使用ioctl FBIOGET_FSCREENINFO FBIOGET_VSCREENINFO可以获取到显存大小和实际屏幕的大小。

在fb_fix_screeninfo中有
__u32 smem_len 是这个/dev/fb0的大小,也就是内存大小。
__u32 line_length 是屏幕上一行的点在内存中占有的空间,不是一行上的点数。
在fb_var_screeninfo 中有
__u32 xres ,__u32 yres 是x和y方向的分辨率,就是两个方向上的点数。
__u32 bits_per_pixel 是每一点占有的内存空间。

The mem is :6291456
The line_length is :4096
The xres is :1024
The yres is :768
bits_per_pixel is :32

内存长度恰好为 6291456 / 1024 /1024 = 6。每行占4K的空间。(原文为4M),色彩深度为32bit。屏幕上的点由 1024*768 = 786432个,每个点占32bit,屏幕一共占有内存 32 * 786432 = 25165824 ==》 25165824 / 8 / 1024 /1024 = 3MB。恰好为3MB,但是上面的程序告诉我们有6MB的存储空间。这是因为,多重缓冲技术。显存中有两页的屏幕数据,接替显示,可以实现屏幕抗闪烁等效果。

目前了解了FB,然后可以就在屏幕上进行一个点一个线的绘制。在linux 中一切都是文件,即对屏幕的绘制就是对/dev/fb0的绘制,那么在屏幕上画点的流程就是。

  1. 打开设备

  2. 通过mmap的方式将/dev/fb0映射到用户的进程空间中,然后获取到这个一块内存的大小。
    fbp = mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fp,0);

  3. 画点的方式就是 直接赋值来改变屏幕上某点的颜色

    x = 100;
    y = 100;
    location = x * (vinfo.bits_per_pixel / 8) + y  *  finfo.line_length;
    
    
    *(fbp + location) = 100;  /* 蓝色的色深 */  /*直接赋值来改变屏幕上某点的颜色*/
    *(fbp + location + 1) = 15; /* 绿色的色深*/   
    *(fbp + location + 2) = 200; /* 红色的色深*/   
    *(fbp + location + 3) = 0;  /* 是否透明*/  
    

    如果画线的话,就循环画点呗。

完整实例

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <sys/mman.h>

int main(void)
{
    int fp = 0;
    struct fb_var_screeninfo v_info;
    struct fb_fix_screeninfo f_info;
    long s32ScreenSize = 0;
    char * fbp = 0;
    int x = 0;
    int y = 0;
    long s32Location = 0;



    fp = open("/dev/fb0", O_RDWR);

    if(fp < 0 ) {
        perror("open");
        exit(1);
    }

    int s32Ret = -1;

    s32Ret = ioctl(fp, FBIOGET_FSCREENINFO, &f_info);
    if(s32Ret) {
        perror("ioctl");
        goto err;
    }

    s32Ret = ioctl(fp, FBIOGET_VSCREENINFO, &v_info);
    if(s32Ret) {
        perror("ioctl");
        goto err;
    }

    printf("The mem is :%d\n", f_info.smem_len);
    printf("The line_length is :%d\n", f_info.line_length);
    printf("The xres is :%d\n", v_info.xres);
    printf("The yres is :%d\n", v_info.yres);
    printf("bits_per_pixel is :%d\n",v_info.bits_per_pixel);



    printf("long size[%lu] \n", sizeof(long));

    s32ScreenSize = v_info.xres * v_info.yres *  v_info.bits_per_pixel / 8;
    // void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    fbp = (char*) mmap(NULL, s32ScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fp, 0);
    if(fbp == NULL){
        perror("mmap");
        goto err;
    }

    x = 400;
    y = 400;
    s32Location = x * (v_info.bits_per_pixel / 8) + y * f_info.line_length;

    int i = 0;
    for(i = 0; i < 100 ; i++) {
        *(fbp + s32Location + i) = 100;
        *(fbp + s32Location + i + 1) = 15;
        *(fbp + s32Location + i + 2) = 200;
        *(fbp + s32Location + i + 3) = 0;
    }


    munmap(fbp,s32ScreenSize);




    close(fp);

    return 0;
err:
    close(fp);

    exit(1);
    return -1;
}

/dev/fb0入门练习(linux FrameBuffer)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值