记一个framebuffer显示混乱的低级错误

news2024/12/15 23:32:45

记一个framebuffer显示混乱的低级错误

由于framebuffer的基础知识不扎实,这个任务上我多卡了两天,差点把我搞死,于此记录为后鉴。

打算用awtk做一个多进程项目,计划把framebuffer的内容通过websocket输出到浏览器上去显示画面, 架构大概为:

browser部署项目<---websocket<------framebuffer输出程序

用于输出framebuffer的项目在公司的嵌入式设备平台上显示良好:

image-20241214104234183

但是换到ubuntu服务器上部署时,在浏览器上显示,却变成了这样:

image-20241214104526302

检查framebuffer输出程序内部代码,mock数据给跟fb打交道的中间bitmap变量,然后再推流:

void update_g_bitmap_backgroud() {
	rect_t r = rect_init(0, 0, g_bitmap->w, g_bitmap->h);
	char *shared_data = LibFrameBufferGet(USE_FB_ID)->fbdata;  

	bitmap_t temp_bmp;
	bitmap_init(&temp_bmp, 800, 480, BITMAP_FMT_BGRA8888, shared_data);
	// ******* add
	rect_t temp_r = rect_init(0, 0, temp_bmp.w / 3, temp_bmp.h);
	image_fill(&temp_bmp, &temp_r, color_init(0, 0, 255 , 255));

	temp_r = rect_init(temp_bmp.w / 3, 0, temp_bmp.w / 3, temp_bmp.h);
	image_fill(&temp_bmp, &temp_r, color_init(0, 255, 0 , 255));

	temp_r = rect_init(temp_bmp.w * 2 / 3, 0, temp_bmp.w / 3, temp_bmp.h);
	image_fill(&temp_bmp, &temp_r, color_init(255, 0,  0, 255));
	// ********
	helper_bitmap_bgra8888_to_rgba8888(g_bitmap, &temp_bmp);
	bitmap_deinit(&temp_bmp);
}

浏览器上正常显示:

image-20241214114746960

那看来是获取fb这段的逻辑或者输出到fb的程序出了问题,但是检查一天,并未发现明显的错误,这时候通过awtk-linux-fb的输出日志注意到一个现象,我之前用的测试机器的line_length是3200,像素显示位数32 / 8 = 4 pixel, 正好对应机器显示分辨率xres= 3200/ 4 = 800:

app_root=./res
devices_load : path = file:///home/zhangdalin/AWStudioProjects/kp25sweb/process/Awtk_GamiWebDisplayStream/config/devices.json
devices[0]: path = /dev/fb0, type = fb
devices[1]: path = /dev/dri/card0, type = drm
devices[2]: path = /dev/input/event1, type = input
devices[3]: path = /dev/input/event2, type = mouse
fb_info_t: /dev/fb0
xres=800 yres=480
xres_virtual=800 yres_virtual=480
bits_per_pixel=32 line_length=3200
fb_info_t: red(16 8) green(8 8) blue(0 8)
xpanstep=1 ywrapstep=0
fb_size=768000 fb_total_size=1536000 fb_nr=2 smem_len=1536000
fb_open clear
fb_open ok
run in vmware and fix FBIOPAN_DISPLAY block issue
=========fb_number=2
ratio=1.000000 800 480
ratio=1.000000 800 480

而在ubuntu机器上,同样像素字节数4位,line_length=4704对应虚拟分辨率xres_virtual=4704 / 4 = 1176。

app_root=./res
devices_load : path = file:///home/zhangdalin/AWStudioProjects/kp25sweb/process/Awtk_GamiWebDisplayStream/config/devices.json
devices[0]: path = /dev/fb0, type = fb
devices[1]: path = /dev/dri/card0, type = drm
devices[2]: path = /dev/input/event1, type = input
devices[3]: path = /dev/input/event2, type = mouse
fb_info_t: /dev/fb0
xres=800 yres=600
xres_virtual=1176 yres_virtual=885
bits_per_pixel=32 line_length=4704
fb_info_t: red(16 8) green(8 8) blue(0 8)
xpanstep=1 ywrapstep=0
fb_size=2257920 fb_total_size=4163040 fb_nr=2 smem_len=4163040
fb_open clear
fb_open ok
run in vmware and fix FBIOPAN_DISPLAY block issue
=========fb_number=2
ratio=1.000000 800 600
ratio=1.000000 800 600

这时候已经接近线索了,可惜framebuffer基础没怎么过,以为是分辨率不一样的问题,还用fbset去改,结果当然是无功而返,实际上分辨率设多少都只是放缩画布的大小,只要在项目的设置里面设定了分辨率800x480, 那它就会以(0,0)起点绘制一个800x480的画面。

比如fbset设置分辨率1024x768的情况:

image-20241214111021491

fbset搞了半天,始终没有找到问题的解决方法,干脆想把ubuntu虚拟机的fb设置改成和机器一致,但fb设置属于linux驱动范畴,已经超出了我的能力,眼看这个任务卡到明天毫无头绪,就这么卡死了?

