目录
5)struct fd_var_screeninfo info;
项目实现
内容解析
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
结构体中包含了多个字段,用于描述屏幕的可变参数。以下是一些常用的字段:
xres
、yres
:分别表示屏幕的x轴和y轴分辨率(以像素为单位)。bits_per_pixel
:表示每个像素的颜色深度(以比特为单位)。red
、green
、blue
、transp
:这些结构体描述了RGB(红绿蓝)和透明度(如果有的话)的颜色分量在显存中的位置和长度。xres_virtual
、yres_virtual
:分别表示虚拟屏幕的x轴和y轴分辨率。虚拟屏幕通常比实际屏幕大,用于双缓冲等机制。xoffset
、yoffset
:表示实际屏幕在虚拟屏幕中的偏移量。
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 退出