实践项目------ 1部分内容解析

目录

内容解析

1)显存

2)显存与内存的差异

3)显示器与内存的关系

4)帧缓存  Frame Buffer

framebuffer 操作流程:

1.open 

2.获取frame相关信息( ioctl )

3.映射显存地址(mmap)

4.向显存写内容(写到映射的用户空间)

5.解除映射(munmmap)

6.关闭 close(fd)

5)struct fd_var_screeninfo info;

 结构体字段解释

  1 . 实现画点​编辑

2 . 实现画横线​编辑

3 . 实现画竖线​编辑

4 . 实现画圆 ​编辑


项目实现







内容解析

1)显存

       显存,全称为显示内存(Video Memory)或视频内存(Graphic Memory),是显卡上用来存储图形处理所需数据的一种专用存储器。它是显卡的重要组成部分,直接影响显卡的性能表现。

      显存的主要作用是存储显示芯片处理过或即将提取的渲染数据,包括帧缓冲、Z缓冲(决定物体前后关系)、纹理等。这些数据在处理完毕后会被送到RAMDAC(数模转换器)中进行数模转换,再输出到显示器上形成图像。因此,显存的容量、速度和带宽等因素都会直接影响到显卡处理图形数据的能力,进而影响显卡的性能。

2)显存与内存的差异

一、功能与服务对象

  • 显存:显存是显卡上用于存储图形处理所需数据的专用存储器,也被称为“显卡内存”、“GPU内存”或“图形内存”。它主要服务于GPU(图形处理单元),用于暂存GPU处理过程中的图形数据,如帧缓冲、Z缓冲、纹理等。
  • 内存:内存是计算机的重要部件,用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行。内存主要服务于CPU和系统,用于缓存程序和数据,以加快计算机的运行速度。

二、存储速度与带宽

  • 显存:随着技术的发展,现代显卡通常采用GDDR5、GDDR6等高速显存技术,这些显存具有更高的带宽和更快的访问速度。例如,GDDR6显存的速度可以高达72GB/s,以满足显卡处理大量图形数据的需求。
  • 内存:虽然内存的速度也在不断提升,但相比于显存,其带宽和访问速度通常较低。例如,DDR4内存的速度在25.6GB/s左右,远低于高端GDDR6显存的速度。

三、容量与扩展性

  • 显存:显存容量是固定的,由显卡厂商根据显卡的设计和定位来配置。消费者在购买显卡时,其显存容量就已经确定,无法自行添加或扩展。
  • 内存:消费级电脑的内存则具有较好的扩展性。内存插槽的数量和类型决定了内存的容量上限,用户可以根据需求和主板的插槽数量来增减内存容量。

四、技术特点

  • 显存:显存的电压通常较高,频率也较高,具有“高密度寻址能力”(单位颗粒容量提高)和“高速传输能力”(更大的数据传输率)两个特点。这些特点使得显存能够更快地处理图形数据,满足高性能图形处理的需求。
  • 内存:内存的技术特点则主要体现在其作为CPU与外部存储器之间桥梁的作用上。内存的性能直接影响到计算机的整体运行速度和稳定性。

3)显示器与内存的关系

4)帧缓存  Frame Buffer

一、定义与作用

       帧缓存本质上是一块内存或者硬件中的空间,用于存储需要渲染图像的像素相关信息。在渲染管线中,帧缓存是在实际渲染到屏幕之前的最后一个步骤,负责保存处理后的图像数据,以便后续输出到显示器上。帧缓存的存在使得在渲染过程中可以对图像进行后期处理(如抗锯齿、颜色校正等),同时也支持离屏渲染,即渲染过程不在屏幕上直接进行,而是在帧缓存中完成后再输出。

二、组成与类型

帧缓存是一个集合概念,其内部通常包括多个缓存区,如:

  • 颜色缓存(Color Buffer):记录像素的颜色信息,是帧缓存的主体部分。
  • 深度缓存(Z Buffer):记录像素的深度值,用于深度测试,确定像素的遮挡关系。
  • 模板缓存(Stencil Buffer):限制渲染区域,与深度缓存一起创造不同的渲染效果。

此外,根据不同的应用场景和需求,帧缓存还可以包含其他类型的缓存区。

三、工作原理

       在图形渲染过程中,显示芯片处理完图形数据后,会将结果保存到帧缓存中。然后,根据输出时序需求,从帧缓存中读取图像数据并输出到显示器上。对于多路视频输入和输出系统,通常需要使用多个帧缓存来存储和处理视频数据。

四、应用场景

      帧缓存广泛应用于计算机图形处理、视频处理、游戏开发等领域。例如,在游戏开发中,帧缓存用于存储游戏画面的每一帧数据,确保游戏画面的流畅性和稳定性。同时,帧缓存还支持高级图形效果的处理,如动态光影、环境光遮蔽等。

