首页 > 其他分享 >framebuffer(帧缓冲)

framebuffer(帧缓冲)

时间:2024-08-03 15:27:27浏览次数:7  
标签:__ 映射 int 缓冲 unsigned u32 y0 framebuffer

framebuffer

       在Linux系统中,Framebuffer通常是指Framebuffer设备,它是一种特殊的字符设备,在Linux系统中,Framebuffer设备使得程序员可以通过其设定的函数接口直接访问硬件,而不需要通过CPU。

framebuffer的一般操作流程为:

1.打开  (open)
2.获取frame相关信息  (ioctl)
3.映射显存地址  (mmap)
4.向显存写内容(写到映射的用户空间)  
5.解除映射  (munmap)
6.关闭  close(fd);

ioctl()

int ioctl(int fd, unsigned long request, ...);
参数:

fd:操作的文件描述符
request:表示与驱动程序交互的命令,
    用不同的命令控制驱动程序输出我们需要的数据;
    一般使用到的参数:
    FBIOGET_FSCREENINFO:返回与Framebuffer有关的固定的信息,
        比如图形硬件上实际的帧缓存空间的大小、
        能否硬件加速等信息。
    FBIOGET_VSCREENINFO:返回的是与Framebuffer有关的可变信息。
...:表示可变参数 arg,根据 request 命令,
    设备驱动程序返回输出的数据。
    一般使用struct fb_var_screeninfo 来接收参数,对framebuffer进行基础操作用到

   上面几个标注的参数即可

    返回值:

    成功:返回文件描述符
    失败:-1

struct fb_var_screeninfo {
     __u32 xres;         /* visible resolution */这两个字段表示可见分辨率的宽度和高度,                                                                
     __u32 yres;                                //单位是像素。
     __u32 xres_virtual;     /* virtual resolution */
     __u32 yres_virtual;    //这两个字段表示虚拟分辨率的宽度和高度,单位是像素。
                            //虚拟分辨率是指Framebuffer可以支持的最大分辨率。
     __u32 xoffset;          /* offset from virtual to visible */
     __u32 yoffset;          /* resolution  */ //这两个字段表示从虚拟分辨率到
                                               //可见分辨率之间的偏移量。
     __u32 bits_per_pixel;       /* guess what */  //这个字段表示每个像素的比特数,
                                                   //用于确定每个像素的颜色位数。
     __u32 grayscale;        /* 0 = color, 1 = grayscale, */
                     /* >1 = FOURCC          */
     struct fb_bitfield red;     /* bitfield in fb mem if true color, */
     struct fb_bitfield green;   /* else only length is significant */
     struct fb_bitfield blue;
     struct fb_bitfield transp;  /* transparency         */  
 
     __u32 nonstd;__u32 activate;         /* see FB_ACTIVATE_*        */
 
     __u32 height;           /* height of picture in mm    */
     __u32 width;            /* width of picture in mm     */
                                                                                                          
     __u32 accel_flags;      /* (OBSOLETE) see fb_info.flags */
 
     /* Timing: All values in pixclocks, except pixclock (of course) */
     __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;        /* length of vertical sync  */
     __u32 sync;         /* see FB_SYNC_*        */
     __u32 vmode;            /* see FB_VMODE_*       */
     __u32 rotate;           /* angle we rotate counter clockwise */
     __u32 colorspace;       /* colorspace for FOURCC-based modes */
    __u32 reserved[4];      /* Reserved for future compatibility */
 };

mmap()

void *mmap(void *addr, size_t length, int prot,
             int flags,int fd, off_t offset);

功能:
创建内存映射
参数:
addr:表示指定映射的內存起始地址,通常设为 NULL,在内存中的映射区中(不是堆)
      表示让系统自动选定地址,并在成功映射后返回该地址;
length:表示将文件中多大的内容映射到内存中;
        一般通过虚拟分辨率(支持最大分辨率)算出:

unsigned long size = info.xres_virtual * info.yres_virtual * info.bits_per_pixel / 8;
 //前面三个变量相乘得到虚拟分辨率所占的比特数(最大分辨率),除8得到字节数

prot:表示映射区域的保护方式,可以为以下 4 种方式的组合
     a. PROT_EXEC 映射区域可被执行
     b. PROT_READ 映射区域可被读出
     c. PROT_WRITE 映射区域可被写入
     d. PROT_NONE 映射区域不能存取    
