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