framebuffer 操作流程:

1.open 

2.获取frame相关信息( ioctl )

  • request:用户程序对设备的控制命令,它是一个无符号长整型(unsigned long),用于指示要执行的具体操作。
  • ...:可变参数,用于传递额外的数据给驱动程序,具体取决于request命令的需求。

FBIOGET_VSCREENINFO是Linux framebuffer编程中一个重要的ioctl命令,它允许用户程序获取屏幕的可变参数信息,为进一步的显示操作提供基础

3.映射显存地址(mmap)


PROT_EXEC:映射区域可被执行 

PROT_READ:映射区域可被读写

PROT_WRITE:映射区域可被写入

PROT_NONE:映射区域不能存取

MAP_SHARED:

      当使用 MAP_SHARED 标志时,映射的内存区域和底层对象(如文件)是共享的。这意味着对该内存区域的任何修改都会反映到底层对象中,并且如果底层对象被其他进程以 MAP_SHARED 方式映射,那么这些修改也会对其他进程可见。这对于进程间通信(IPC)特别有用,因为它允许不同进程通过修改共享内存区域来交换数据。

MAP_PRIVATE:

与 MAP_SHARED 不同,MAP_PRIVATE 标志指示映射的内存区域是私有的。对该内存区域的任何修改都不会反映到底层对象中。这意味着,如果你修改了一个以 MAP_PRIVATE 方式映射的文件内存区域,这些修改只会在当前进程的内存中表示,不会写回到文件中。这可以用于创建一个文件的临时副本,以便在不修改原始文件的情况下对其进行操作。

eg:

假设你有一个文件,你想要在内存中映射它以进行读取和写入操作。

  • 如果你使用 MAP_SHARED,你可以与其他进程共享对文件的修改,或者仅仅是为了确保任何对映射内存的修改都会写回到文件中。
  • 如果你使用 MAP_PRIVATE,你可能想要对文件数据进行一些临时的、不希望写回到文件的修改,或者你想避免多个进程同时写入同一个文件可能导致的冲突。
4.向显存写内容(写到映射的用户空间)
5.解除映射(munmmap)

6.关闭 close(fd)

5)struct fd_var_screeninfo info;

struct fb_var_screeninfo {
    __u32 xres; /*可见屏幕一行有多少个像素点*/
    __u32 yres; /*可见屏幕一列有多少个像素点*/
    __u32 xres_virtual; /*虚拟屏幕一行有多少个像素点*/
    __u32 yres_virtual; /*虚拟屏幕一列有多少个像素点*/
    __u32 xoffset; /*虚拟到可见屏幕之间的行偏移*/
    __u32 yoffset; /*虚拟到可见屏幕之间的列偏移*/
    __u32 bits_per_pixel; /*每个像素的位数即BPP*/
    __u32 grayscale; /*非0时,指的是灰度*/
    struct fb_bitfield red; /*fb缓存的R位域*/
    struct fb_bitfield green; /*fb缓存的G位域*/
    struct fb_bitfield blue; /*fb缓存的B位域*/
    struct fb_bitfield transp; /*透明度*/
    __u32 nonstd; /* != 0 非标准像素格式*/
    __u32 activate;
    __u32 height; /*高度*/
    __u32 width; /*宽度*/
    __u32 accel_flags;
    /*定时:除了pixclock本身外,其他的都以像素时钟为单位*/
    __u32 pixclock; /*像素时钟(皮秒)*/
    __u32 left_margin; /*行切换,从同步到绘图之间的延迟*/
    __u32 right_margin; /*行切换,从绘图到同步之间的延迟*/
    __u32 upper_margin; /*帧切换,从同步到绘图之间的延迟*/
    __u32 lower_margin; /*帧切换,从绘图到同步之间的延迟*/
    __u32 hsync_len; /*水平同步的长度*/
    __u32 vsync_len; /*垂直同步的长度*/
    __u32 sync;
    __u32 vmode;
    __u32 rotate;
    __u32 reserved[5]; /*保留*/
};

 结构体字段解释

struct fb_var_screeninfo结构体中包含了多个字段,用于描述屏幕的可变参数。以下是一些常用的字段:

  • xresyres:分别表示屏幕的x轴和y轴分辨率(以像素为单位)。
  • bits_per_pixel:表示每个像素的颜色深度(以比特为单位)。
  • redgreenbluetransp:这些结构体描述了RGB(红绿蓝)和透明度(如果有的话)的颜色分量在显存中的位置和长度。
  • xres_virtualyres_virtual:分别表示虚拟屏幕的x轴和y轴分辨率。虚拟屏幕通常比实际屏幕大,用于双缓冲等机制。
  • xoffsetyoffset:表示实际屏幕在虚拟屏幕中的偏移量。

  1 . 实现画点

2 . 实现画横线

3 . 实现画竖线

4 . 实现画圆 

