xref: /haiku/src/system/kernel/boot_splash.cpp (revision e0ef64750f3169cd634bb2f7a001e22488b05231)
1 /*
2  * Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Artur Wyszynski <harakash@gmail.com>
7  */
8 
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 
15 #include <KernelExport.h>
16 
17 #define __BOOTSPLASH_KERNEL__
18 #ifdef HAIKU_DISTRO_COMPATIBILITY_OFFICIAL
19 #include <boot/images.h>
20 #else
21 #include <boot/images-sans-tm.h>
22 #endif
23 
24 
25 #include <boot_item.h>
26 #include <debug.h>
27 #include <frame_buffer_console.h>
28 
29 #include <boot_splash.h>
30 
31 
32 //#define TRACE_BOOT_SPLASH 1
33 #ifdef TRACE_BOOT_SPLASH
34 #	define TRACE(x...) dprintf(x);
35 #else
36 #	define TRACE(x...) ;
37 #endif
38 
39 
40 static struct frame_buffer_boot_info *sInfo;
41 static uint8 *sUncompressedIcons;
42 
43 
44 static void
45 blit8_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
46 	uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
47 	uint16 left, uint16 top)
48 {
49 	data += (imageWidth * imageTop + imageLeft);
50 	uint8* start = (uint8*)(sInfo->frame_buffer
51 		+ sInfo->bytes_per_row * (top + imageTop) + 1 * (left + imageLeft));
52 
53 	for (int32 y = imageTop; y < imageBottom; y++) {
54 		const uint8* src = data;
55 		uint8* dst = start;
56 		for (int32 x = imageLeft; x < imageRight; x++) {
57 			dst[0] = src[0];
58 			dst++;
59 			src++;
60 		}
61 
62 		data += imageWidth;
63 		start = (uint8*)((addr_t)start + sInfo->bytes_per_row);
64 	}
65 }
66 
67 
68 static void
69 blit15_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
70 	uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
71 	uint16 left, uint16 top)
72 {
73 	data += (imageWidth * imageTop + imageLeft) * 3;
74 	uint16* start = (uint16*)(sInfo->frame_buffer
75 		+ sInfo->bytes_per_row * (top + imageTop)
76 		+ 2 * (left + imageLeft));
77 
78 	for (int32 y = imageTop; y < imageBottom; y++) {
79 		const uint8* src = data;
80 		uint16* dst = start;
81 		for (int32 x = imageLeft; x < imageRight; x++) {
82 			dst[0] = ((src[2] >> 3) << 10)
83 				| ((src[1] >> 3) << 5)
84 				| ((src[0] >> 3));
85 
86 			dst++;
87 			src += 3;
88 		}
89 
90 		data += imageWidth * 3;
91 		start = (uint16*)((addr_t)start + sInfo->bytes_per_row);
92 	}
93 }
94 
95 
96 static void
97 blit16_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
98 	uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
99 	uint16 left, uint16 top)
100 {
101 	data += (imageWidth * imageTop + imageLeft) * 3;
102 	uint16* start = (uint16*)(sInfo->frame_buffer
103 		+ sInfo->bytes_per_row * (top + imageTop) + 2 * (left + imageLeft));
104 
105 	for (int32 y = imageTop; y < imageBottom; y++) {
106 		const uint8* src = data;
107 		uint16* dst = start;
108 		for (int32 x = imageLeft; x < imageRight; x++) {
109 			dst[0] = ((src[2] >> 3) << 11)
110 				| ((src[1] >> 2) << 5)
111 				| ((src[0] >> 3));
112 
113 			dst++;
114 			src += 3;
115 		}
116 
117 		data += imageWidth * 3;
118 		start = (uint16*)((addr_t)start + sInfo->bytes_per_row);
119 	}
120 }
121 
122 
123 static void
124 blit24_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
125 	uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
126 	uint16 left, uint16 top)
127 {
128 	data += (imageWidth * imageTop + imageLeft) * 3;
129 	uint8* start = (uint8*)(sInfo->frame_buffer
130 		+ sInfo->bytes_per_row * (top + imageTop) + 3 * (left + imageLeft));
131 
132 	for (int32 y = imageTop; y < imageBottom; y++) {
133 		const uint8* src = data;
134 		uint8* dst = start;
135 		for (int32 x = imageLeft; x < imageRight; x++) {
136 			dst[0] = src[0];
137 			dst[1] = src[1];
138 			dst[2] = src[2];
139 			dst += 3;
140 			src += 3;
141 		}
142 
143 		data += imageWidth * 3;
144 		start = (uint8*)((addr_t)start + sInfo->bytes_per_row);
145 	}
146 }
147 
148 
149 static void
150 blit32_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
151 	uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
152 	uint16 left, uint16 top)
153 {
154 	data += (imageWidth * imageTop + imageLeft) * 3;
155 	uint32* start = (uint32*)(sInfo->frame_buffer
156 		+ sInfo->bytes_per_row * (top + imageTop) + 4 * (left + imageLeft));
157 
158 	for (int32 y = imageTop; y < imageBottom; y++) {
159 		const uint8* src = data;
160 		uint32* dst = start;
161 		for (int32 x = imageLeft; x < imageRight; x++) {
162 			dst[0] = (src[2] << 16) | (src[1] << 8) | (src[0]);
163 			dst++;
164 			src += 3;
165 		}
166 
167 		data += imageWidth * 3;
168 		start = (uint32*)((addr_t)start + sInfo->bytes_per_row);
169 	}
170 }
171 
172 
173 static void
174 blit_cropped(const uint8* data, uint16 imageLeft, uint16 imageTop,
175 	uint16 imageRight, uint16 imageBottom, uint16 imageWidth,
176 	uint16 left, uint16 top)
177 {
178 	switch (sInfo->depth) {
179 		case 8:
180 			blit8_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
181 				imageWidth, left, top);
182 			return;
183 		case 15:
184 			blit15_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
185 				imageWidth, left, top);
186 			return;
187 		case 16:
188 			blit16_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
189 				imageWidth, left, top);
190 			return;
191 		case 24:
192 			blit24_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
193 				imageWidth, left, top);
194 			return;
195 		case 32:
196 			blit32_cropped(data, imageLeft, imageTop, imageRight, imageBottom,
197 				imageWidth, left, top);
198 			return;
199 	}
200 }
201 
202 
203 //	#pragma mark - exported functions
204 
205 
206 void
207 boot_splash_init(uint8 *bootSplash)
208 {
209 	TRACE("boot_splash_init: enter\n");
210 
211 	if (debug_screen_output_enabled())
212 		return;
213 
214 	sInfo = (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO,
215 		NULL);
216 
217 	sUncompressedIcons = bootSplash;
218 }
219 
220 
221 void
222 boot_splash_uninit(void)
223 {
224 	sInfo = NULL;
225 }
226 
227 
228 void
229 boot_splash_set_stage(int stage)
230 {
231 	TRACE("boot_splash_set_stage: stage=%d\n", stage);
232 
233 	if (sInfo == NULL || stage < 0 || stage >= BOOT_SPLASH_STAGE_MAX)
234 		return;
235 
236 	int iconsHalfHeight = kSplashIconsHeight / 2;
237 	int width = min_c(kSplashIconsWidth, sInfo->width);
238 	int height = min_c(kSplashLogoHeight + iconsHalfHeight, sInfo->height);
239 	int placementX = max_c(0, min_c(100, kSplashIconsPlacementX));
240 	int placementY = max_c(0, min_c(100, kSplashIconsPlacementY));
241 
242 	int x = (sInfo->width - width) * placementX / 100;
243 	int y = kSplashLogoHeight + (sInfo->height - height) * placementY / 100;
244 
245 	int stageLeftEdge = width * stage / BOOT_SPLASH_STAGE_MAX;
246 	int stageRightEdge = width * (stage + 1) / BOOT_SPLASH_STAGE_MAX;
247 
248 	height = min_c(iconsHalfHeight, sInfo->height);
249 	blit_cropped(sUncompressedIcons, stageLeftEdge, 0, stageRightEdge,
250 		height, kSplashIconsWidth, x, y);
251 }
252 
253