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
35static struct frame_buffer_boot_info *sInfo;
36static uint8 *sUncompressedIcons;
37
38
39static void
40blit8_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
63static void
64blit15_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
91static void
92blit16_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
118static void
119blit24_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
144static void
145blit32_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
168static void
169blit_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
201void
202boot_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
216void
217boot_splash_uninit(void)
218{
219	sInfo = NULL;
220}
221
222
223void
224boot_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