xref: /haiku/src/system/boot/platform/generic/video_splash.cpp (revision 1368eabbff038d765b7095c20568a0eb69cee520)
17db9fbfeSFrançois Revol /*
27db9fbfeSFrançois Revol  * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
37db9fbfeSFrançois Revol  * Copyright 2008, Stephan Aßmus <superstippi@gmx.de>
47db9fbfeSFrançois Revol  * Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com>
57db9fbfeSFrançois Revol  * Distributed under the terms of the MIT License.
67db9fbfeSFrançois Revol  */
77db9fbfeSFrançois Revol 
87db9fbfeSFrançois Revol 
97db9fbfeSFrançois Revol #include <arch/cpu.h>
107db9fbfeSFrançois Revol #include <boot/stage2.h>
117db9fbfeSFrançois Revol #include <boot/platform.h>
127db9fbfeSFrançois Revol #include <boot/menu.h>
137db9fbfeSFrançois Revol #include <boot/kernel_args.h>
147db9fbfeSFrançois Revol #include <boot/platform/generic/video.h>
1589fa2a85SPhilippe Houdoin #include <boot/images.h>
167db9fbfeSFrançois Revol 
177db9fbfeSFrançois Revol #include <stdio.h>
187db9fbfeSFrançois Revol #include <stdlib.h>
197db9fbfeSFrançois Revol 
2067938b0dSPhilippe Houdoin #include <zlib.h>
2167938b0dSPhilippe Houdoin 
227db9fbfeSFrançois Revol 
237db9fbfeSFrançois Revol //#define TRACE_VIDEO
247db9fbfeSFrançois Revol #ifdef TRACE_VIDEO
257db9fbfeSFrançois Revol #	define TRACE(x) dprintf x
267db9fbfeSFrançois Revol #else
277db9fbfeSFrançois Revol #	define TRACE(x) ;
287db9fbfeSFrançois Revol #endif
297db9fbfeSFrançois Revol 
307db9fbfeSFrançois Revol 
3167938b0dSPhilippe Houdoin static status_t
3267938b0dSPhilippe Houdoin uncompress(const uint8 compressed[], unsigned int compressedSize,
3367938b0dSPhilippe Houdoin 	uint8* uncompressed, unsigned int uncompressedSize)
3467938b0dSPhilippe Houdoin {
3567938b0dSPhilippe Houdoin 	if (compressedSize == 0 || uncompressedSize == 0)
3667938b0dSPhilippe Houdoin 		return B_BAD_VALUE;
3767938b0dSPhilippe Houdoin 
3867938b0dSPhilippe Houdoin 	// prepare zlib stream
3967938b0dSPhilippe Houdoin 	z_stream zStream = {
4067938b0dSPhilippe Houdoin 		(Bytef*)compressed,		// next_in
4167938b0dSPhilippe Houdoin 		compressedSize,			// avail_in
4267938b0dSPhilippe Houdoin 		0,						// total_in
4367938b0dSPhilippe Houdoin 		(Bytef*)uncompressed,	// next_out
4467938b0dSPhilippe Houdoin 		uncompressedSize,		// avail_out
4567938b0dSPhilippe Houdoin 		0,						// total_out
4667938b0dSPhilippe Houdoin 		0,						// msg
4767938b0dSPhilippe Houdoin 		0,						// state
4867938b0dSPhilippe Houdoin 		Z_NULL,					// zalloc (kernel_args_malloc?)
4967938b0dSPhilippe Houdoin 		Z_NULL,					// zfree (kernel_args_free?)
5067938b0dSPhilippe Houdoin 		Z_NULL,					// opaque
5167938b0dSPhilippe Houdoin 		0,						// data_type
5267938b0dSPhilippe Houdoin 		0,						// adler
5367938b0dSPhilippe Houdoin 		0						// reserved
5467938b0dSPhilippe Houdoin 	};
5567938b0dSPhilippe Houdoin 
5667938b0dSPhilippe Houdoin 	int zlibError = inflateInit(&zStream);
5767938b0dSPhilippe Houdoin 	if (zlibError != Z_OK)
5867938b0dSPhilippe Houdoin 		return B_ERROR;	// TODO: translate zlibError
5967938b0dSPhilippe Houdoin 
6067938b0dSPhilippe Houdoin 	// inflate
6167938b0dSPhilippe Houdoin 	status_t status = B_OK;
6267938b0dSPhilippe Houdoin 	zlibError = inflate(&zStream, Z_FINISH);
6367938b0dSPhilippe Houdoin 	if (zlibError != Z_STREAM_END) {
6467938b0dSPhilippe Houdoin 		if (zlibError == Z_OK)
6567938b0dSPhilippe Houdoin 			status = B_BUFFER_OVERFLOW;
6667938b0dSPhilippe Houdoin 		else
6767938b0dSPhilippe Houdoin 			status = B_ERROR;	// TODO: translate zlibError
6867938b0dSPhilippe Houdoin 	}
6967938b0dSPhilippe Houdoin 
7067938b0dSPhilippe Houdoin 	// clean up
7167938b0dSPhilippe Houdoin 	zlibError = inflateEnd(&zStream);
7267938b0dSPhilippe Houdoin 	if (zlibError != Z_OK && status == B_OK)
7367938b0dSPhilippe Houdoin 		status = B_ERROR;	// TODO: translate zlibError
7467938b0dSPhilippe Houdoin 
7567938b0dSPhilippe Houdoin 	if (status == B_OK && zStream.total_out != uncompressedSize)
7667938b0dSPhilippe Houdoin 		status = B_ERROR;
7767938b0dSPhilippe Houdoin 
7867938b0dSPhilippe Houdoin 	return status;
7967938b0dSPhilippe Houdoin }
8067938b0dSPhilippe Houdoin 
8167938b0dSPhilippe Houdoin 
827db9fbfeSFrançois Revol extern "C" status_t
8304cbc258SFredrik Holmqvist video_display_splash(addr_t frameBuffer)
847db9fbfeSFrançois Revol {
857db9fbfeSFrançois Revol 	if (!gKernelArgs.frame_buffer.enabled)
867db9fbfeSFrançois Revol 		return B_NO_INIT;
877db9fbfeSFrançois Revol 
8804cbc258SFredrik Holmqvist 	addr_t pos = 0;
8904cbc258SFredrik Holmqvist 	// Limit area to clear to estimated screen area
9004cbc258SFredrik Holmqvist 	// UEFI can happily report a >256M framebuffer
9104cbc258SFredrik Holmqvist 	addr_t size = min_c(gKernelArgs.frame_buffer.width
92*1368eabbSFredrik Holmqvist 			* gKernelArgs.frame_buffer.height * 4u,
937db9fbfeSFrançois Revol 		gKernelArgs.frame_buffer.physical_buffer.size);
947db9fbfeSFrançois Revol 
9504cbc258SFredrik Holmqvist 	if (size >= 64) {
9604cbc258SFredrik Holmqvist 		// Align writes
97*1368eabbSFredrik Holmqvist 		for (addr_t align = (8 - (frameBuffer & 7)) & 7; pos < align; pos++)
9804cbc258SFredrik Holmqvist 			*(char*)(frameBuffer + pos) = 0;
9904cbc258SFredrik Holmqvist 		// Write eight bytes, many many times, but not too many
10004cbc258SFredrik Holmqvist 		for (addr_t alignSize = size - 8; pos < alignSize; pos +=8) {
10104cbc258SFredrik Holmqvist 			*(uint32*)(frameBuffer + pos) = 0;
10204cbc258SFredrik Holmqvist 			*(uint32*)(frameBuffer + pos + 4) = 0;
10304cbc258SFredrik Holmqvist 		}
10404cbc258SFredrik Holmqvist 	}
10504cbc258SFredrik Holmqvist 	// Write a few bytes more
10604cbc258SFredrik Holmqvist 	for (; pos < size; pos++)
10704cbc258SFredrik Holmqvist 		*(char*)(frameBuffer + pos) = 0;
10804cbc258SFredrik Holmqvist 
1097db9fbfeSFrançois Revol 	uint8* uncompressedLogo = NULL;
11067938b0dSPhilippe Houdoin 	unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
1117db9fbfeSFrançois Revol 	switch (gKernelArgs.frame_buffer.depth) {
1127db9fbfeSFrançois Revol 		case 8:
1137db9fbfeSFrançois Revol 			platform_set_palette(k8BitPalette);
11467938b0dSPhilippe Houdoin 			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
1157db9fbfeSFrançois Revol 			if (uncompressedLogo == NULL)
1167db9fbfeSFrançois Revol 				return B_NO_MEMORY;
11767938b0dSPhilippe Houdoin 
11867938b0dSPhilippe Houdoin 			uncompress(kSplashLogo8BitCompressedImage,
11967938b0dSPhilippe Houdoin 				sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo,
12067938b0dSPhilippe Houdoin 				uncompressedSize);
1217db9fbfeSFrançois Revol 		break;
12267938b0dSPhilippe Houdoin 		default: // 24 bits is assumed here
12367938b0dSPhilippe Houdoin 			uncompressedSize *= 3;
12467938b0dSPhilippe Houdoin 			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
1257db9fbfeSFrançois Revol 			if (uncompressedLogo == NULL)
1267db9fbfeSFrançois Revol 				return B_NO_MEMORY;
12767938b0dSPhilippe Houdoin 
12867938b0dSPhilippe Houdoin 			uncompress(kSplashLogo24BitCompressedImage,
12967938b0dSPhilippe Houdoin 				sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo,
13067938b0dSPhilippe Houdoin 				uncompressedSize);
1317db9fbfeSFrançois Revol 		break;
1327db9fbfeSFrançois Revol 	}
1337db9fbfeSFrançois Revol 
1347db9fbfeSFrançois Revol 	// TODO: support 4-bit indexed version of the images!
1357db9fbfeSFrançois Revol 
1367db9fbfeSFrançois Revol 	// render splash logo
1377db9fbfeSFrançois Revol 	uint16 iconsHalfHeight = kSplashIconsHeight / 2;
1387db9fbfeSFrançois Revol 
1397db9fbfeSFrançois Revol 	int width = min_c(kSplashLogoWidth, gKernelArgs.frame_buffer.width);
1407db9fbfeSFrançois Revol 	int height = min_c(kSplashLogoHeight + iconsHalfHeight,
1417db9fbfeSFrançois Revol 		gKernelArgs.frame_buffer.height);
1427db9fbfeSFrançois Revol 	int placementX = max_c(0, min_c(100, kSplashLogoPlacementX));
1437db9fbfeSFrançois Revol 	int placementY = max_c(0, min_c(100, kSplashLogoPlacementY));
1447db9fbfeSFrançois Revol 
1457db9fbfeSFrançois Revol 	int x = (gKernelArgs.frame_buffer.width - width) * placementX / 100;
1467db9fbfeSFrançois Revol 	int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100;
1477db9fbfeSFrançois Revol 
1487db9fbfeSFrançois Revol 	height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height);
1497db9fbfeSFrançois Revol 	switch (gKernelArgs.frame_buffer.depth) {
1507db9fbfeSFrançois Revol 		case 8:
1517db9fbfeSFrançois Revol 			break;
1527db9fbfeSFrançois Revol 	}
1537db9fbfeSFrançois Revol 	video_blit_image(frameBuffer, uncompressedLogo, width, height,
1547db9fbfeSFrançois Revol 		kSplashLogoWidth, x, y);
1557db9fbfeSFrançois Revol 
1567db9fbfeSFrançois Revol 	kernel_args_free(uncompressedLogo);
1577db9fbfeSFrançois Revol 
1587db9fbfeSFrançois Revol 	const uint8* lowerHalfIconImage;
15967938b0dSPhilippe Houdoin 	uncompressedSize = kSplashIconsWidth * kSplashIconsHeight;
1607db9fbfeSFrançois Revol 	switch (gKernelArgs.frame_buffer.depth) {
1617db9fbfeSFrançois Revol 		case 8:
1627db9fbfeSFrançois Revol 			// pointer into the lower half of the icons image data
1637db9fbfeSFrançois Revol 			gKernelArgs.boot_splash
16467938b0dSPhilippe Houdoin 				= (uint8*)kernel_args_malloc(uncompressedSize);
16562d36f98SAlex Smith 			if (gKernelArgs.boot_splash == NULL)
1667db9fbfeSFrançois Revol 				return B_NO_MEMORY;
16767938b0dSPhilippe Houdoin 			uncompress(kSplashIcons8BitCompressedImage,
16867938b0dSPhilippe Houdoin 				sizeof(kSplashIcons8BitCompressedImage),
16967938b0dSPhilippe Houdoin 				gKernelArgs.boot_splash, uncompressedSize);
170d8efc6caSAlex Smith 			lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
1717db9fbfeSFrançois Revol 				+ (kSplashIconsWidth * iconsHalfHeight);
1727db9fbfeSFrançois Revol 		break;
17367938b0dSPhilippe Houdoin 		default:	// 24bits is assumed here
17467938b0dSPhilippe Houdoin 			uncompressedSize *= 3;
1757db9fbfeSFrançois Revol 			// pointer into the lower half of the icons image data
1767db9fbfeSFrançois Revol 			gKernelArgs.boot_splash
17767938b0dSPhilippe Houdoin 				= (uint8*)kernel_args_malloc(uncompressedSize);
17862d36f98SAlex Smith 			if (gKernelArgs.boot_splash == NULL)
1797db9fbfeSFrançois Revol 				return B_NO_MEMORY;
18067938b0dSPhilippe Houdoin 			uncompress(kSplashIcons24BitCompressedImage,
18167938b0dSPhilippe Houdoin 				sizeof(kSplashIcons24BitCompressedImage),
18267938b0dSPhilippe Houdoin 				gKernelArgs.boot_splash, uncompressedSize);
183d8efc6caSAlex Smith 			lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
1847db9fbfeSFrançois Revol 				+ (kSplashIconsWidth * iconsHalfHeight) * 3;
1857db9fbfeSFrançois Revol 		break;
1867db9fbfeSFrançois Revol 	}
1877db9fbfeSFrançois Revol 
1887db9fbfeSFrançois Revol 	// render initial (grayed out) icons
1897db9fbfeSFrançois Revol 	// the grayed out version is the lower half of the icons image
1907db9fbfeSFrançois Revol 
1917db9fbfeSFrançois Revol 	width = min_c(kSplashIconsWidth, gKernelArgs.frame_buffer.width);
1927db9fbfeSFrançois Revol 	height = min_c(kSplashLogoHeight + iconsHalfHeight,
1937db9fbfeSFrançois Revol 		gKernelArgs.frame_buffer.height);
1947db9fbfeSFrançois Revol 	placementX = max_c(0, min_c(100, kSplashIconsPlacementX));
1957db9fbfeSFrançois Revol 	placementY = max_c(0, min_c(100, kSplashIconsPlacementY));
1967db9fbfeSFrançois Revol 
1977db9fbfeSFrançois Revol 	x = (gKernelArgs.frame_buffer.width - width) * placementX / 100;
1987db9fbfeSFrançois Revol 	y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height)
1997db9fbfeSFrançois Revol 		* placementY / 100;
2007db9fbfeSFrançois Revol 
2017db9fbfeSFrançois Revol 	height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height);
2027db9fbfeSFrançois Revol 	video_blit_image(frameBuffer, lowerHalfIconImage, width, height,
2037db9fbfeSFrançois Revol 		kSplashIconsWidth, x, y);
204477d2636SFrançois Revol 	return B_OK;
2057db9fbfeSFrançois Revol }
2067db9fbfeSFrançois Revol 
20767938b0dSPhilippe Houdoin 
20867938b0dSPhilippe Houdoin 
209