Uboot中支持lcd和hdmi显示不同的logo图片【转】
2017-10-03 09:26
309 查看
本文转载自:http://blog.csdn.net/u010865783/article/details/54953315
在lcd为竖屏,hdmi显示横屏的情况下,如果按照默认的uboot显示框架来看,只能保证lcd或者hdmi上面显示出来的图片一个是正的,另外一个是旋转了90度的样子。
为了能是lcd和hdmi同时支持显示图片都是正的,需要对uboot的框架做修改。如果硬件支持旋转功能的话,就可直接使用硬件旋转,不需要软件来调整。
由于项目原因,折腾了一把这个流程,具体实现记录下:
1:由于硬件不支持rotation功能,在软件上采用的方法是准备两份logo资源,解析后将两份数据送到不同的显示设备上面做显示。
在解析logo的时候需要解析两份资源:
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
2:添加对hdmi驱动中的支持和在cfb_console.c中添加解析图片的支持
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
3:接下来需要对添加对hdmi logo的解析成fb的数据
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
实现了上面的内容之后,接下来需要在uboot的fb中做好映射,主要是将fb0对应的logo的资源送到lcd、fb1对应的logo资源送到hdmi显示,具体的代码和平台相关。
这样造成的影响是会使uboot阶段显示的内存增加一倍,之前只用了一个图片,现在用到了两个图片,所以内存会增加一倍。
当android系统起来的时候,因为lcd是竖屏,lcd上面的内容旋转了90度当成了横屏模式在使用,hdmi是横屏,会造成android动画的前半段在hdmi上面显示的android字样变成了垂直显示,知道android的display的java服务启动之后,android的显示系统识别到了hdmi设备,系统才显示正常。
对于这种情况,hdmi的前半段的异常显示,由于硬件无法rotation,只能采取一个规避的方式解决,将开机启动的logo一直保存到android上层的显示系统识别到hdmi后,才释放boot logo的资源,在这个之前,一直都显示logo的图片。具体的实现方式和平台相关,代码就不贴了。
在lcd为竖屏,hdmi显示横屏的情况下,如果按照默认的uboot显示框架来看,只能保证lcd或者hdmi上面显示出来的图片一个是正的,另外一个是旋转了90度的样子。
为了能是lcd和hdmi同时支持显示图片都是正的,需要对uboot的框架做修改。如果硬件支持旋转功能的话,就可直接使用硬件旋转,不需要软件来调整。
由于项目原因,折腾了一把这个流程,具体实现记录下:
1:由于硬件不支持rotation功能,在软件上采用的方法是准备两份logo资源,解析后将两份数据送到不同的显示设备上面做显示。
在解析logo的时候需要解析两份资源:
static int splash_image_load(void) { int ret; char *filename,*filename_hdmi; void *splash_image_addr,*splash_image_hdmi_addr; char splash_image_char[16], splash_image_hdmi_char[16]; //分配给lcd资源的地址 splash_image_addr = memalign(128, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); if(splash_image_addr == NULL) { printk("Malloc size for splash image failed!\n"); return -1; } //分配给hdmi资源logo的地址 splash_image_hdmi_addr = memalign(128, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); if(splash_image_hdmi_addr == NULL) { printk("Malloc size for splash image hdmi failed!\n"); return -1; } filename = splash_image_select(); filename_hdmi = CONFIG_SYS_VIDEO_LOGO_HDMI_NAME; if (!filename) { printk("No splash image loaded\n"); return -1; } //拿到lcd的logo ret = file_fat_read(filename, splash_image_addr, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); if(ret < 0) { printk("Fail to load splash image\n"); free(splash_image_addr); return -1; } //拿到hdmi的logo ret = file_fat_read(filename_hdmi, splash_image_hdmi_addr, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); if(ret < 0) { printk("Fail to load splash hdmi image\n"); free(splash_image_hdmi_addr); return -1; } sprintf(splash_image_char, "%x", (unsigned int) splash_image_addr); sprintf(splash_image_hdmi_char, "%x", (unsigned int) splash_image_hdmi_addr); //将解析到的地址保存到env中,后续需要再读取出来 setenv("splashimage", splash_image_char); setenv("splashimagehdmi", splash_image_hdmi_char); 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
2:添加对hdmi驱动中的支持和在cfb_console.c中添加解析图片的支持
static int video_init(void) { unsigned char color8; pGD = video_hw_init(); if (pGD == NULL) return -1; //获取驱动中的hdmi的fb的信息video_hw_hdmi_init在fb的驱动中实现 pGD_HDMI = video_hw_hdmi_init(); if (pGD_HDMI == NULL) return -1; ... } static void *video_logo(void) { char info[128]; int space, len; __maybe_unused int y_off = 0; __maybe_unused ulong addr; __maybe_unused char *s,*s_hdmi; splash_get_pos(&video_logo_xpos, &video_logo_ypos); //splash_get_pos(&video_logo_xpos, &video_logo_ypos); video_hdmi_logo_xpos = BMP_ALIGN_CENTER; //init xpos and ypos video_hdmi_logo_ypos = BMP_ALIGN_CENTER; #ifdef CONFIG_SPLASH_SCREEN //从env中拿到lcd和hdmi图片的地址 s = getenv("splashimage"); s_hdmi = getenv("splashimagehdmi"); if (s != NULL) { splash_screen_prepare(); addr = simple_strtoul(s, NULL, 16); //解析lcd的logo资源成送显的数据 if (video_display_bitmap(addr, video_logo_xpos, video_logo_ypos) == 0) { video_logo_height = 0; //return ((void *) (video_fb_address)); } } if (s_hdmi != NULL) { //printf("xieshsh debug video display\n"); splash_screen_prepare(); addr = simple_strtoul(s_hdmi, NULL, 16); //解析lcd的hdmi资源成送显的数据 if (video_display_hdmi_bitmap(addr, video_hdmi_logo_xpos, video_hdmi_logo_ypos) == 0) { video_hdmi_logo_ypos = 0; return ((void *) (video_fb_address)); } }
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
3:接下来需要对添加对hdmi logo的解析成fb的数据
int video_display_hdmi_bitmap(ulong bmp_image, int x, int y) { ushort xcount, ycount; uchar *fb; bmp_image_t *bmp = (bmp_image_t *) bmp_image; uchar *bmap; ushort padded_line; unsigned long width, height, bpp; unsigned colors; unsigned long compression; bmp_color_table_entry_t cte; #ifdef CONFIG_VIDEO_BMP_GZIP unsigned char *dst = NULL; ulong len; #endif WATCHDOG_RESET(); if (!((bmp->header.signature[0] == 'B') && (bmp->header.signature[1] == 'M'))) { #ifdef CONFIG_VIDEO_BMP_GZIP /* * Could be a gzipped bmp image, try to decrompress... */ len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE; dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); if (dst == NULL) { printf("Error: malloc in gunzip failed!\n"); return 1; } /* * NB: we need to force offset of +2 * See doc/README.displaying-bmps */ if (gunzip(dst+2, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE-2, (uchar *) bmp_image, &len) != 0) { printf("Error: no valid bmp or bmp.gz image at %lx\n", bmp_image); free(dst); return 1; } if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) { printf("Image could be truncated " "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n"); } /* * Set addr to decompressed image */ bmp = (bmp_image_t *)(dst+2); if (!((bmp->header.signature[0] == 'B') && (bmp->header.signature[1] == 'M'))) { printf("Error: no valid bmp.gz image at %lx\n", bmp_image); free(dst); return 1; } #else printf("Error: no valid bmp image at %lx\n", bmp_image); return 1; #endif /* CONFIG_VIDEO_BMP_GZIP */ } width = le32_to_cpu(bmp->header.width); height = le32_to_cpu(bmp->header.height); bpp = le16_to_cpu(bmp->header.bit_count); colors = le32_to_cpu(bmp->header.colors_used); compression = le32_to_cpu(bmp->header.compression); debug("Display-bmp: %ld x %ld with %d colors\n", width, height, colors); if (compression != BMP_BI_RGB #ifdef CONFIG_VIDEO_BMP_RLE8 && compression != BMP_BI_RLE8 #endif ) { printf("Error: compression type %ld not supported\n", compression); #ifdef CONFIG_VIDEO_BMP_GZIP if (dst) free(dst); #endif return 1; } padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3; #ifdef CONFIG_SPLASH_SCREEN_ALIGN if (x == BMP_ALIGN_CENTER){ x = max(0, (int)(VIDEO_HDMI_VISIBLE_COLS - width) / 2); printf("VVVVVVVVx=%d",x); } else if (x < 0) x = max(0, (int)(VIDEO_HDMI_VISIBLE_COLS - width + x + 1)); if (y == BMP_ALIGN_CENTER) y = max(0, (int)(VIDEO_HDMI_VISIBLE_ROWS - height) / 2); else if (y < 0) y = max(0, (int)(VIDEO_HDMI_VISIBLE_ROWS - height + y + 1)); #endif /* CONFIG_SPLASH_SCREEN_ALIGN */ /* * Just ignore elements which are completely beyond screen * dimensions. */ if ((x >= VIDEO_HDMI_VISIBLE_COLS) || (y >= VIDEO_HDMI_VISIBLE_ROWS)) return 0; if ((x + width) > VIDEO_HDMI_VISIBLE_COLS) width = VIDEO_HDMI_VISIBLE_COLS - x; if ((y + height) > VIDEO_HDMI_VISIBLE_ROWS) height = VIDEO_HDMI_VISIBLE_ROWS - y; bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset); fb = (uchar *) (video_hdmi_fb_address + ((y + height - 1) * VIDEO_HDMI_VISIBLE_COLS * VIDEO_HDMI_PIXEL_SIZE) + x * VIDEO_HDMI_PIXEL_SIZE); /* We handle only 4, 8, or 24 bpp bitmaps */ switch (le16_to_cpu(bmp->header.bit_count)) { case 24: padded_line -= 3 * width; ycount = height; //printf("xiessh----VIDEO_DATA_FORMAT = %d\n",VIDEO_HDMI_DATA_FORMAT); switch (VIDEO_HDMI_DATA_FORMAT) { case GDF_32BIT_X888RGB: while (ycount--) { WATCHDOG_RESET(); xcount = width; while (xcount--) { FILL_32BIT_X888RGB(bmap[2], bmap[1], bmap[0]); bmap += 3; } bmap += padded_line; fb -= (VIDEO_HDMI_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE; } break; default: printf("Error: 24 bits/pixel bitmap incompatible " "with current video mode\n"); break; } break; default: printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n", le16_to_cpu(bmp->header.bit_count)); break; } #ifdef CONFIG_VIDEO_BMP_GZIP if (dst) { free(dst); } #endif if (cfb_do_flush_cache) flush_cache(VIDEO_FB_ADRS, VIDEO_SIZE); 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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
实现了上面的内容之后,接下来需要在uboot的fb中做好映射,主要是将fb0对应的logo的资源送到lcd、fb1对应的logo资源送到hdmi显示,具体的代码和平台相关。
这样造成的影响是会使uboot阶段显示的内存增加一倍,之前只用了一个图片,现在用到了两个图片,所以内存会增加一倍。
当android系统起来的时候,因为lcd是竖屏,lcd上面的内容旋转了90度当成了横屏模式在使用,hdmi是横屏,会造成android动画的前半段在hdmi上面显示的android字样变成了垂直显示,知道android的display的java服务启动之后,android的显示系统识别到了hdmi设备,系统才显示正常。
对于这种情况,hdmi的前半段的异常显示,由于硬件无法rotation,只能采取一个规避的方式解决,将开机启动的logo一直保存到android上层的显示系统识别到hdmi后,才释放boot logo的资源,在这个之前,一直都显示logo的图片。具体的实现方式和平台相关,代码就不贴了。
相关文章推荐
- Uboot中支持lcd和hdmi显示不同的logo图片
- 制作uboot LCD开机logo 及LCD字符显示错误的解决
- 按钮的背景图片根据状态的不同而显示不同的图片,网上有介绍相关的方法。
- 视频和QT的GUI显示到LCD的不同显示层—透过GUI能看到视频
- 同一个ImageView显示不同的图片--->level-list
- Android使用webview调用系统浏览器以及项目内显示并支持图片和输入
- 获取图片的路径,即src的值,并依据不同的样式在alt属性中显示
- MFC使用OpenCV在文档窗口中显示图像(支持多图片格式)
- 修ecshop品牌筛选以LOGO图片形式显示
- Android之GLES2.0显示立方体各面不同图片测试代码
- 让DuiLib支持Icon图片显示
- 任意文字,任意图片,彩色lcd显示,画面实时更新,全部通过非gui方式实现了。
- Android把相同图片放到不同的文件夹显示不同的问题
- Swift - 集成app启动页广告,切换rootViewController,支持LaunchImage和LaunchScreen.storyboard,支持GIF图片显示,支持视图过渡动画
- u-boot下载模式LCD显示图片修改方法(基于TQ2440)
- JSP使用ckfinder实现中文图片上传后,无法显示,主要是tomcat不支持中文路径
- 浅谈 Glide - BitmapPool 的存储时机 & 解答 ViewTarget 在同一View显示不同的图片时,总用同一个 Bitmap 引用的原因
- MFC在picture control中JPG/BMP/ICO等格式图片显示,并支持清除图片显示
- 基于vs2010+opencv2.4.8实现----将三通道RGB图片分别按R,G,B三个不同分量输出显示
- 【android】图片放错文件夹引起显示大小不同的原因与屏幕适配原理