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