a. MAP_SHARED  用于创建一个私有的映射,写操作不会立即生效,
            当映射的文件被关闭时,所有未写入的更改会被写入到文件中。
            这种行为类似于文件的临时副本,可以被修改,
            但不会立即影响文件的内容。
            可以安全地修改而不立即影响文件。
 b. MAP_PRIVATE 用于创建一个共享的映射,写操作会立即生效,
            会同步到磁盘,并可以被其他进程看到,
            类似于直接在文件上进行修改    

munmap()

int munmap(void *addr, size_t length)

功能:与mmap函数配套,解除内存映射

参数:

addr: 映射区域的起始地址,即mmap()函数的返回值。

length: 映射区域的大小,以字节为单位。应与mmap()函数中的length参数相同。

返回值:

成功:返回0

失败:返回-1

显示器与显存的关系:

注意:从映射内存中走完显示器整行内容后,下一个元素并不是第二行的第一个元素,而是走完整行显存后,下一个元素才是第二行的第一个元素

 unsigned int * p = (unsigned int *)(p_fd + (y0 * info.xres_virtual + x0) * 4);

示例代码:

1.为什么要使用结构体__color与联合体col?

      便于修改与传参,要对这个颜色(r,g,b)中修改时,明显通过结构体对每一位修改更加直观,更加方便,而联合体的另一个int型变量与结构体(4个char型变量)所占用空间一样,公用一个空间,这时,传入int型l就相当于传入了这个颜色所有的位变量

2.mmap映射出的地址p_fd在函数中使用,是使用全局变量好还是使用传参好?

      全局变量好,因为如果在实际使用中封装函数不希望别的使用者来对这个变量进行修改时(修改后无法找到该映射空间首地址),使用全局变量后,别的使用者无法调用。

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

#define pi 3.141592657
struct fb_var_screeninfo info;
unsigned char * p_fd = NULL;

typedef struct __color
{
	unsigned char b;
	unsigned char g;
	unsigned char r;
	unsigned char null;  //暂时不需要透明度
}color;

typedef union 
{
	color rgb;
	unsigned int l;
}col;

int draw_point(int x0, int y0, col c)
{
	if((x0 < 0) || (x0 > info.xres_virtual))
		return -1;
	if((y0 < 0) || (y0 > info.yres_virtual))
		return -1;

	unsigned int * p = (unsigned int *)(p_fd + (y0 * info.xres_virtual + x0) * 4);
	*p = c.l;

	return 0;
}

int draw_h_line(int x0, int y0, int len, col c)
{
	int i = 0;
	for(i = 0; i < len; i++)
	{
		draw_point(x0 + i, y0, c);	
	}

	return 0;
}

int draw_v_line(int x0, int y0, int len, col c)
{
	int i = 0;
	for(i = 0; i < len; i++)
	{
		draw_point(x0, y0 + i, c);	
	}

	return 0;
}

int draw_cicle(int x0, int y0, int r, col c)
{
	float i=0;
	for(i=0;i<360;i+=0.1)
	{
		int x = r * cos(2 * pi * i/360) + x0;
		int y = r * sin(2 * pi * i/360) + y0;
		draw_point(x,y,c);
	}
}

int main(int argc, const char *argv[])
{
	//open
	int fd =  open("/dev/fb0", O_RDWR);
	if(fd < 0)
	{
		perror("open fd failed:");
		return fd;
	}

	//get_screen_info
	int ret = ioctl(fd, FBIOGET_VSCREENINFO, &info);
	if(ret < 0)
	{
		perror("ioctl failed:");
		return ret;
	}
	printf("xres = %d yres = %d\n",
			info.xres, info.yres);
	printf("xres_virtual = %d yres_virtual = %d\n",
			info.xres_virtual, info.yres_virtual);
	printf("bits_per_pixel = %d\n", info.bits_per_pixel);

	//mmap
	unsigned long size = info.xres_virtual * info.yres_virtual * info.bits_per_pixel / 8;
	p_fd = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
	if(NULL == p_fd)
	{
		perror("mmap failed:");
		return -3;
	}

	col c;
	c.rgb.r = 0xff;
	c.rgb.g = 0xff;
	c.rgb.b = 0x0;

	//draw_h_line(100, 100, 200, c);
	draw_cicle(100,200,120,c);

	//munmap
	munmap(p_fd, size);
	//close
	close(fd);
	return 0;
}

