当前位置: 首页 > news >正文

在虚拟机ubuntu上修改framebuffer桌面不能显示图像

目录

一、测试程序

二、排查原因

三、为什么 Xorg 会导致程序无法工作?


一、测试程序

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>static int width; //LCD X 分辨率
static int height; //LCD Y 分辨率
static unsigned int *screen_base = NULL; //映射后的显存基地址
/********************************************************************
* 函数名称: lcd_draw_point
* 功能描述: 打点
* 输入参数: x, y, color
* 返 回 值: 无
********************************************************************/
static void lcd_draw_point(unsigned int x, unsigned int y, unsigned int color)
{/* 对传入参数的校验 */if (x >= width)x = width - 1;if (y >= height)y = height - 1;/* 填充颜色 */screen_base[y * width + x] = color;
}
/********************************************************************
* 函数名称: lcd_draw_line
* 功能描述: 画线(水平或垂直线)
* 输入参数: x, y, dir, length, color
* 返 回 值: 无
********************************************************************/
static void lcd_draw_line(unsigned int x, unsigned int y, int dir,
unsigned int length, unsigned int color)
{unsigned int end;unsigned long temp;/* 对传入参数的校验 */if (x >= width)x = width - 1;if (y >= height)y = height - 1;/* 填充颜色 */temp = y * width + x;//定位到起点if (dir) { //水平线end = x + length - 1;if (end >= width)end = width - 1;for ( ; x <= end; x++, temp++)screen_base[temp] = color;}else { //垂直线end = y + length - 1;if (end >= height)end = height - 1;for ( ; y <= end; y++, temp += width)screen_base[temp] = color;}
}
/********************************************************************
* 函数名称: lcd_draw_rectangle
* 功能描述: 画矩形
* 输入参数: start_x, end_x, start_y, end_y, color
* 返 回 值: 无
********************************************************************/
static void lcd_draw_rectangle(unsigned int start_x, unsigned int end_x,
unsigned int start_y, unsigned int end_y,
unsigned int color)
{int x_len = end_x - start_x + 1;int y_len = end_y - start_y - 1;lcd_draw_line(start_x, start_y, 1, x_len, color);//上边lcd_draw_line(start_x, end_y, 1, x_len, color); //下边lcd_draw_line(start_x, start_y + 1, 0, y_len, color);//左边lcd_draw_line(end_x, start_y + 1, 0, y_len, color);//右边
}
/********************************************************************
* 函数名称: lcd_fill
* 功能描述: 将一个矩形区域填充为参数 color 所指定的颜色
* 输入参数: start_x, end_x, start_y, end_y, color
* 返 回 值: 无
********************************************************************/
static void lcd_fill(unsigned int start_x, unsigned int end_x,
unsigned int start_y, unsigned int end_y,
unsigned int color)
{unsigned long temp;unsigned int x;/* 对传入参数的校验 */if (end_x >= width)end_x = width - 1;if (end_y >= height)end_y = height - 1;/* 填充颜色 */temp = start_y * width; //定位到起点行首for ( ; start_y <= end_y; start_y++, temp+=width) {for (x = start_x; x <= end_x; x++)screen_base[temp + x] = color;}
}int main(int argc, char *argv[])
{struct fb_fix_screeninfo fb_fix;struct fb_var_screeninfo fb_var;unsigned int screen_size;int fd;/* 打开 framebuffer 设备 */if (0 > (fd = open("/dev/fb0", O_RDWR))) {perror("open error");exit(EXIT_FAILURE);}/* 获取参数信息 */ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);printf("Solution: %d*%d\n""pixel depth bpp: %d\n""Number of bytes in a row: %d\n""Pixel format: R<%d %d> G<%d %d> B<%d %d> A<%d %d>\n",fb_var.xres, fb_var.yres, fb_var.bits_per_pixel,fb_fix.line_length,fb_var.red.offset, fb_var.red.length,fb_var.green.offset, fb_var.green.length,fb_var.blue.offset, fb_var.blue.length, fb_var.transp.offset, fb_var.transp.length);screen_size = fb_fix.line_length * fb_var.yres;width = fb_fix.line_length / (fb_var.bits_per_pixel / 8);height = fb_var.yres;/* 将显示缓冲区映射到进程地址空间 */screen_base = mmap(NULL, screen_size, PROT_WRITE, MAP_SHARED, fd, 0);if (MAP_FAILED == (void *)screen_base) {perror("mmap error");close(fd);exit(EXIT_FAILURE);}/* 画正方形方块 */int w = height * 0.25;//方块的宽度为 1/4 屏幕高度lcd_fill(0, fb_var.xres-1, 0, height-1, 0x0); //清屏(屏幕显示黑色)lcd_fill(0, w, 0, w, 0xFF0000); //红色方块lcd_fill(fb_var.xres-w, fb_var.xres-1, 0, w, 0xFF00); //绿色方块lcd_fill(0, w, height-w, height-1, 0xFF); //蓝色方块lcd_fill(fb_var.xres-w, fb_var.xres-1, height-w, height-1, 0xFFFF00);//黄色方块/* 画线: 十字交叉线 */lcd_draw_line(0, height * 0.5, 1, fb_var.xres, 0xFFFFFF);//白色线lcd_draw_line(fb_var.xres * 0.5, 0, 0, height, 0xFFFFFF);//白色线/* 画矩形 */unsigned int s_x, s_y, e_x, e_y;s_x = 0.25 * fb_var.xres;s_y = w;e_x = fb_var.xres - s_x;e_y = height - s_y;for ( ; (s_x <= e_x) && (s_y <= e_y);s_x+=5, s_y+=5, e_x-=5, e_y-=5)lcd_draw_rectangle(s_x, e_x, s_y, e_y, 0xFFFFFF);/* 退出 */munmap(screen_base, screen_size); //取消映射close(fd); //关闭文件exit(EXIT_SUCCESS); //退出进程
}

