Switched boot splash compression to use boot_zlib (which was already

used by tarfs anyway) instead of RLE.
While this should allows larger logo/icons, it doesn't remove the
current 300000 bytes size limits for haiku_loader, so #6710 is not yet fixed.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40215 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2011-01-12 15:43:14 +00:00
parent 6f8d1ab089
commit 67938b0d59
7 changed files with 9126 additions and 26873 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -2,6 +2,8 @@ SubDir HAIKU_TOP src system boot platform bios_ia32 ;
SubDirHdrs $(HAIKU_TOP) headers private kernel boot platform $(TARGET_BOOT_PLATFORM) ;
SubDirSysHdrs $(HAIKU_TOP) headers libs zlib ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateHeaders [ FDirName graphics vesa ] ;
@@ -21,7 +23,6 @@ local genericPlatformSources =
text_menu.cpp
video_blit.cpp
video_splash.cpp
video_rle.cpp
;
KernelMergeObject boot_platform_bios_ia32.o :
@@ -1,97 +0,0 @@
/*
* Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2008, Stephan Aßmus <superstippi@gmx.de>
* Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com>
* Distributed under the terms of the MIT License.
*/
#include <arch/cpu.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/kernel_args.h>
#include <boot/platform/generic/video.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRACE_VIDEO
#ifdef TRACE_VIDEO
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
void
uncompress_24bit_RLE(const uint8 compressed[], uint8 *uncompressed)
{
uint32 cursorUncompressed = 0;
uint32 cursorCompressed = 0;
uint8 count = 0;
uint8 item = 0;
int i = 0;
for (uint8 c = 0; c < 3; c++) {
// for Red channel, then Green, then finally Blue...
cursorUncompressed = c;
while (compressed[cursorCompressed]) {
// at the end of the channel there is a terminating 0,
// so the loop will end... (ref: generate_boot_screen.cpp)
count = compressed[cursorCompressed++];
if (count < 128) {
// regular run, repeat "item" "count" times...
item = compressed[cursorCompressed++];
for (i = count - 1; i >= 0; --i) {
uncompressed[cursorUncompressed] = item;
cursorUncompressed += 3;
}
} else {
// enumeration, just write the next "count" items as is...
count = count - 128;
for (i = count - 1; i >= 0; --i) {
uncompressed[cursorUncompressed]
= compressed[cursorCompressed++];
cursorUncompressed += 3;
}
}
}
// the current position of compressed[cursor] is the end of channel,
// we skip it...
cursorCompressed++;
}
}
void
uncompress_8bit_RLE(const uint8 compressed[], uint8 *uncompressed)
{
uint32 cursorUncompressed = 0;
uint32 cursorCompressed = 0;
uint8 count = 0;
uint8 item = 0;
int i = 0;
while (compressed[cursorCompressed]) {
// at the end of the channel there is a terminating 0,
// so the loop will end... (ref: generate_boot_screen.cpp)
count = compressed[cursorCompressed++];
if (count < 128) {
// regular run, repeat "item" "count" times...
item = compressed[cursorCompressed++];
for (i = count - 1; i >= 0; --i) {
uncompressed[cursorUncompressed] = item;
cursorUncompressed++;
}
} else {
// enumeration, just write the next "count" items as is...
count = count - 128;
for (i = count - 1; i >= 0; --i) {
uncompressed[cursorUncompressed]
= compressed[cursorCompressed++];
cursorUncompressed++;
}
}
}
}
@@ -18,6 +18,8 @@
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
//#define TRACE_VIDEO
#ifdef TRACE_VIDEO
@@ -27,6 +29,57 @@
#endif
static status_t
uncompress(const uint8 compressed[], unsigned int compressedSize,
uint8* uncompressed, unsigned int uncompressedSize)
{
if (compressedSize == 0 || uncompressedSize == 0)
return B_BAD_VALUE;
// prepare zlib stream
z_stream zStream = {
(Bytef*)compressed, // next_in
compressedSize, // avail_in
0, // total_in
(Bytef*)uncompressed, // next_out
uncompressedSize, // avail_out
0, // total_out
0, // msg
0, // state
Z_NULL, // zalloc (kernel_args_malloc?)
Z_NULL, // zfree (kernel_args_free?)
Z_NULL, // opaque
0, // data_type
0, // adler
0 // reserved
};
int zlibError = inflateInit(&zStream);
if (zlibError != Z_OK)
return B_ERROR; // TODO: translate zlibError
// inflate
status_t status = B_OK;
zlibError = inflate(&zStream, Z_FINISH);
if (zlibError != Z_STREAM_END) {
if (zlibError == Z_OK)
status = B_BUFFER_OVERFLOW;
else
status = B_ERROR; // TODO: translate zlibError
}
// clean up
zlibError = inflateEnd(&zStream);
if (zlibError != Z_OK && status == B_OK)
status = B_ERROR; // TODO: translate zlibError
if (status == B_OK && zStream.total_out != uncompressedSize)
status = B_ERROR;
return status;
}
extern "C" status_t
video_display_splash(addr_t frameBuffer)
{
@@ -34,27 +87,31 @@ video_display_splash(addr_t frameBuffer)
return B_NO_INIT;
// clear the video memory
memset((void *)frameBuffer, 0,
memset((void*)frameBuffer, 0,
gKernelArgs.frame_buffer.physical_buffer.size);
uint8 *uncompressedLogo = NULL;
uint8* uncompressedLogo = NULL;
unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
switch (gKernelArgs.frame_buffer.depth) {
case 8:
platform_set_palette(k8BitPalette);
uncompressedLogo = (uint8 *)kernel_args_malloc(kSplashLogoWidth
* kSplashLogoHeight);
uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
if (uncompressedLogo == NULL)
return B_NO_MEMORY;
uncompress_8bit_RLE(kSplashLogo8BitCompressedImage,
uncompressedLogo);
uncompress(kSplashLogo8BitCompressedImage,
sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo,
uncompressedSize);
break;
default:
uncompressedLogo = (uint8 *)kernel_args_malloc(kSplashLogoWidth
* kSplashLogoHeight * 3);
default: // 24 bits is assumed here
uncompressedSize *= 3;
uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
if (uncompressedLogo == NULL)
return B_NO_MEMORY;
uncompress_24bit_RLE(kSplashLogo24BitCompressedImage,
uncompressedLogo);
uncompress(kSplashLogo24BitCompressedImage,
sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo,
uncompressedSize);
break;
}
@@ -83,29 +140,30 @@ video_display_splash(addr_t frameBuffer)
kernel_args_free(uncompressedLogo);
const uint8* lowerHalfIconImage;
uncompressedSize = kSplashIconsWidth * kSplashIconsHeight;
switch (gKernelArgs.frame_buffer.depth) {
case 8:
// pointer into the lower half of the icons image data
gKernelArgs.boot_splash
= (uint8 *)kernel_args_malloc(kSplashIconsWidth
* kSplashIconsHeight);
= (uint8*)kernel_args_malloc(uncompressedSize);
if (gKernelArgs.boot_splash == NULL)
return B_NO_MEMORY;
uncompress_8bit_RLE(kSplashIcons8BitCompressedImage,
gKernelArgs.boot_splash );
uncompress(kSplashIcons8BitCompressedImage,
sizeof(kSplashIcons8BitCompressedImage),
gKernelArgs.boot_splash, uncompressedSize);
lowerHalfIconImage = gKernelArgs.boot_splash
+ (kSplashIconsWidth * iconsHalfHeight);
break;
default:
default: // 24bits is assumed here
uncompressedSize *= 3;
// pointer into the lower half of the icons image data
gKernelArgs.boot_splash
= (uint8 *)kernel_args_malloc(kSplashIconsWidth
* kSplashIconsHeight * 3);
= (uint8*)kernel_args_malloc(uncompressedSize);
if (gKernelArgs.boot_splash == NULL)
return B_NO_MEMORY;
uncompress_24bit_RLE(kSplashIcons24BitCompressedImage,
gKernelArgs.boot_splash );
uncompress(kSplashIcons24BitCompressedImage,
sizeof(kSplashIcons24BitCompressedImage),
gKernelArgs.boot_splash, uncompressedSize);
lowerHalfIconImage = gKernelArgs.boot_splash
+ (kSplashIconsWidth * iconsHalfHeight) * 3;
break;
@@ -130,3 +188,5 @@ video_display_splash(addr_t frameBuffer)
return B_OK;
}
+114 -185
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Haiku, Inc. All rights reserved.
* Copyright (c) 2008-2011, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
@@ -7,6 +7,7 @@
* Stephan Aßmus <superstippi@gmx.de>
* Philippe Saint-Pierre <stpere@gmail.com>
* David Powell <david@mad.scientist.com>
* Philippe Houdoin
*/
//! Haiku boot splash image generator/converter
@@ -18,6 +19,8 @@
#include <stdint.h>
#include <stdlib.h>
#include <zlib.h>
#include <ColorQuantizer.h>
// TODO: Create 4 bit palette version of these
@@ -41,6 +44,18 @@ error(const char *s, ...)
}
static void
new_line_if_required()
{
sOffset++;
if (sOffset % 12 == 0)
fprintf(sOutput, "\n\t");
}
// #pragma mark -
class AutoFileCloser {
public:
AutoFileCloser(FILE* file)
@@ -55,6 +70,93 @@ private:
};
// #pragma mark -
class ZlibCompressor {
public:
ZlibCompressor(FILE* output);
int Compress(const void* data, int dataSize, int flush = Z_NO_FLUSH);
int Finish();
private:
FILE* fOutput;
z_stream fStream;
};
ZlibCompressor::ZlibCompressor(FILE* output)
: fOutput(output)
{
// prepare zlib stream
fStream.next_in = NULL;
fStream.avail_in = 0;
fStream.total_in = 0;
fStream.next_out = NULL;
fStream.avail_out = 0;
fStream.total_out = 0;
fStream.msg = 0;
fStream.state = 0;
fStream.zalloc = Z_NULL;
fStream.zfree = Z_NULL;
fStream.opaque = Z_NULL;
fStream.data_type = 0;
fStream.adler = 0;
fStream.reserved = 0;
int zlibError = deflateInit(&fStream, Z_BEST_COMPRESSION);
if (zlibError != Z_OK)
return; // TODO: translate zlibError
}
int
ZlibCompressor::Compress(const void* data, int dataSize, int flush)
{
uint8 buffer[1024];
fStream.next_in = (Bytef*)data;
fStream.avail_in = dataSize;
int zlibError = Z_OK;
do {
fStream.next_out = (Bytef*)buffer;
fStream.avail_out = sizeof(buffer);
zlibError = deflate(&fStream, flush);
if (zlibError != Z_OK &&
(flush == Z_FINISH && zlibError != Z_STREAM_END))
return zlibError;
unsigned int outputSize = sizeof(buffer) - fStream.avail_out;
for (unsigned int i = 0; i < outputSize; i++) {
fprintf(fOutput, "%d, ", buffer[i]);
new_line_if_required();
}
if (zlibError == Z_STREAM_END)
break;
} while (fStream.avail_in > 0 || flush == Z_FINISH);
return zlibError;
}
int
ZlibCompressor::Finish()
{
Compress(NULL, 0, Z_FINISH);
return deflateEnd(&fStream);
}
// #pragma mark -
static void
read_png(const char* filename, int& width, int& height, png_bytep*& rowPtrs,
png_structp& pngPtr, png_infop& infoPtr)
@@ -125,15 +227,6 @@ read_png(const char* filename, int& width, int& height, png_bytep*& rowPtrs,
}
static void
new_line_if_required()
{
sOffset++;
if (sOffset % 12 == 0)
fprintf(sOutput, "\n\t");
}
static void
write_24bit_image(const char* baseName, int width, int height, png_bytep* rowPtrs)
{
@@ -141,104 +234,17 @@ write_24bit_image(const char* baseName, int width, int height, png_bytep* rowPtr
fprintf(sOutput, "static const uint16 %sHeight = %d;\n", baseName, height);
fprintf(sOutput, "#ifndef __BOOTSPLASH_KERNEL__\n");
int buffer[128];
// buffer[0] stores count, buffer[1..127] holds the actual values
fprintf(sOutput, "static uint8 %s24BitCompressedImage[] = {\n\t",
baseName);
for (int c = 0; c < 3; c++) {
// for each component i.e. R, G, B ...
// NOTE : I don't care much about performance at this step,
// decoding however...
int currentValue = rowPtrs[0][c];
int count = 0;
ZlibCompressor zlib(sOutput);
// When bufferActive == true, we store the number rather than writing
// them directly; we use this to store numbers until we find a pair..
bool bufferActive = false;
for (int y = 0; y < height; y++)
zlib.Compress(rowPtrs[y], width * 3);
sOffset = 0;
zlib.Finish();
for (int y = 0; y < height; y++) {
png_byte* row = rowPtrs[y];
for (int x = c; x < width * 3; x += 3) {
if (row[x] == currentValue) {
if (bufferActive) {
bufferActive = false;
count = 2;
if (buffer[0] > 1) {
fprintf(sOutput, "%d, ",
128 + buffer[0] - 1);
new_line_if_required();
for (int i = 1; i < buffer[0] ; i++) {
fprintf(sOutput, "%d, ",
buffer[i]);
new_line_if_required();
}
}
} else {
count++;
if (count == 127) {
fprintf(sOutput, "127, ");
new_line_if_required();
fprintf(sOutput, "%d, ", currentValue);
new_line_if_required();
count = 0;
}
}
} else {
if (bufferActive) {
if (buffer[0] == 127) {
// we don't have enough room,
// flush the buffer
fprintf(sOutput, "%d, ",
128 + buffer[0] - 1);
new_line_if_required();
for (int i = 1; i < buffer[0]; i++) {
fprintf(sOutput, "%d, ", buffer[i]);
new_line_if_required();
}
buffer[0] = 0;
}
} else {
if (count > 0) {
fprintf(sOutput, "%d, ", count);
new_line_if_required();
fprintf(sOutput, "%d, ", currentValue);
new_line_if_required();
}
buffer[0] = 0;
bufferActive = true;
}
buffer[0]++;
buffer[buffer[0]] = row[x];
currentValue = row[x];
}
}
}
if (bufferActive) {
// I could have written 127 + buffer[0],
// but I think this is more readable...
fprintf(sOutput, "%d, ", 128 + buffer[0] - 1);
new_line_if_required();
for (int i = 1; i < buffer[0] ; i++) {
fprintf(sOutput, "%d, ", buffer[i]);
new_line_if_required();
}
} else {
fprintf(sOutput, "%d, %d, ", count, currentValue);
new_line_if_required();
}
// we put a terminating zero for the next byte that indicates
// a "count", just to indicate the end of the channel
fprintf(sOutput, "0");
if (c != 2)
fprintf(sOutput, ",");
fprintf(sOutput, "\n\t");
}
fprintf(sOutput, "};\n");
fprintf(sOutput, "\n};\n");
fprintf(sOutput, "#endif\n\n");
}
@@ -252,92 +258,15 @@ write_8bit_image(const char* baseName, int width, int height, unsigned char** ro
fprintf(sOutput, "static uint8 %s8BitCompressedImage[] = {\n\t",
baseName);
// NOTE: I don't care much about performance at this step,
// decoding however...
unsigned char currentValue = rowPtrs[0][0];
int count = 0;
// When bufferActive == true, we store the number rather than writing
// them directly; we use this to store numbers until we find a pair..
bool bufferActive = false;
ZlibCompressor zlib(sOutput);
sOffset = 0;
for (int y = 0; y < height; y++) {
unsigned char* row = rowPtrs[y];
for (int x = 0; x < width; x++) {
if (row[x] == currentValue) {
if (bufferActive) {
bufferActive = false;
count = 2;
if (buffer[0] > 1) {
fprintf(sOutput, "%d, ",
128 + buffer[0] - 1);
new_line_if_required();
for (int i = 1; i < buffer[0] ; i++) {
fprintf(sOutput, "%d, ",
buffer[i]);
new_line_if_required();
}
}
} else {
count++;
if (count == 127) {
fprintf(sOutput, "127, ");
new_line_if_required();
fprintf(sOutput, "%d, ", currentValue);
new_line_if_required();
count = 0;
}
}
} else {
if (bufferActive) {
if (buffer[0] == 127) {
// we don't have enough room,
// flush the buffer
fprintf(sOutput, "%d, ",
128 + buffer[0] - 1);
new_line_if_required();
for (int i = 1; i < buffer[0]; i++) {
fprintf(sOutput, "%d, ", buffer[i]);
new_line_if_required();
}
buffer[0] = 0;
}
} else {
if (count > 0) {
fprintf(sOutput, "%d, ", count);
new_line_if_required();
fprintf(sOutput, "%d, ", currentValue);
new_line_if_required();
}
buffer[0] = 0;
bufferActive = true;
}
buffer[0]++;
buffer[buffer[0]] = row[x];
currentValue = row[x];
}
}
}
if (bufferActive) {
// I could have written 127 + buffer[0],
// but I think this is more readable...
fprintf(sOutput, "%d, ", 128 + buffer[0] - 1);
new_line_if_required();
for (int i = 1; i < buffer[0] ; i++) {
fprintf(sOutput, "%d, ", buffer[i]);
new_line_if_required();
}
} else {
fprintf(sOutput, "%d, %d, ", count, currentValue);
new_line_if_required();
}
// we put a terminating zero for the next byte that indicates
// a "count", to indicate the end
fprintf(sOutput, "0");
for (int y = 0; y < height; y++)
zlib.Compress(rowPtrs[y], width);
fprintf(sOutput, "\n\t");
fprintf(sOutput, "};\n\n");
zlib.Finish();
fprintf(sOutput, "\n};\n\n");
}