标签:__,映射,int,缓冲,unsigned,u32,y0,framebuffer
From: https://blog.csdn.net/qq_54094530/article/details/140779020

相关文章

  • 缓冲流
    Java的缓冲流是对字节流和字符流的一种封装,通过在内存中开辟缓冲区来提高I/O操作的效率。Java通过BufferedInputStream和BufferedOutputStream来实现字节流的缓冲,通过BufferedReader和BufferedWriter来实现字符流的缓冲。缓冲流的工作原理是将数据先写入缓冲区中,当缓......
  • .NET 高性能缓冲队列实现 BufferQueue
    目录前言适用场景功能说明使用示例BufferQueue内部设计概述Topic的隔离Partition的设计对并发的支持Partition的动态扩容Segment的回收机制Benchmark写入性能测试消费性能测试前言BufferQueue是一个用.NET编写的高性能的缓冲队列实现,支持多线程并发操作。项目是从moch......
  • FrameBuffer 应用编程-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子阿尔法开发板
    FrameBuffer应用编程什么是Framebuffer设备Framebuffer定义:Framebuffer是帧缓冲,指一块内存,用于保存一帧图像Linux系统中的Framebuffer:在Linux系统中,Framebuffer是一种显示驱动接口,抽象并屏蔽了不同显示设备的硬件细节,对应用层提供了一块显示内存(显存)Framebuf......
  • 嵌入式学习第9天——C语言运算符,程序设计结构,输入输出缓冲机制
    2024.7.25第九天笔记关于++混合操作,不同计算结果推理第一种编译结果:inti=5;intsum=(++i)+(++i)=6+7=13第二种编译结果:inti=5;intsum=(++i)+(++i)=6+7=7+7前面的7是因为后面i的变化被影响后,重新赋值=14第一种编译结果:inti=5;in......
  • 如何在 2 个 GPU 之间发送缓冲区?
    我尝试将缓冲区A和缓冲区B分配给GPU0,然后将它们(缓冲区A和缓冲区B)分配给GPU1,并运行它们添加A+B的内核,并将其分配给缓冲区D(我之前在GPU中分配)1)我的问题是它在python中不起作用,在pycuda中不起作用,在cup中不起作用。我在PyCuda中尝试了这段代码,......
  • 使用 FFpyplayer 帧和 QPixmap 以及 MPEG-TS 格式的 UDP 流时出现追赶延时缓冲和滞后
    我正在尝试根据此帖子中找到的代码来构建我的用例。但是,我在使用pythonFFpyPlayer时遇到了麻烦;对于传统的ffplay,我没有这些问题。运行我的应用程序时,我注意到一种追赶延时缓冲效果,视频播放速度显着加快,然后恢复到正常速度。在某些视频中,我发......
  • golang 无缓冲区通道的 range 操作
     对一个无缓冲通道(chan)进行range操作意味着想要迭代并消费通道中的所有值。但是,由于无缓冲通道的特性,这种操作具有特定的行为和潜在的副作用,主要体现在以下几点: 阻塞行为:当你开始对无缓冲通道进行range操作时,每次循环迭代都会尝试从通道接收一个值。如果通......
  • 木舟0基础学习Java的第十八天(IO流,字节流,字符流,缓冲)
    IO流正常使用流程:1.抛异常 2.资源读写 3.关闭资源(从后往前关)字节流:(拷贝推荐使用)开发中一般不会抛出异常用try{}catch(){}也不推荐字节流读中文FileInputStream:读FileInputStreamfs=newFileInputStream("e:/b.txt");//11111111为-1的补......
  • C/C++ 避免缓冲区溢出的措施
    在C/C++中,缓冲区溢出是一种常见的安全问题,可以导致程序崩溃或安全漏洞。为了避免缓冲区溢出,可以采取以下防范措施:使用安全的函数:使用strncpy(), strncat(), snprintf()等函数代替strcpy(), strcat(), sprintf()等,这些函数允许你指定最大复制的字符数,从而避免溢出。......
  • tryhackme-Buffer Overflow Prep(缓冲区溢出准备)
    前景概述最开始接触二进制方式是因为参加比赛缺少一个pwn手,慢慢的学习在二进制方面懂了很多,学习了C和C++、基本的汇编语法、pwndbg、ollydbg等调试工具,以及在做pwn题目是相关的工具pwntools,学习了栈相关的基本知识,栈溢出相关的一些姿势,例如:ret2text、ret2plt、ret2shellcode、......