Patch by Philippe Saint-Pierre:
* Implemented RLE compression for the boot splash images, resulting in smaller kernel and boot loader. * Only the boot loader contains the RLE compressed images, the decompressed buffer for the icons is passed to the kernel via kernel args. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24812 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+5453
-15090
File diff suppressed because it is too large
Load Diff
@@ -79,6 +79,10 @@ typedef struct kernel_args {
|
|||||||
|
|
||||||
platform_kernel_args platform_args;
|
platform_kernel_args platform_args;
|
||||||
arch_kernel_args arch_args;
|
arch_kernel_args arch_args;
|
||||||
|
|
||||||
|
// bootsplash data
|
||||||
|
uint8 *boot_splash;
|
||||||
|
|
||||||
} kernel_args;
|
} kernel_args;
|
||||||
|
|
||||||
#endif /* KERNEL_BOOT_KERNEL_ARGS_H */
|
#endif /* KERNEL_BOOT_KERNEL_ARGS_H */
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BOOT_SPLASH_STAGE_1_INIT_MODULES = 0,
|
BOOT_SPLASH_STAGE_1_INIT_MODULES = 0,
|
||||||
BOOT_SPLASH_STAGE_2_BOOTSTRAP_FS,
|
BOOT_SPLASH_STAGE_2_BOOTSTRAP_FS,
|
||||||
@@ -29,7 +28,7 @@ enum {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void boot_splash_init(void);
|
void boot_splash_init(uint8 * boot_splash);
|
||||||
void boot_splash_set_stage(int stage);
|
void boot_splash_set_stage(int stage);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -794,6 +794,18 @@ blit_image(const uint8 *data, const uint8* indexedData, uint16 width,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uncompress_RLE(const RLE_element *compressed, uint8 *uncompressed, uint32 size)
|
||||||
|
{
|
||||||
|
uint32 cursor = 0;
|
||||||
|
for (uint32 i = 0; i < size; i++) {
|
||||||
|
memset(uncompressed + cursor, compressed[i].colorComponent,
|
||||||
|
compressed[i].count);
|
||||||
|
cursor += compressed[i].count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
@@ -868,8 +880,14 @@ fallback:
|
|||||||
memset((void *)sFrameBuffer, 0,
|
memset((void *)sFrameBuffer, 0,
|
||||||
gKernelArgs.frame_buffer.physical_buffer.size);
|
gKernelArgs.frame_buffer.physical_buffer.size);
|
||||||
|
|
||||||
|
uint8 *uncompressedLogo = (uint8 *)kernel_args_malloc(kSplashLogoWidth
|
||||||
|
* kSplashLogoHeight * 3);
|
||||||
|
if (uncompressedLogo == NULL)
|
||||||
|
return;
|
||||||
|
uncompress_RLE(kSplashLogoCompressedImage, uncompressedLogo,
|
||||||
|
kSplashLogoSize);
|
||||||
|
|
||||||
// TODO: support indexed versions of the images!
|
// TODO: support indexed versions of the images!
|
||||||
// TODO: support compressed RGB image data (simple RLE?)
|
|
||||||
|
|
||||||
// render splash logo
|
// render splash logo
|
||||||
uint16 iconsHalfHeight = kSplashIconsHeight / 2;
|
uint16 iconsHalfHeight = kSplashIconsHeight / 2;
|
||||||
@@ -884,9 +902,18 @@ fallback:
|
|||||||
int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100;
|
int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100;
|
||||||
|
|
||||||
height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height);
|
height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height);
|
||||||
blit_image(kSplashLogoImage, NULL, width, height, kSplashLogoWidth,
|
blit_image(uncompressedLogo, NULL, width, height, kSplashLogoWidth,
|
||||||
NULL, x, y);
|
NULL, x, y);
|
||||||
|
|
||||||
|
kernel_args_free(uncompressedLogo);
|
||||||
|
|
||||||
|
gKernelArgs.boot_splash = (uint8 *)kernel_args_malloc(kSplashIconsWidth
|
||||||
|
* kSplashIconsHeight * 3);
|
||||||
|
if (gKernelArgs.boot_splash == NULL)
|
||||||
|
return;
|
||||||
|
uncompress_RLE(kSplashIconsCompressedImage, gKernelArgs.boot_splash,
|
||||||
|
kSplashIconsSize);
|
||||||
|
|
||||||
// render initial (grayed out) icons
|
// render initial (grayed out) icons
|
||||||
// the grayed out version is the lower half of the icons image
|
// the grayed out version is the lower half of the icons image
|
||||||
|
|
||||||
@@ -901,7 +928,7 @@ fallback:
|
|||||||
* placementY / 100;
|
* placementY / 100;
|
||||||
|
|
||||||
// pointer into the lower half of the icons image data
|
// pointer into the lower half of the icons image data
|
||||||
const uint8* lowerHalfIconImage = kSplashIconsImage
|
const uint8* lowerHalfIconImage = gKernelArgs.boot_splash
|
||||||
+ (kSplashIconsWidth * iconsHalfHeight) * 3;
|
+ (kSplashIconsWidth * iconsHalfHeight) * 3;
|
||||||
height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height);
|
height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height);
|
||||||
blit_image(lowerHalfIconImage, NULL, width, height,
|
blit_image(lowerHalfIconImage, NULL, width, height,
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <boot_splash.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -16,11 +14,16 @@
|
|||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#define __BOOTSPLASH_KERNEL__
|
||||||
#include <boot/images.h>
|
#include <boot/images.h>
|
||||||
|
|
||||||
|
|
||||||
#include <boot_item.h>
|
#include <boot_item.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <frame_buffer_console.h>
|
#include <frame_buffer_console.h>
|
||||||
|
|
||||||
|
#include <boot_splash.h>
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_BOOT_SPLASH 1
|
//#define TRACE_BOOT_SPLASH 1
|
||||||
#ifdef TRACE_BOOT_SPLASH
|
#ifdef TRACE_BOOT_SPLASH
|
||||||
@@ -31,7 +34,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static struct frame_buffer_boot_info *sInfo;
|
static struct frame_buffer_boot_info *sInfo;
|
||||||
|
static uint8 *sUncompressedIcons;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
blit15_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
blit15_cropped(const uint8 *data, uint16 imageLeft, uint16 imageTop,
|
||||||
@@ -168,7 +171,7 @@ blit_cropped(const uint8* data, const uint8* indexedData,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
boot_splash_init(void)
|
boot_splash_init(uint8 *boot_splash)
|
||||||
{
|
{
|
||||||
TRACE("boot_splash_init: enter\n");
|
TRACE("boot_splash_init: enter\n");
|
||||||
|
|
||||||
@@ -177,6 +180,8 @@ boot_splash_init(void)
|
|||||||
|
|
||||||
sInfo = (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO,
|
sInfo = (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
sUncompressedIcons = boot_splash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -201,7 +206,7 @@ boot_splash_set_stage(int stage)
|
|||||||
int stageRightEdge = width * (stage + 1) / BOOT_SPLASH_STAGE_MAX;
|
int stageRightEdge = width * (stage + 1) / BOOT_SPLASH_STAGE_MAX;
|
||||||
|
|
||||||
height = min_c(iconsHalfHeight, sInfo->height);
|
height = min_c(iconsHalfHeight, sInfo->height);
|
||||||
blit_cropped(kSplashIconsImage, NULL, stageLeftEdge, 0, stageRightEdge,
|
blit_cropped(sUncompressedIcons, NULL, stageLeftEdge, 0, stageRightEdge,
|
||||||
height, kSplashIconsWidth, NULL, x, y);
|
height, kSplashIconsWidth, NULL, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ main2(void *unused)
|
|||||||
|
|
||||||
TRACE("start of main2: initializing devices\n");
|
TRACE("start of main2: initializing devices\n");
|
||||||
|
|
||||||
boot_splash_init();
|
boot_splash_init(sKernelArgs.boot_splash);
|
||||||
|
|
||||||
TRACE("Init modules\n");
|
TRACE("Init modules\n");
|
||||||
boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES);
|
boot_splash_set_stage(BOOT_SPLASH_STAGE_1_INIT_MODULES);
|
||||||
@@ -282,6 +282,10 @@ main2(void *unused)
|
|||||||
device_manager_init_post_modules(&sKernelArgs);
|
device_manager_init_post_modules(&sKernelArgs);
|
||||||
|
|
||||||
boot_splash_set_stage(BOOT_SPLASH_STAGE_7_RUN_BOOT_SCRIPT);
|
boot_splash_set_stage(BOOT_SPLASH_STAGE_7_RUN_BOOT_SCRIPT);
|
||||||
|
// kernel_args_free(sKernelArgs.boot_splash);
|
||||||
|
// NOTE: We could introduce a syscall to draw more icons indicating
|
||||||
|
// stages in the boot script itself. Then we should not free the image.
|
||||||
|
|
||||||
// start the init process
|
// start the init process
|
||||||
{
|
{
|
||||||
const char *args[] = {"/bin/sh", "/boot/beos/system/boot/Bootscript",
|
const char *args[] = {"/bin/sh", "/boot/beos/system/boot/Bootscript",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
// TODO: Generate the single optimal palette for all three images,
|
// TODO: Generate the single optimal palette for all three images,
|
||||||
// store palette versions of these images as well, so that they are
|
// store palette versions of these images as well, so that they are
|
||||||
@@ -123,22 +124,43 @@ writeHeader(const char* baseName, int width, int height, png_bytep* rowPtrs)
|
|||||||
{
|
{
|
||||||
fprintf(sOutput, "static const uint16 %sWidth = %d;\n", baseName, width);
|
fprintf(sOutput, "static const uint16 %sWidth = %d;\n", baseName, width);
|
||||||
fprintf(sOutput, "static const uint16 %sHeight = %d;\n", baseName, height);
|
fprintf(sOutput, "static const uint16 %sHeight = %d;\n", baseName, height);
|
||||||
fprintf(sOutput, "static const uint8 %sImage[] = {\n\t", baseName);
|
fprintf(sOutput, "#ifndef __BOOTSPLASH_KERNEL__\n");
|
||||||
|
fprintf(sOutput, "static const RLE_element %sCompressedImage[] = {\n\t",
|
||||||
|
baseName);
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
int lastColor = -1;
|
||||||
|
int counter = 0;
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
png_byte* row = rowPtrs[y];
|
png_byte* row = rowPtrs[y];
|
||||||
for (int x = 0; x < width * 3; x++) {
|
for (int x = 0; x < width * 3; x++) {
|
||||||
offset++;
|
if (lastColor == row[x]) {
|
||||||
|
// if the currentColor is already being counted...
|
||||||
|
counter++;
|
||||||
|
} else {
|
||||||
|
// otherwise display what we had in memory, record that color
|
||||||
|
// and reset the counter...
|
||||||
|
if (lastColor != -1) {
|
||||||
|
offset++;
|
||||||
|
fprintf(sOutput, "{%d, 0x%02x}, ", counter, lastColor);
|
||||||
|
if (offset % 6 == 0) {
|
||||||
|
fprintf(sOutput, "\n\t");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastColor = row[x];
|
||||||
|
counter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (x == width * 3 - 1 && y == height - 1) {
|
if (x == width * 3 - 1 && y == height - 1) {
|
||||||
fprintf(sOutput, "0x%02x\n};\n\n", row[x]);
|
// we have reach the end
|
||||||
|
fprintf(sOutput, "{%d, 0x%02x}\n};\n\n", counter, row[x]);
|
||||||
|
offset++;
|
||||||
break;
|
break;
|
||||||
} else if ((offset % 12) == 0)
|
}
|
||||||
fprintf(sOutput, "0x%02x,\n\t", row[x]);
|
|
||||||
else
|
|
||||||
fprintf(sOutput, "0x%02x, ", row[x]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fprintf(sOutput, "static const uint32 %sSize = %d;\n", baseName, offset);
|
||||||
|
fprintf(sOutput, "#endif\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -210,6 +232,9 @@ main(int argc, char* argv[])
|
|||||||
fprintf(sOutput, "static const int32 kSplashIconsPlacementY = %d;\n\n",
|
fprintf(sOutput, "static const int32 kSplashIconsPlacementY = %d;\n\n",
|
||||||
iconPlacementY);
|
iconPlacementY);
|
||||||
|
|
||||||
|
fprintf(sOutput, "struct RLE_element \n{\n\tuint16 count; \n\tuint8 "
|
||||||
|
"colorComponent;\n};\n\n");
|
||||||
|
|
||||||
parseImage(argv[1], "kSplashLogo");
|
parseImage(argv[1], "kSplashLogo");
|
||||||
parseImage(argv[4], "kSplashIcons");
|
parseImage(argv[4], "kSplashIcons");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user