• Linux FrameBuffer(二)- VMware虚拟机的Ubuntu系统FrameBuffer画图


    目录
    一、确认/dev/fb0文件存在
    二、Ubuntu进入命令行模式
    三、在命令行模式下,执行FrameBuffer画图程序。
    四、虚拟机Ubuntu的FrameBuffer(/dev/fb0)画图的问题


    一、确认/dev/fb0文件存在

    在Ubuntu上画图,需要对应的FrameBuffer设备文件的支持,一般FrameBuffer的设备文件路径为/dev/fb开头的,可能是/dev/fb0/dev/fb1等,所以进行下面的步骤之前要先确保/dev/fb*的文件是否存在。

    如果你的Ubuntu版本比较旧,没有/dev/fb0的设备文件的话,可以参照这个文章:虚拟机的 Ubuntu 没有 /dev/fb0 的解决办法


    二、Ubuntu进入命令行模式

    Ubuntu有命令行模式图形界面模式l,在图形界面模式时,即使执行了在/dev/fb0画图的程序也无法看到效果,所以执行FrameBuffer画图程序时,需要进入命令行。

    可以通过按快捷键 Ctrl + Alt + F1来切换到命令行模式,通过按Ctrl + Alt + F7切换到图形界面模式。切换到命令行模式也可以Ctrl + Alt + (F1~F6任意一个)去切换。


    三、在命令行模式下,执行FrameBuffer画图程序。

    如果你自己有已经写好的FrameBuffer程序,经过前面两个步骤,应该可以执行跑起来了看到画图的效果了。运行程序时,需要加sudo,不然没有权限打开设备文件。如果没有程序或者跑起来有问题,可以复制下面代码编译执行,执行结果就是在左上角画一个30*30的方块,每秒变一个颜色,如图:
    在这里插入图片描述

    // framebuffer.c
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    unsigned int fb_byteW=0, fb_byteH=0; // 用字节表示的宽度和高度
    unsigned int bytesPerPixel = 0;	// 一个像素占用的字节数
    char *fbMapMem = NULL;
    
    void fillRect(int color, int x, int y, int w, int h)
    {
    	int i=0, j=0, offset = 0;
    	if(bytesPerPixel==4)
    	{
    		for(i=0; i<h; i++)
    		{
    			offset = x*bytesPerPixel + (y+i)*fb_byteW;
    			for(j=0; j<w; j++)
    			{
    				int *tmp = (int *)&fbMapMem[offset];
    				*tmp = color;
    				offset += bytesPerPixel;
    			}
    		}
    	}
    	else
    		printf("error bytesPerPixel=%d\n", bytesPerPixel);
    }
    
    int main(int argc, char *argv[])
    {
    	// 1.打开设备
    	char fbPath[64] = "/dev/fb0";
    	int framebuf_fd = open(fbPath, O_RDWR);
    	if ( framebuf_fd < 0 ) {
            printf("[%s:%d] open %s error \n", __FILE__,__LINE__,fbPath);
            return -1;
        }
    	
    	// 2.获取设备固定参数
    	struct fb_fix_screeninfo finfo;
    	if (ioctl(framebuf_fd, FBIOGET_FSCREENINFO, &finfo) < 0)
        {
            fprintf(stderr, "ioctl FBIOGET_FSCREENINFO err \r\n");
            return -1;
        }
    
    	// 3.1 获取虚拟参数
    	struct fb_var_screeninfo vinfo;
        if (ioctl(framebuf_fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
        {
            fprintf(stderr, "ioctl FBIOGET_VSCREENINFO err \r\n");
            return -1;
        }
    
    	// 3.2 设置虚拟参数
    	bytesPerPixel = vinfo.bits_per_pixel / 8;
    	vinfo.xres = vinfo.xres_virtual = finfo.line_length/bytesPerPixel;
    	if (ioctl(framebuf_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0)
        {
            fprintf(stderr, "ioctl FBIOPUT_VSCREENINFO err \r\n");
            return -1;
        }
    	
    	fb_byteW = vinfo.xres * bytesPerPixel;
    	fb_byteH = vinfo.yres * bytesPerPixel;
    	printf("[line:%d] line_length=%d res=[%dx%d], Bpp=%d ByteWH=[%d %d]\n",__LINE__,finfo.line_length,vinfo.xres,vinfo.yres,bytesPerPixel,fb_byteW, fb_byteH);
    	
    	// 4.映射物理显存到用户虚拟内存空间
    	unsigned long size = vinfo.xres*vinfo.yres*bytesPerPixel;
        if (NULL == (fbMapMem=(char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, framebuf_fd, 0)) )
        {
            fprintf(stderr, "mmap size %ld err \r\n", size);
            return -1;
        }
    	
    	// 5.操作虚拟内存,完成具体绘制任务,每隔一秒画一个颜色的正方形
    	while(1)
    	{
    		fillRect(0xff0000,0,0,30,30);// 红色
    		sleep(1);
    		fillRect(0x00ff00,0,0,30,30);// 绿色
    		sleep(1);
    		fillRect(0x0000ff,0,0,30,30);// 蓝色
    		sleep(1);
    	}
    	
    	// 6.解除显存映射
    	munmap(fbMapMem, size);
    	
    	// 7.关闭设备
    	close(framebuf_fd);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    四、虚拟机Ubuntu的FrameBuffer(/dev/fb0)画图的问题

    如果你执行画图程序后,能出来东西,但画出来的图不是自己想要的,感觉分辨率没对应上,像下图一样。
    在这里插入图片描述
    原因可能就是设备固定参数(struct fb_fix_screeninfo)的line_length字段字节数,跟虚拟参数(struct fb_var_screeninfo)的分辨率的宽xres字段对不上。需要在你的程序里添加这句代码,再设置虚拟参数,可以参考上面代码。

    vinfo.xres = vinfo.xres_virtual = finfo.line_length/bytesPerPixel;
    
    • 1

    在这里插入图片描述

  • 相关阅读:
    1.IAR-8051安装
    c++ qt 绘制设备
    关于我写的IDEA插件能一键生成service,mapper....这件事(附源码)
    【九】http服务器开发--高并发的实现http服务器示例
    设计模式:享元模式
    Elasticsearch同义词最佳实践
    获取 Adobe Creative Cloud 2023 创意应用软件,解锁无限创造力
    字节跳动测试岗,3面都过了,HR告诉我这个原因被刷了...
    SpringBoot+Vue项目实现疫情期间社区出入管理系统
    Python基础
  • 原文地址:https://blog.csdn.net/wkd_007/article/details/128013718