linux显示启动logo源码分析以及修改显示logo
1、linux显示启动logo整个流程分析
(1)logo图片在内核源码中是以ppm格式的文件保存,在编译内核时会把ppm格式的文件自动转换成.c文件,在c文件中会构造一个struct linux_logo结构体变量,
变量名字就是文件的名字,struct linux_logo结构体在内核中用来表示一副logo图像信息;
(2)内核在初始化显示器后,会按照配置去匹配合适的struct linux_logo结构体,也就是查找logo图片;
(3)将logo图像显示到默认屏幕上;
2、linux显示启动logo源码分析
2.1、全局变量fb_logo
(1)显示启动logo的代码在fbmem.c中实现,使用struct logo_data结构体来描述启动logo相关的信息;
(2)成员logo表示启动logo图像的具体信息,其他的变量和图像的格式和图像深度有关系;
2.2、struct linux_logo结构体
#define LINUX_LOGO_MONO 1 /* monochrome black/white */
#define LINUX_LOGO_VGA16 2 /* 16 colors VGA text palette */
#define LINUX_LOGO_CLUT224 3 /* 224 colors */
#define LINUX_LOGO_GRAY256 4 /* 256 levels grayscale */
(1)struct linux_logo结构体就是内核中用来描述logo图片的,这个结构体不用我们去构造,是有ppm文件转换成c文件时自动生成;
(2)logo图像有4中格式,其中LINUX_LOGO_CLUT224应用最为广泛,所占空间也最小。LINUX_LOGO_CLUT224类型的图像颜色种类不会超过224中,颜色的具体信息保存在clut成员表示的颜色对照表中,成员data
指向由颜色对照表索引构成的图像数据。
(3)LINUX_LOGO_CLUT224类型的图像空间计算,比如:对于长宽分别是150和100的 Logo,如果bpp为24 使用颜色对照表方式存储这幅Logo最多需要( 150×100+224 × 3)=15672字节,而如果直接
存储 Logo的所有像素信息,就需要(150×100×3)=45000字节。
(4)通常情况下,内核对于bpp大于等于8的情况,会使用颜色对照表的方式存放Logo ,而bpp小于8时,使用颜色对照表反而可能占用更多空间,因此直接将像素信息存放在成员data中;
2.3、函数调用关系
s3cfb_probe() //这是显示器驱动的prob函数fb_prepare_logo() //查找合适的logofb_get_color_depth() //获取显示器的颜色深度fb_find_logo() //真正找到合适的logo图像,也就是struct linux_logo结构体fb_prepare_extra_logos() //设置附加的logo数据,不是必须的fb_set_cmap() //设置显示屏的颜色表fb_show_logo() //显示logo图像fb_show_logo_line() //构建struct fb_image结构体fb_do_show_logo() //执行logo显示info->fbops->fb_imageblit() //调用显示驱动的fb_imageblit()方法,这里是实际操作硬件的fb_show_extra_logos() //显示附加的logo数据,非必须
2.4、fb_prepare_logo()函数
int fb_prepare_logo(struct fb_info *info, int rotate)
{//计算颜色深度int depth = fb_get_color_depth(&info->var, &info->fix);unsigned int yres;memset(&fb_logo, 0, sizeof(struct logo_data));if (info->flags & FBINFO_MISC_TILEBLITTING ||info->flags & FBINFO_MODULE)return 0;if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {depth = info->var.blue.length;if (info->var.red.length < depth)depth = info->var.red.length;if (info->var.green.length < depth)depth = info->var.green.length;}if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {/* assume console colormap */depth = 4;}/* 根据颜色深度返回找到的struct linux_logo结构体 */fb_logo.logo = fb_find_logo(depth);if (!fb_logo.logo) {return 0;}//判断是否旋转if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)yres = info->var.yres;elseyres = info->var.xres;//判断logo图像的高是否超过可视屏幕的高if (fb_logo.logo->height > yres) {fb_logo.logo = NULL;return 0;}/* 根据logo图像类型设置图像深度 */if (fb_logo.logo->type == LINUX_LOGO_CLUT224)fb_logo.depth = 8;else if (fb_logo.logo->type == LINUX_LOGO_VGA16)fb_logo.depth = 4;elsefb_logo.depth = 1;if (fb_logo.depth > 4 && depth > 4) {switch (info->fix.visual) {case FB_VISUAL_TRUECOLOR:fb_logo.needs_truepalette = 1;break;case FB_VISUAL_DIRECTCOLOR:fb_logo.needs_directpalette = 1;fb_logo.needs_cmapreset = 1;break;case FB_VISUAL_PSEUDOCOLOR:fb_logo.needs_cmapreset = 1;break;}}return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
}
(1)调用fb_get_color_depth()函数,根据info->var和info->fix计算图像深度,并返回给局部变量depth;
(2)调用fb_find_logo()函数,根据图像深度何也找到合适的Logo图像数据并返回给fb_logo.logo;
(3)如果找到了合适的图像数据,则根据 Logo 图像数据的类型给fb_logo.depth赋值
(4)如果由fb_logo.depth和depth 都大于 4,则根据 info->fix且sual 的值设置 fb_logo 剩下的成员:若 info->fix且sual 为 FB_VISUAL_TRUECOLOR,则由1__logo 的 needs二刷刷e出成员被设置,若为 FB_VISUAL_TR四COLOR,则 needs_directpalette 和 needs_cmapreset 均被设置,若为 FB_VISUAL_PSEUDOCOLOR,则 needs_cmapreset 被设置;
(5)调用fb_prepare_extra_logos()函数设置附加Logo数据;
2.5、fb_find_logo()函数
const struct linux_logo * __init_refok fb_find_logo(int depth)
{const struct linux_logo *logo = NULL;if (nologo)return NULL;if (depth >= 1) {#ifdef CONFIG_LOGO_LINUX_MONO/* Generic Linux logo */logo = &logo_linux_mono;
#endif}if (depth >= 4) {#ifdef CONFIG_LOGO_LINUX_VGA16/* Generic Linux logo */logo = &logo_linux_vga16;
#endif}if (depth >= 8) {#ifdef CONFIG_LOGO_LINUX_CLUT224/* Generic Linux logo */logo = &logo_linux_clut224;
#endif//X210开发板的logo图像数据
#ifdef CONFIG_LOGO_X210_CLUT224
/* x210 android logo */
logo = &logo_x210_clut224;
#endif}return logo;
}
(1)根据depth去查找合适的logo数据,这里的struct linux_logo结构体是由ppm文件转换成C语言文件得到的;
(2)注意这里的查找有后覆盖性,当查找到合适的struct linux_logo结构体函数不会返回,会把所有的结构体都查找一遍,最后一个
匹配的会被返回;
2.6、fb_show_logo_line()函数
static int fb_show_logo_line(struct fb_info *info, int rotate,const struct linux_logo *logo, int y,unsigned int n)
{u32 *palette = NULL, *saved_pseudo_palette = NULL;unsigned char *logo_new = NULL, *logo_rotate = NULL;struct fb_image image;/* Return if the frame buffer is not mapped or suspended */if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||info->flags & FBINFO_MODULE)return 0;image.depth = 8;image.data = logo->data; //图像数据//若needs_cmapreset被设置,则根据logo配置颜色表,设置颜色表//最终会调用info->fbops中的fb_setcmap()或fb_setcolreg()方法if (fb_logo.needs_cmapreset)fb_set_logocmap(info, logo);//若needs_truepalette或 needs_directpalette被设置,则根据logo分配并设置调色板if (fb_logo.needs_truepalette ||fb_logo.needs_directpalette) {palette = kmalloc(256 * 4, GFP_KERNEL);if (palette == NULL)return 0;if (fb_logo.needs_truepalette)fb_set_logo_truepalette(info, logo, palette);elsefb_set_logo_directpalette(info, logo, palette);//备份info中原调色板内容,并设置为新的调色板saved_pseudo_palette = info->pseudo_palette;info->pseudo_palette = palette;}//对于depth <=4 的情况,既不使用颜色表,也不使用调色板,//image.data中直接存入像素信息,而不是颜色表或者调色板的索引if (fb_logo.depth <= 4) {logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);if (logo_new == NULL) {kfree(palette);if (saved_pseudo_palette)info->pseudo_palette = saved_pseudo_palette;return 0;}image.data = logo_new;fb_set_logo(info, logo, logo_new, fb_logo.depth);}//logo显示的起始坐标image.dx = 0;image.dy = y;//logo图像的宽高image.width = logo->width;image.height = logo->height;//根据旋转方式调整图像if (rotate) {logo_rotate = kmalloc(logo->width *logo->height, GFP_KERNEL);if (logo_rotate)fb_rotate_logo(info, logo_rotate, &image, rotate);}//执行logo显示fb_do_show_logo(info, &image, rotate, n);kfree(palette);//恢复原调色板内容if (saved_pseudo_palette != NULL)info->pseudo_palette = saved_pseudo_palette;kfree(logo_new);kfree(logo_rotate);return logo->height;
}
传参 | 注释 |
---|---|
info | 帧缓冲设备描述结构 |
rotate | 屏幕旋转方式 |
logo | 待显示的 Logo 图像 logo(实际上是 fb_logo.logo) |
y | logo显示起始坐标的y值 |
n | 系统 CPU 数量 |
3、制作ppm文件
//安装工具包
sudo apt-get install netpbm//将名字为logo.png的图像,转换成logo_linux_clut224.ppm文件
pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_linux_clut224.ppm
(1)上面是利用命令pngtopnm & ppmquant & pnmtoplainpnm来将png格式图像转换成ppm格式图像,如果linux中没有相关命令则要先安装命令包;
(2)在上面的命令中,注意图片文件的名字和你实际的对应上,放到内核源码中放ppm格式文件的目录下;
4、ppm文件自动转换成C源文件
obj-$(CONFIG_LOGO) += logo.o
obj-$(CONFIG_LOGO_LINUX_MONO) += logo_linux_mono.oobj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o//添加宏进行控制
obj-$(CONFIG_LOGO_X210_CLUT224) += logo_x210_clut224.o # Use logo-cfiles to retrieve list of .c files to be built
logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \$(wildcard $(srctree)/$(src)/*$(1).$(2))))# Mono logos
extra-y += $(call logo-cfiles,_mono,pbm)# VGA16 logos
extra-y += $(call logo-cfiles,_vga16,ppm)# 224 Logos
extra-y += $(call logo-cfiles,_clut224,ppm)# Gray 256
extra-y += $(call logo-cfiles,_gray256,pgm)pnmtologo := scripts/pnmtologo# Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
quiet_cmd_logo = LOGO $@cmd_logo = $(pnmtologo) \-t $(patsubst $*_%,%,$(notdir $(basename $<))) \-n $(notdir $(basename $<)) -o $@ $<$(obj)/%_mono.c: $(src)/%_mono.pbm $(pnmtologo) FORCE$(call if_changed,logo)$(obj)/%_vga16.c: $(src)/%_vga16.ppm $(pnmtologo) FORCE$(call if_changed,logo)#将ppm格式转换成c语言文件
$(obj)/%_clut224.c: $(src)/%_clut224.ppm $(pnmtologo) FORCE$(call if_changed,logo)$(obj)/%_gray256.c: $(src)/%_gray256.pgm $(pnmtologo) FORCE$(call if_changed,logo)# Files generated that shall be removed upon make clean
clean-files := *.o *_mono.c *_vga16.c *_clut224.c *_gray256.c
(1)上面是内核中放ppm格式文件目录的Makefile,在匹配规则中,有将各种pbm、ppm等格式的图像转换成C语言文件的规则;
(2)规则的匹配是根据文件的后缀名来匹配,所以我们要注意对ppm文件的名字命名要以"_clut224"结尾;
(3)通过宏控制要编译哪些ppm格式的文件;
5、转换得到的logo_linux_clut224.c文件
static unsigned char logo_x210_clut224_data[] __initdata = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,······
}static unsigned char logo_x210_clut224_clut[] __initdata = {0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x19, 0x09, 0x18, 0x36, 0x14,······
}const struct linux_logo logo_x210_clut224 __initconst = {.type = LINUX_LOGO_CLUT224, //图像类型.width = 800, //宽.height = 480, //高.clutsize = 102, //颜色对照表大小.clut = logo_x210_clut224_clut, //颜色对照表.data = logo_x210_clut224_data //Logo 图像数据
};
(1)主要就是构建一个struct linux_logo结构体,这是内核用来描述logo图像信息的结构体;
(2)注意这个结构体的名字是和文件名一致的;
6、ppm文件如何与内核源码关联
(1)ppm格式转换成c语言文件,是根据文件的后缀名去Makefile中进行规则的匹配,自动完成编译;
(2)C语言文件中主体就是struct linux_logo结构体,名字和c文件的名字一致;
(3)在内核源码中就是匹配转换得到的struct linux_logo结构体;
7、替换内核启动logo图像
(1)制作ppm格式的文件,注意文件名字的后缀要符合Makefile的匹配规则,并且图像大小不能超过显示屏的分辨率;
(2)修改ppm文件同级的Makefile文件,按照其他的ppm文件的添加方式,通过宏进行控制;
(3)在内核源码的fb_find_logo()函数中,添加新生成的struct linux_logo结构体变量;
8、修改启动logo图像显示位置
修改fb_show_logo_line()函数中logo显示的起始坐标;
linux显示启动logo源码分析以及修改显示logo相关推荐
- 【Android 插件化】VirtualApp 源码分析 ( 启动应用源码分析 | HomePresenterImpl 启动应用方法 | VirtualCore 启动插件应用最终方法 )
文章目录 一.启动应用源码分析 1.HomeActivity 启动应用点击方法 2.HomePresenterImpl 启动应用方法 3.VirtualCore 启动插件应用最终方法 一.启动应用源码 ...
- Spring Boot 2.x 启动全过程源码分析(全)
上篇<Spring Boot 2.x 启动全过程源码分析(一)入口类剖析>我们分析了 Spring Boot 入口类 SpringApplication 的源码,并知道了其构造原理,这篇我 ...
- Spring Boot 2.x 启动全过程源码分析(上)入口类剖析
转载自 Spring Boot 2.x 启动全过程源码分析(上)入口类剖析 Spring Boot 的应用教程我们已经分享过很多了,今天来通过源码来分析下它的启动过程,探究下 Spring Boo ...
- storm启动supervisor源码分析-supervisor.clj
storm启动supervisor源码分析-supervisor.clj supervisor是storm集群重要组成部分,supervisor主要负责管理各个"工作节点".sup ...
- storm启动nimbus源码分析-nimbus.clj
storm启动nimbus源码分析-nimbus.clj nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus ...
- 3supervisor启动worker源码分析-worker.clj
supervisor启动worker源码分析-worker.clj supervisor通过调用sync-processes函数来启动worker,关于sync-processes函数的详细分析请参见 ...
- supervisor启动worker源码分析-worker.clj
supervisor通过调用sync-processes函数来启动worker,关于sync-processes函数的详细分析请参见"storm启动supervisor源码分析-superv ...
- Linux brk(),mmap()系统调用源码分析3:brk()的内存申请流程
Linux brk(),mmap()系统调用源码分析 brk()的内存申请流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...
- Linux系统编程 / triggerhappy 源码分析(3.select 的应用)
哈喽,我是老吴,继续记录我的学习心得. 一.进步的滞后性 我们期望进步是线性: 每一个人付出一些努力后,都希望它有立竿见影的效果. 现实是: 做出努力后,结果的显现往往滞后. 只有在几个月或几年后,我 ...
最新文章
- JDK12的五大重要新特性
- 最大似然估计与损失函数
- java算法:冒泡排序
- cmd执行python 环境变量应该怎么写_python怎么运行py文件?.py文件cmd命令方法及环境变量配置教程...
- 【JavaWeb】数据库基础复习
- 《C++面向对象高效编程(第2版)》——3.16 从函数中返回引用
- 大话RAC介质恢复---联机日志损坏
- lg linux电视安装软件,LG电视如何安装第三方应用软件的方法教程
- 明解c语言练习答案,《明解C语言》练习题4-2的实现
- 苹果系统安装Java开发环境JDK
- 高通平台音频软件架构
- 某音漂亮小姐姐视频合集一键下载,想看就看!
- 最近把beecloud,芝麻信用,智能门锁接入了系统。闲下来把遇到的一些坑排下,也能给后人一些指导
- php拼多多api接口,api.php
- ACM-ICPC 2018 沈阳赛区网络预赛 G. Spare Tire
- 【Unity】碰撞后缩小比例并与碰撞目标紧贴(吸附效果)
- 湾区潮涌·香港向前 | 香港科大副校长汪扬:用好一国两制制度优势,香港要成数字经济接轨世界桥梁...
- 【工具推荐】图形化Git客户端Sourcetree推荐
- 视屏剪辑学习笔记(3)
- 环境规划与管理名词解释