xref: /haiku/src/system/boot/platform/generic/video_splash.cpp (revision de8d5cfb5fd2e2c7e78f004170fbb1d6cea614df)
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>
15029e447bSAugustin Cavalier #include <boot/platform/generic/video_blitter.h>
16*de8d5cfbSAugustin Cavalier 
1789fa2a85SPhilippe Houdoin #include <boot/images.h>
18*de8d5cfbSAugustin Cavalier #include <boot/platform/generic/video_splash.h>
197db9fbfeSFrançois Revol 
207db9fbfeSFrançois Revol #include <stdio.h>
217db9fbfeSFrançois Revol #include <stdlib.h>
227db9fbfeSFrançois Revol 
2367938b0dSPhilippe Houdoin #include <zlib.h>
2467938b0dSPhilippe Houdoin 
257db9fbfeSFrançois Revol 
267db9fbfeSFrançois Revol //#define TRACE_VIDEO
277db9fbfeSFrançois Revol #ifdef TRACE_VIDEO
287db9fbfeSFrançois Revol #	define TRACE(x) dprintf x
297db9fbfeSFrançois Revol #else
307db9fbfeSFrançois Revol #	define TRACE(x) ;
317db9fbfeSFrançois Revol #endif
327db9fbfeSFrançois Revol 
337db9fbfeSFrançois Revol 
3467938b0dSPhilippe Houdoin static status_t
uncompress(const uint8 compressed[],unsigned int compressedSize,uint8 * uncompressed,unsigned int uncompressedSize)3567938b0dSPhilippe Houdoin uncompress(const uint8 compressed[], unsigned int compressedSize,
3667938b0dSPhilippe Houdoin 	uint8* uncompressed, unsigned int uncompressedSize)
3767938b0dSPhilippe Houdoin {
3867938b0dSPhilippe Houdoin 	if (compressedSize == 0 || uncompressedSize == 0)
3967938b0dSPhilippe Houdoin 		return B_BAD_VALUE;
4067938b0dSPhilippe Houdoin 
4167938b0dSPhilippe Houdoin 	// prepare zlib stream
4267938b0dSPhilippe Houdoin 	z_stream zStream = {
4367938b0dSPhilippe Houdoin 		(Bytef*)compressed,		// next_in
4467938b0dSPhilippe Houdoin 		compressedSize,			// avail_in
4567938b0dSPhilippe Houdoin 		0,						// total_in
4667938b0dSPhilippe Houdoin 		(Bytef*)uncompressed,	// next_out
4767938b0dSPhilippe Houdoin 		uncompressedSize,		// avail_out
4867938b0dSPhilippe Houdoin 		0,						// total_out
4967938b0dSPhilippe Houdoin 		0,						// msg
5067938b0dSPhilippe Houdoin 		0,						// state
5167938b0dSPhilippe Houdoin 		Z_NULL,					// zalloc (kernel_args_malloc?)
5267938b0dSPhilippe Houdoin 		Z_NULL,					// zfree (kernel_args_free?)
5367938b0dSPhilippe Houdoin 		Z_NULL,					// opaque
5467938b0dSPhilippe Houdoin 		0,						// data_type
5567938b0dSPhilippe Houdoin 		0,						// adler
5667938b0dSPhilippe Houdoin 		0						// reserved
5767938b0dSPhilippe Houdoin 	};
5867938b0dSPhilippe Houdoin 
5967938b0dSPhilippe Houdoin 	int zlibError = inflateInit(&zStream);
6067938b0dSPhilippe Houdoin 	if (zlibError != Z_OK)
6167938b0dSPhilippe Houdoin 		return B_ERROR;	// TODO: translate zlibError
6267938b0dSPhilippe Houdoin 
6367938b0dSPhilippe Houdoin 	// inflate
6467938b0dSPhilippe Houdoin 	status_t status = B_OK;
6567938b0dSPhilippe Houdoin 	zlibError = inflate(&zStream, Z_FINISH);
6667938b0dSPhilippe Houdoin 	if (zlibError != Z_STREAM_END) {
6767938b0dSPhilippe Houdoin 		if (zlibError == Z_OK)
6867938b0dSPhilippe Houdoin 			status = B_BUFFER_OVERFLOW;
6967938b0dSPhilippe Houdoin 		else
7067938b0dSPhilippe Houdoin 			status = B_ERROR;	// TODO: translate zlibError
7167938b0dSPhilippe Houdoin 	}
7267938b0dSPhilippe Houdoin 
7367938b0dSPhilippe Houdoin 	// clean up
7467938b0dSPhilippe Houdoin 	zlibError = inflateEnd(&zStream);
7567938b0dSPhilippe Houdoin 	if (zlibError != Z_OK && status == B_OK)
7667938b0dSPhilippe Houdoin 		status = B_ERROR;	// TODO: translate zlibError
7767938b0dSPhilippe Houdoin 
7867938b0dSPhilippe Houdoin 	if (status == B_OK && zStream.total_out != uncompressedSize)
7967938b0dSPhilippe Houdoin 		status = B_ERROR;
8067938b0dSPhilippe Houdoin 
8167938b0dSPhilippe Houdoin 	return status;
8267938b0dSPhilippe Houdoin }
8367938b0dSPhilippe Houdoin 
8467938b0dSPhilippe Houdoin 
85029e447bSAugustin Cavalier extern "C" void
video_blit_image(addr_t frameBuffer,const uint8 * data,uint16 width,uint16 height,uint16 imageWidth,uint16 left,uint16 top)86029e447bSAugustin Cavalier video_blit_image(addr_t frameBuffer, const uint8 *data,
87029e447bSAugustin Cavalier 	uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top)
88029e447bSAugustin Cavalier {
89029e447bSAugustin Cavalier 	if (gKernelArgs.frame_buffer.depth == 4) {
90029e447bSAugustin Cavalier 		// call platform specific code since it's really platform-specific.
91029e447bSAugustin Cavalier 		platform_blit4(frameBuffer, data, width, height,
92029e447bSAugustin Cavalier 			imageWidth, left, top);
93029e447bSAugustin Cavalier 	} else {
94029e447bSAugustin Cavalier 		BlitParameters params;
95029e447bSAugustin Cavalier 		params.from = data;
96029e447bSAugustin Cavalier 		params.fromWidth = imageWidth;
97029e447bSAugustin Cavalier 		params.fromLeft = params.fromTop = 0;
98029e447bSAugustin Cavalier 		params.fromRight = width;
99029e447bSAugustin Cavalier 		params.fromBottom = height;
100029e447bSAugustin Cavalier 		params.to = (uint8*)frameBuffer;
101029e447bSAugustin Cavalier 		params.toBytesPerRow = gKernelArgs.frame_buffer.bytes_per_row;
102029e447bSAugustin Cavalier 		params.toLeft = left;
103029e447bSAugustin Cavalier 		params.toTop = top;
104029e447bSAugustin Cavalier 		blit(params, gKernelArgs.frame_buffer.depth);
105029e447bSAugustin Cavalier 	}
106029e447bSAugustin Cavalier }
107029e447bSAugustin Cavalier 
108029e447bSAugustin Cavalier 
1097db9fbfeSFrançois Revol extern "C" status_t
video_display_splash(addr_t frameBuffer)11004cbc258SFredrik Holmqvist video_display_splash(addr_t frameBuffer)
1117db9fbfeSFrançois Revol {
1127db9fbfeSFrançois Revol 	if (!gKernelArgs.frame_buffer.enabled)
1137db9fbfeSFrançois Revol 		return B_NO_INIT;
1147db9fbfeSFrançois Revol 
11504cbc258SFredrik Holmqvist 	addr_t pos = 0;
11604cbc258SFredrik Holmqvist 	// Limit area to clear to estimated screen area
11704cbc258SFredrik Holmqvist 	// UEFI can happily report a >256M framebuffer
11804cbc258SFredrik Holmqvist 	addr_t size = min_c(gKernelArgs.frame_buffer.width
1191368eabbSFredrik Holmqvist 			* gKernelArgs.frame_buffer.height * 4u,
1207db9fbfeSFrançois Revol 		gKernelArgs.frame_buffer.physical_buffer.size);
1217db9fbfeSFrançois Revol 
12204cbc258SFredrik Holmqvist 	if (size >= 64) {
12304cbc258SFredrik Holmqvist 		// Align writes
1241368eabbSFredrik Holmqvist 		for (addr_t align = (8 - (frameBuffer & 7)) & 7; pos < align; pos++)
12504cbc258SFredrik Holmqvist 			*(char*)(frameBuffer + pos) = 0;
12604cbc258SFredrik Holmqvist 		// Write eight bytes, many many times, but not too many
12704cbc258SFredrik Holmqvist 		for (addr_t alignSize = size - 8; pos < alignSize; pos +=8) {
12804cbc258SFredrik Holmqvist 			*(uint32*)(frameBuffer + pos) = 0;
12904cbc258SFredrik Holmqvist 			*(uint32*)(frameBuffer + pos + 4) = 0;
13004cbc258SFredrik Holmqvist 		}
13104cbc258SFredrik Holmqvist 	}
13204cbc258SFredrik Holmqvist 	// Write a few bytes more
13304cbc258SFredrik Holmqvist 	for (; pos < size; pos++)
13404cbc258SFredrik Holmqvist 		*(char*)(frameBuffer + pos) = 0;
13504cbc258SFredrik Holmqvist 
1367db9fbfeSFrançois Revol 	uint8* uncompressedLogo = NULL;
13767938b0dSPhilippe Houdoin 	unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
1387db9fbfeSFrançois Revol 	switch (gKernelArgs.frame_buffer.depth) {
1397db9fbfeSFrançois Revol 		case 8:
1407db9fbfeSFrançois Revol 			platform_set_palette(k8BitPalette);
14167938b0dSPhilippe Houdoin 			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
1427db9fbfeSFrançois Revol 			if (uncompressedLogo == NULL)
1437db9fbfeSFrançois Revol 				return B_NO_MEMORY;
14467938b0dSPhilippe Houdoin 
14567938b0dSPhilippe Houdoin 			uncompress(kSplashLogo8BitCompressedImage,
14667938b0dSPhilippe Houdoin 				sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo,
14767938b0dSPhilippe Houdoin 				uncompressedSize);
1487db9fbfeSFrançois Revol 		break;
14967938b0dSPhilippe Houdoin 		default: // 24 bits is assumed here
15067938b0dSPhilippe Houdoin 			uncompressedSize *= 3;
15167938b0dSPhilippe Houdoin 			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
1527db9fbfeSFrançois Revol 			if (uncompressedLogo == NULL)
1537db9fbfeSFrançois Revol 				return B_NO_MEMORY;
15467938b0dSPhilippe Houdoin 
15567938b0dSPhilippe Houdoin 			uncompress(kSplashLogo24BitCompressedImage,
15667938b0dSPhilippe Houdoin 				sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo,
15767938b0dSPhilippe Houdoin 				uncompressedSize);
1587db9fbfeSFrançois Revol 		break;
1597db9fbfeSFrançois Revol 	}
1607db9fbfeSFrançois Revol 
1617db9fbfeSFrançois Revol 	// TODO: support 4-bit indexed version of the images!
1627db9fbfeSFrançois Revol 
1637db9fbfeSFrançois Revol 	// render splash logo
164*de8d5cfbSAugustin Cavalier 	int width, height, x, y;
165*de8d5cfbSAugustin Cavalier 	compute_splash_logo_placement(gKernelArgs.frame_buffer.width, gKernelArgs.frame_buffer.height,
166*de8d5cfbSAugustin Cavalier 		width, height, x, y);
1677db9fbfeSFrançois Revol 	video_blit_image(frameBuffer, uncompressedLogo, width, height,
1687db9fbfeSFrançois Revol 		kSplashLogoWidth, x, y);
1697db9fbfeSFrançois Revol 
1707db9fbfeSFrançois Revol 	kernel_args_free(uncompressedLogo);
1717db9fbfeSFrançois Revol 
1727db9fbfeSFrançois Revol 	const uint8* lowerHalfIconImage;
17367938b0dSPhilippe Houdoin 	uncompressedSize = kSplashIconsWidth * kSplashIconsHeight;
174*de8d5cfbSAugustin Cavalier 	const uint16 iconsHalfHeight = kSplashIconsHeight / 2;
1757db9fbfeSFrançois Revol 	switch (gKernelArgs.frame_buffer.depth) {
1767db9fbfeSFrançois Revol 		case 8:
1777db9fbfeSFrançois Revol 			// pointer into the lower half of the icons image data
1787db9fbfeSFrançois Revol 			gKernelArgs.boot_splash
17967938b0dSPhilippe Houdoin 				= (uint8*)kernel_args_malloc(uncompressedSize);
18062d36f98SAlex Smith 			if (gKernelArgs.boot_splash == NULL)
1817db9fbfeSFrançois Revol 				return B_NO_MEMORY;
18267938b0dSPhilippe Houdoin 			uncompress(kSplashIcons8BitCompressedImage,
18367938b0dSPhilippe Houdoin 				sizeof(kSplashIcons8BitCompressedImage),
18467938b0dSPhilippe Houdoin 				gKernelArgs.boot_splash, uncompressedSize);
185d8efc6caSAlex Smith 			lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
1867db9fbfeSFrançois Revol 				+ (kSplashIconsWidth * iconsHalfHeight);
1877db9fbfeSFrançois Revol 		break;
18867938b0dSPhilippe Houdoin 		default:	// 24bits is assumed here
18967938b0dSPhilippe Houdoin 			uncompressedSize *= 3;
1907db9fbfeSFrançois Revol 			// pointer into the lower half of the icons image data
1917db9fbfeSFrançois Revol 			gKernelArgs.boot_splash
19267938b0dSPhilippe Houdoin 				= (uint8*)kernel_args_malloc(uncompressedSize);
19362d36f98SAlex Smith 			if (gKernelArgs.boot_splash == NULL)
1947db9fbfeSFrançois Revol 				return B_NO_MEMORY;
19567938b0dSPhilippe Houdoin 			uncompress(kSplashIcons24BitCompressedImage,
19667938b0dSPhilippe Houdoin 				sizeof(kSplashIcons24BitCompressedImage),
19767938b0dSPhilippe Houdoin 				gKernelArgs.boot_splash, uncompressedSize);
198d8efc6caSAlex Smith 			lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
1997db9fbfeSFrançois Revol 				+ (kSplashIconsWidth * iconsHalfHeight) * 3;
2007db9fbfeSFrançois Revol 		break;
2017db9fbfeSFrançois Revol 	}
2027db9fbfeSFrançois Revol 
2037db9fbfeSFrançois Revol 	// render initial (grayed out) icons
2047db9fbfeSFrançois Revol 	// the grayed out version is the lower half of the icons image
205*de8d5cfbSAugustin Cavalier 	compute_splash_icons_placement(gKernelArgs.frame_buffer.width, gKernelArgs.frame_buffer.height,
206*de8d5cfbSAugustin Cavalier 		width, height, x, y);
2077db9fbfeSFrançois Revol 
2087db9fbfeSFrançois Revol 	video_blit_image(frameBuffer, lowerHalfIconImage, width, height,
2097db9fbfeSFrançois Revol 		kSplashIconsWidth, x, y);
210477d2636SFrançois Revol 	return B_OK;
2117db9fbfeSFrançois Revol }
212