详细代码:

  1 #include <stdio.h>  //标准输入输出,用于打印
  2 #include <sys/stat.h>
  3 #include <sys/types.h>
  4 #include <fcntl.h>  // 以上三个用于文件操作,如打开帧缓冲设备
  5 #include <sys/ioctl.h>
  6 #include <linux/fb.h> //用于ioctl操作,获取帧缓冲设备的屏幕信息
  7 #include <sys/mman.h> //用于内存映射(mmap)
  8 #include <unistd.h>
  9 #include <stdlib.h>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
 10 
 11 struct fb_var_screeninfo info; 
    //用于存储通过ioctl获取的帧缓冲设备的屏幕信息
 12 unsigned char * p_fd = NULL; 
    //指向映射到帧缓冲设备的内存区域的指针
 13 
 14 typedef struct __color
 15 {
 16     unsigned char b;
 17     unsigned char g;
 18     unsigned char r;
 19     unsigned char null;
 20 }color;
 21 
 22 typedef union
 23 {
 24     color rgb;
 25     unsigned int l;
 26 }col;
 27 
 28 //画点
 29 int draw_point(int x0, int y0, col c) //画点
 30 {
 31     if((x0 < 0) || (x0 > info.xres_virtual))
 32         return -1;
 33     if((y0 < 0) || (y0 > info.yres_virtual))
 34         return -1;
 35 
 36     unsigned int * p = (unsigned int *)(p_fd + (y0 * info.xres_virtual + x0) * 4);
 37     *p = c.l;
 38 
 39     return 0;
 40 }
 41 
 42 //画横线
 43 int draw_h_line(int x0, int y0, int len, col c)
 44 {
 45     int i = 0;
 46     for(i = 0; i < len; i++)
 47     {
 48         draw_point(x0 + i, y0, c);
 49     }
 50 
 51     return 0;
 52 }
 53 
 54 //画竖线
 55 int draw_v_line(int x0, int y0, int len, col c)
 56 {
 57     int i = 0;
 58     for(i = 0; i < len; i++)
 59     {
 60         draw_point(x0, y0 + i, c);
 61     }
 62 
 63     return 0;
 64 }
 65 
 66 //画圆
 67 int draw_cicle(int x0, int y0, int r, col c)
 68 {
 69 
 70 }
 71 
 72 int main(int argc, const char *argv[])
 73 {
 74     //open
 75     int fd =  open("/dev/fb0", O_RDWR);
 76     if(fd < 0)
 77     {
 78         perror("open fd failed:");
 79         return fd;
 80     }
 81 
 82     //get_screen_info 通过ioctl调用FBIOGET_VSCREENINFO获取帧缓冲设备的屏幕信息,并打印分 
        辨率和每像素位数
 83     int ret = ioctl(fd, FBIOGET_VSCREENINFO, &info);
 84     if(ret < 0)
 85     {
 86         perror("ioctl failed:");
 87         return ret;
 88     }
 89     printf("xres = %d yres = %d\n",
 90             info.xres, info.yres);
 91     printf("xres_virtual = %d yres_virtual = %d\n",
 92             info.xres_virtual, info.yres_virtual);
 93     printf("bits_per_pixel = %d\n", info.bits_per_pixel);
 94 
 95     //mmap
 96     unsigned long size = info.xres_virtual * info.yres_virtual * info.bits_per_pixel / 8;
 97     p_fd = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
 98     if(NULL == p_fd)
 99     {
100         perror("mmap failed:");
101         return -3;
102     }
103 
104     col c;
105     c.rgb.r = 0xff;
106     c.rgb.g = 0xff;
107     c.rgb.b = 0xff;
108 
109     draw_h_line(100, 100, 200, c);
110     draw_h_line(200, 200, 200, c);
111     draw_v_line(100, 100, 200, c);
112     draw_v_line(200, 200, 200, c);
113 
114     //munmap
115     munmap(p_fd, size);
116     //close
117     close(fd);
118     return 0;
119 }
120 
~      

 补加+

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

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;
}

#define PI 3.1415926

int draw_circle(int x0, int y0, int r, col c)
{
	double si = 0;
	unsigned int x = 0;
	unsigned int y = 0;
	for(si = 0; si < 360; si+=0.1)
	{
		x = x0 + r * cos(2 * PI * si / 360);
		y = y0 + r * sin(2 * PI * si / 360);
		draw_point(x, y, c);
	}
	return 0;
}

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_h_line(200, 200, 200, c);
	draw_v_line(100, 100, 200, c);
	draw_v_line(200, 200, 200, c);
	draw_circle(400, 300, 300, c);
	//munmap
	munmap(p_fd, size);
	//close
	close(fd);
	return 0;
}

 ctrl + alt +F5 进入
 ctrl + alt 显示鼠标
 ctrl + Fn + alt + F1 退出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值