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