xref: /haiku/src/system/boot/platform/generic/video_splash.cpp (revision 1c09002cbee8e797a0f8bbfc5678dfadd39ee1a7)
1 /*
2  * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2008, Stephan Aßmus <superstippi@gmx.de>
4  * Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com>
5  * Distributed under the terms of the MIT License.
6  */
7 
8 
9 #include <arch/cpu.h>
10 #include <boot/stage2.h>
11 #include <boot/platform.h>
12 #include <boot/menu.h>
13 #include <boot/kernel_args.h>
14 #include <boot/platform/generic/video.h>
15 #include <boot/images.h>
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include <zlib.h>
22 
23 
24 //#define TRACE_VIDEO
25 #ifdef TRACE_VIDEO
26 #	define TRACE(x) dprintf x
27 #else
28 #	define TRACE(x) ;
29 #endif
30 
31 
32 static status_t
33 uncompress(const uint8 compressed[], unsigned int compressedSize,
34 	uint8* uncompressed, unsigned int uncompressedSize)
35 {
36 	if (compressedSize == 0 || uncompressedSize == 0)
37 		return B_BAD_VALUE;
38 
39 	// prepare zlib stream
40 	z_stream zStream = {
41 		(Bytef*)compressed,		// next_in
42 		compressedSize,			// avail_in
43 		0,						// total_in
44 		(Bytef*)uncompressed,	// next_out
45 		uncompressedSize,		// avail_out
46 		0,						// total_out
47 		0,						// msg
48 		0,						// state
49 		Z_NULL,					// zalloc (kernel_args_malloc?)
50 		Z_NULL,					// zfree (kernel_args_free?)
51 		Z_NULL,					// opaque
52 		0,						// data_type
53 		0,						// adler
54 		0						// reserved
55 	};
56 
57 	int zlibError = inflateInit(&zStream);
58 	if (zlibError != Z_OK)
59 		return B_ERROR;	// TODO: translate zlibError
60 
61 	// inflate
62 	status_t status = B_OK;
63 	zlibError = inflate(&zStream, Z_FINISH);
64 	if (zlibError != Z_STREAM_END) {
65 		if (zlibError == Z_OK)
66 			status = B_BUFFER_OVERFLOW;
67 		else
68 			status = B_ERROR;	// TODO: translate zlibError
69 	}
70 
71 	// clean up
72 	zlibError = inflateEnd(&zStream);
73 	if (zlibError != Z_OK && status == B_OK)
74 		status = B_ERROR;	// TODO: translate zlibError
75 
76 	if (status == B_OK && zStream.total_out != uncompressedSize)
77 		status = B_ERROR;
78 
79 	return status;
80 }
81 
82 
83 extern "C" status_t
84 video_display_splash(addr_t frameBuffer)
85 {
86 	if (!gKernelArgs.frame_buffer.enabled)
87 		return B_NO_INIT;
88 
89 	// clear the video memory
90 	memset((void*)frameBuffer, 0,
91 		gKernelArgs.frame_buffer.physical_buffer.size);
92 
93 	uint8* uncompressedLogo = NULL;
94 	unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
95 	switch (gKernelArgs.frame_buffer.depth) {
96 		case 8:
97 			platform_set_palette(k8BitPalette);
98 			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
99 			if (uncompressedLogo == NULL)
100 				return B_NO_MEMORY;
101 
102 			uncompress(kSplashLogo8BitCompressedImage,
103 				sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo,
104 				uncompressedSize);
105 		break;
106 		default: // 24 bits is assumed here
107 			uncompressedSize *= 3;
108 			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
109 			if (uncompressedLogo == NULL)
110 				return B_NO_MEMORY;
111 
112 			uncompress(kSplashLogo24BitCompressedImage,
113 				sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo,
114 				uncompressedSize);
115 		break;
116 	}
117 
118 	// TODO: support 4-bit indexed version of the images!
119 
120 	// render splash logo
121 	uint16 iconsHalfHeight = kSplashIconsHeight / 2;
122 
123 	int width = min_c(kSplashLogoWidth, gKernelArgs.frame_buffer.width);
124 	int height = min_c(kSplashLogoHeight + iconsHalfHeight,
125 		gKernelArgs.frame_buffer.height);
126 	int placementX = max_c(0, min_c(100, kSplashLogoPlacementX));
127 	int placementY = max_c(0, min_c(100, kSplashLogoPlacementY));
128 
129 	int x = (gKernelArgs.frame_buffer.width - width) * placementX / 100;
130 	int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100;
131 
132 	height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height);
133 	switch (gKernelArgs.frame_buffer.depth) {
134 		case 8:
135 			break;
136 	}
137 	video_blit_image(frameBuffer, uncompressedLogo, width, height,
138 		kSplashLogoWidth, x, y);
139 
140 	kernel_args_free(uncompressedLogo);
141 
142 	const uint8* lowerHalfIconImage;
143 	uncompressedSize = kSplashIconsWidth * kSplashIconsHeight;
144 	switch (gKernelArgs.frame_buffer.depth) {
145 		case 8:
146 			// pointer into the lower half of the icons image data
147 			gKernelArgs.boot_splash
148 				= (uint8*)kernel_args_malloc(uncompressedSize);
149 			if (gKernelArgs.boot_splash == NULL)
150 				return B_NO_MEMORY;
151 			uncompress(kSplashIcons8BitCompressedImage,
152 				sizeof(kSplashIcons8BitCompressedImage),
153 				gKernelArgs.boot_splash, uncompressedSize);
154 			lowerHalfIconImage = gKernelArgs.boot_splash
155 				+ (kSplashIconsWidth * iconsHalfHeight);
156 		break;
157 		default:	// 24bits is assumed here
158 			uncompressedSize *= 3;
159 			// pointer into the lower half of the icons image data
160 			gKernelArgs.boot_splash
161 				= (uint8*)kernel_args_malloc(uncompressedSize);
162 			if (gKernelArgs.boot_splash == NULL)
163 				return B_NO_MEMORY;
164 			uncompress(kSplashIcons24BitCompressedImage,
165 				sizeof(kSplashIcons24BitCompressedImage),
166 				gKernelArgs.boot_splash, uncompressedSize);
167 			lowerHalfIconImage = gKernelArgs.boot_splash
168 				+ (kSplashIconsWidth * iconsHalfHeight) * 3;
169 		break;
170 	}
171 
172 	// render initial (grayed out) icons
173 	// the grayed out version is the lower half of the icons image
174 
175 	width = min_c(kSplashIconsWidth, gKernelArgs.frame_buffer.width);
176 	height = min_c(kSplashLogoHeight + iconsHalfHeight,
177 		gKernelArgs.frame_buffer.height);
178 	placementX = max_c(0, min_c(100, kSplashIconsPlacementX));
179 	placementY = max_c(0, min_c(100, kSplashIconsPlacementY));
180 
181 	x = (gKernelArgs.frame_buffer.width - width) * placementX / 100;
182 	y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height)
183 		* placementY / 100;
184 
185 	height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height);
186 	video_blit_image(frameBuffer, lowerHalfIconImage, width, height,
187 		kSplashIconsWidth, x, y);
188 	return B_OK;
189 }
190 
191 
192 
193