现在想起来我是忽略了这几个点:

  • framebuffer的读取方式是从左到右,从上到下的

  • framebuffer的参数分variable和fix两类,fbset能修改的是xres, yres, xres_virtual这类的,但是line_length和smem_len都属于fix类参数,fbset改不了

  • awtk中的bitmap_init函数是直接引入外来的一维数组指针的,读取方式和fb一样,但是我想当然的以为是引用整个fb框内从(0,0)左上角为起点的800x480的区域

  • framebuffer一行的长度取决于line_length, 而我当时又想当然的认为一行长度是fbset设置的分辨率宽度*像素位数,基于此,我的framebuffer接口mmap是这么写的:

    size_t screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
    fb->fbdata = (unsigned char *)mmap(NULL, screensize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
    if (fb->fbdata == MAP_FAILED) {
        perror("Error mapping framebuffer to memory");
        exit(EXIT_FAILURE);
    }
    

    但是后面看awtk-linux-fb的源码,才发现smem_len才会把整个framebuffer都包括进去,于是我改成:

    fb->fbdata = (unsigned char *)mmap(NULL, finfo.smem_len, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
    

推流定时器函数逻辑改成:

void update_g_bitmap_background() {
	rect_t src_r = rect_init(0, 0, g_bitmap->w, g_bitmap->h);
	LibFrameBuffer *libframebuffer = LibFrameBufferGet(USE_FB_ID);
	char *shared_data = libframebuffer->fbdata;  

	int line_length = libframebuffer->fixinfo.line_length / libframebuffer->bpp;
	int height = libframebuffer->height;

	bitmap_t temp_bmp;
	bitmap_init(&temp_bmp, line_length, height, BITMAP_FMT_RGBA8888, shared_data);
	...

终于正常显示。

在这个ub虚拟机的fb是个长为1176x885的一维数组,而且每1176字节为一行长度,而我只取了800x480的部分放到800x480的位图,在这个位图上,一行只显示800个像素,剩下的376个像素只能到800x480位图第二行去显示了,这样800x480位图两行才能存放1176x885位图的一行内容,后面的行以此类推,这就解释了为什么出来的800x480位图上出来的图像像是拧毛巾(不知道该怎么比喻。。。。)一样。

嵌入式做业务,底层基础一定要过关啊!

ADD:

ubuntu 20.04中:

  1. Ctrl + Alt + F2:GUI模式
  2. Ctrl + Alt + F6:命令行模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2260186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++---入门

C补充了上的不足&#xff0c;使用各方面更加便捷&#xff0c;在C的基础上面向对象进行编译&#xff0c;学过C之后&#xff0c;对学习C的一定的帮助。 命名空间&#xff1a; namesp的定义&#xff1a;定义命名空间&#xff0c;需要使⽤到namespace关键字&#xff0c;后⾯跟命…

boost电路的同步和异步模式 及CCM、DCM模式 介绍

一、同步 异步 1.一般区别 电路结构 异步升压 IC&#xff1a;采用传统的 Boost 电路结构&#xff0c;主要由电感、开关管、二极管和输出电容等组成。同步升压 IC&#xff1a;与异步升压 IC 的 Boost 电路相比&#xff0c;其将二极管替换成了一个同步整流 MOS 管&#xff0c;…

yolov7源码解读1-训练前准备

一、怎么解决图片输入尺度不统一的问题 YOLOv7的矩形训练是指在训练时对输入图片进行尺寸调整&#xff0c;以提高模型处理长宽比差异较大的图片时的性能&#xff0c;同时避免过多的图像变形。具体来说&#xff0c;以下是矩形训练的处理过程&#xff1a; 1. 矩形训练的核心目标…

用梗营销来启动市场

目录 为什么梗营销适合初创公司 有效的梗营销技巧 梗不仅仅是有趣的图片&#xff0c;它们是包裹在幽默中的文化时刻。对于小企业家&#xff08;以及大企业家&#xff09;&#xff0c;梗代表了一种强大且性价比高的市场推广方式。让我们分解一下为什么梗营销有效&#xff0c;以…

职业院校人工智能实验室解决方案

随着人工智能技术的迅猛发展&#xff0c;企事业单位对具备高素质技术应用能力的人才需求愈发迫切&#xff0c;目前人工智能已经逐步从感知理解阶段转变为生成创造阶段&#xff0c;可以为各行各业提供多维的智能化应用服务。2024年的《政府工作报告》中首次提出了“人工智能”行…

java之集合(详细-Map,Set,List)

1集合体系概述 1.1集合的概念 集合是一种容器&#xff0c;用来装数据的&#xff0c;类似于数组&#xff0c;但集合的大小可变&#xff0c;开发中也非常常用。 1.2集合分类 集合分为单列集合和多列集合 Collection代表单列集合&#xff0c;每个元素&#xff08;数据&#xff…

ansible自动化运维(一)简介及清单,模块

相关文章ansible自动化运维&#xff08;二&#xff09;playbook模式详解-CSDN博客ansible自动化运维&#xff08;三&#xff09;jinja2模板&&roles角色管理-CSDN博客ansible自动化运维&#xff08;四&#xff09;运维实战-CSDN博客 ansible自动化运维工具 1.什么是自…

期末复习-编译原理

一、引论 1.编译、翻译、解释的概念&#xff08;掌握&#xff09; 翻译程序&#xff1a;将一种语言程序&#xff08;源&#xff09;转换成另一种语言程序&#xff08;目标&#xff09;&#xff0c;两者在逻辑上是等价的。 如果源语言是高级语言&#xff0c;目标语言是低级语言…

pytorch bilstm crf的教程,注意 这里不支持批处理,要支持批处理 用torchcrf这个。

### Bi-LSTM Conditional Random Field ### pytorch tutorials https://pytorch.org/tutorials/beginner/nlp/advanced_tutorial.html ### 模型主要结构&#xff1a; ![title](sources/bilstm.png) pytorch bilstm crf的教程&#xff0c;注意 这里不支持批处理 Python version…

docker安装、升级、以及sudo dockerd --debug查看启动失败的问题

1、docker安装包tar下载地址 Index of linux/static/stable/x86_64/ 2、下载tgz文件并解压 tar -zxvf docker-24.0.8.tgz 解压后docker文件夹下位docker相关文件 3、将老版本docker相关文件&#xff0c;备份 将 /usr/bin/docker下docker相关的文件&#xff0c;mv到备份目录…

hive—炸裂函数explode/posexplode

1、Explode炸裂函数 将hive某列一行中复杂的 array 或 map 结构拆分成多行&#xff08;只能输入array或map&#xff09; 语法&#xff1a; select explode(字段) as 字段命名 from 表名; 举例&#xff1a; 1&#xff09;explode(array)使得结果中将array列表里的每个元素生…

【Android学习】RxJava

文章目录 资料连接1. Merge & Zip操作符: 合并数据源2. Map & FlapMap & ConcatMap & Buffer: 变换操作符3. retry & retryUntil & retryWhen : 错误处理操作符4. Transformer & Compose 转换符 资料连接 Android RxJava&#xff1a; 这是一份全面…

浅谈Kubernetes(K8s)之RC控制器与RS控制器

1.RC控制器 1.1RC概述 Replication Controller 控制器会持续监控正在运行的Pod列表&#xff0c;并保证相应类型的Pod的数量与期望相符合&#xff0c;如果Pod数量过少&#xff0c;它会根据Pod模板创建新的副本&#xff0c;反之则会删除多余副本。通过RC可实现了应用服务的高可用…

直流开关电源技术及应用

文章目录 1. 开关电源概论1.1 开关电源稳压原理1.1.1 开关电源稳压原理核心组成部分及其作用工作过程稳压原理 1. 开关电源概论 1.1 开关电源稳压原理 为了提高效率&#xff0c;必须使功率调整器件处于开关工作状态。 作为开关而言&#xff0c;导通时压降很小&#xff0c;几乎…

解决 MyBatis 中空字符串与数字比较引发的条件判断错误

问题复现 假设你在 MyBatis 的 XML 配置中使用了如下代码&#xff1a; <if test"isCollect ! null"><choose><when test"isCollect 1">AND exists(select 1 from file_table imgfile2 where task.IMAGE_SEQimgfile2.IMAGE_SEQ and im…

如何windows命令行使用kali?ssh连接高效又快捷

一、打开虚拟机kali进入cmd中 输入vim /etc/ssh/sshd_config&#xff0c;&#xff08;注意这里需要使用root权限&#xff09; 二、进入编辑文件页面 找到PermitRootLogin prohibit-password和 PasswordAuthentication no两行 将“prohibit-password”修改为“yes”&#xff0…

自动化测试之单元测试框架

单元测试框架 一、单元测试的定义 1&#xff1a;什么是单元测试&#xff1f; 还记不记得我们软件测试学习的时候&#xff0c;按照定义&#xff1a;单元测试就是对单个模块或者是单个函数进行测试&#xff0c;一般是开发做的&#xff0c;按照阶段来分&#xff0c;一般就是单元…

ansible部署nginx:1个简单的playbook脚本

文章目录 hosts--ventoryroles执行命令 使用ansible向3台centos7服务器上安装nginx hosts–ventory [rootstand playhook1]# cat /root/HOSTS # /root/HOSTS [webservers] 192.168.196.111 ansible_ssh_passpassword 192.168.196.112 ansible_ssh_passpassword 192.168.196.1…

SpringBoot左脚进门之Maven管理家

一、概念 Maven 是一个项目管理和整合工具。通过对 目录结构和构建生命周期 的标准化&#xff0c; 使开发团队用极少的时间就能够自动完成工程的基础构建配置。 Maven 简化了工程的构建过程&#xff0c;并对其标准化&#xff0c;提高了重用性。 Maven 本地仓库 (Local Reposi…

最短路----Dijkstra算法详解

简介 迪杰斯特拉&#xff08;Dijkstra&#xff09;算法是一种用于在加权图中找到单个源点到所有其他顶点的最短路径的算法。它是由荷兰计算机科学家艾兹格迪科斯彻&#xff08;Edsger Dijkstra&#xff09;在1956年提出的。Dijkstra算法适用于处理带有非负权重的图。迪杰斯特拉…