执行结果:

lientek@ubuntu:/home/linux_test/lcd$ sudo ./demo 
Solution: 800*600
pixel depth bpp: 32
Number of bytes in a row: 4704
Pixel format: R<16 8> G<8 8> B<0 8> A<0 0>

桌面无图形绘制效果

二、排查原因

        程序无法在虚拟机的 Ubuntu 桌面上绘制图形,主要原因在于现代 Linux 桌面环境(如 Ubuntu 使用的 GNOME、Unity 等)通常运行在 X Window 系统或 Wayland 等显示服务器上,而程序直接操作了/dev/fb0(帧缓冲设备),这在桌面环境中存在一些兼容性问题。

        显示服务器冲突:在桌面环境中,Xorg 或 Wayland 已经独占了帧缓冲设备,普通用户程序无法直接访问/dev/fb0进行绘图

确定当前使用的是 Xorg 还是 Wayland:

alientek@ubuntu:/home/linux_test/lcd$ echo $XDG_SESSION_TYPE
x11

三、为什么 Xorg 会导致程序无法工作?

Xorg 作为显示服务器,会独占 /dev/fb0 设备来管理桌面显示。当 Xorg 运行时:

  1. 它会优先打开并锁定 /dev/fb0,程序虽然可能成功 open("/dev/fb0")(取决于权限),但写入的内容会被 Xorg 的桌面渲染覆盖(因为 Xorg 会持续刷新屏幕)。

  2. 程序直接操作显存的像素数据,但 Xorg 有自己的渲染管线(如通过显卡驱动、窗口管理器等),两者的绘制逻辑冲突,导致你的图形无法显示在桌面。

http://www.xdnf.cn/news/1205659.html

相关文章:

  • STM32F4—电源管理器
  • YOLOv11改进:添加SCConv空间和通道重构卷积二次创新C3k2
  • 时间数字转换器TDC的FPGA方案及核心代码
  • 数分思维10:用户增长
  • 小智源码分析——音频部分(二)
  • 机器学习sklearn:决策树的参数、属性、接口
  • mp核心功能
  • S7-200 SMART 通过本体 RS485 口与 DP01 上传 / 下载程序(网口故障)
  • Java项目:基于SSM框架实现的进销存管理系统【ssm+B/S架构+源码+数据库+毕业论文+远程部署】
  • 我从 Web2 转型到 Web3 的 9 条经验总结
  • 架构实战——互联网架构模板(“存储层”技术)
  • fchown/fchownat系统调用及示例
  • 坚鹏:AI智能体培训是知行学成为AI智能体创新应用引领者的基础
  • 3DGRUT: 革命性的3D高斯粒子光线追踪与混合光栅化技术深度解析
  • Item18:让接口容易被正确使用,不易被误用
  • 鱼皮项目简易版 RPC 框架开发(二)
  • JavaScript:10个数组方法/属性
  • ROS2入门之开发环境搭建
  • 【C++】手搓一个STL风格的vector容器
  • vue如何在data里使用this
  • 屏幕晃动机cad【4张】三维图+设计说明书
  • Java面试宝典:MySQL8新特性
  • 软工八将:软件开发全流程核心角色体系解析
  • kubectl中的yaml配置详解
  • 【Unity游戏】——1.俄罗斯方块
  • 【大模型LLM】梯度累积(Gradient Accumulation)原理详解
  • 软件设计师-知识点记录
  • creating and using sequence
  • AI论文阅读方法+arixiv
  • Redis未授权访问的利用的几种方法原理以及条件