第18章LCD设备驱动之帧缓冲设备的用户空间访问

18.9 帧缓冲设备的用户空间访问

        通过/dev/fbn,应用程序可进行的针对帧缓冲设备的操作主要有如下几种。

        读/写 dev/fbn:相当于读/写屏幕缓冲区。例如用 cp /dev/fb0 tmp 命令可将当前屏幕的内容复制到一个文件中,而命令 cp tmp > /dev/fb0 则将图形文件 tmp 显示在屏幕上。

        映射操作:对于帧缓冲设备,可通过 mmap()映射操作将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读/写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。而且若干个进程可以

映射到同一个显示缓冲区。实际上,使用帧缓冲设备的应用程序都是通过映射操作来显示图形的。

        I/O 控制:对于帧缓冲设备,对设备文件的 ioctl()操作可读取/设置显示设备及屏幕的参数,如分辨率、显示颜色数、屏幕大小等。

        如图 18.6 所示,在应用程序中,操作/dev/fbn 的一般步骤如下。


图18.6 用户空间访问帧缓冲设备的流程

        (1)打开/dev/fbn 设备文件。

        (2)用 ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数和偏移。根据屏幕参数可计算屏幕缓冲区的大小。

        (3)将屏幕缓冲区映射到用户空间。

        (4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。

        代码清单 18.15 所示为一段用户空间访问帧缓冲设备显示缓冲区的范例,包含打开和关闭帧缓冲设备、得到和设置可变参数、得到固定参数、生成与 BPP (每个像素点的比特数)对应的帧缓冲数据及填充显示缓冲区。

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

int main(void)
{

int fbfd = 0;
struct fb_var_screeninfo vinfo;
unsigned long screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
int i = 0;


// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (!fbfd) {
perror("Error: cannot open framebuffer device.\n");
exit(1);
}

printf("The framebuffer device was opened successfully.\n");


// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
perror("Error reading variable information.\n");
exit(1);
}
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);

// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * 2;

// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
fbfd, 0);
if ((int)fbp == -1) {
perror("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");

// Draw 3 rect with graduated RED/GREEN/BLUE
for (i = 0; i < 3; i++) {
for (y = i * (vinfo.yres / 3); y < (i + 1) * (vinfo.yres / 3); y++) {
for (x = 0; x < vinfo.xres; x++) {
long location = x * 2 + y * vinfo.xres * 2;
int r = 0, g = 0, b = 0;
unsigned short rgb;
if (i == 0)
r = ((x * 1.0) / vinfo.xres) * 32;

if (i == 1)
g = ((x * 1.0) / vinfo.xres) * 64;

if (i == 2)
b = ((x * 1.0) / vinfo.xres) * 32;

rgb = (r << 11) | (g << 5) | b;
*((unsigned short*)(fbp + location)) = rgb;
}
}
}

munmap(fbp, screensize);
close(fbfd);

return 0;
}



猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/80756932
今日推荐