Use fast clearing of visible screen for splash

memset uses rep stosb on x86 during boot, with memory
not set to write-combining, which makes it slow.

Instead we do aligned writes of 2 x four bytes at once.
Only clear the minimum of size and width * height * 4
UEFI framebuffer size can be huge, upto 512MB here,
and rep stosb seems to be around 25-30MB/s

This is written as generic as possible to work on
old compilers and different platforms, without
expecting boot memset to be optimized.

This makes it almost unnoticable compared to not
clearing.
This commit is contained in:
Fredrik Holmqvist
2018-08-03 13:40:04 +02:00
parent 3a72e3ebee
commit 04cbc2588e
8 changed files with 28 additions and 13 deletions
@@ -32,7 +32,7 @@ void uncompress_24bit_RLE(const uint8 compressed[], uint8 *uncompressed);
void uncompress_8bit_RLE(const uint8 compressed[], uint8 *uncompressed);
/* default splash display */
status_t video_display_splash(addr_t frameBuffer, bool clear);
status_t video_display_splash(addr_t frameBuffer);
#ifdef __cplusplus
}
@@ -234,7 +234,7 @@ platform_switch_to_logo(void)
sFrameBuffer = gKernelArgs.frame_buffer.physical_buffer.start;
//video_display_splash(sFrameBuffer, true);
//video_display_splash(sFrameBuffer);
}
@@ -1153,7 +1153,7 @@ platform_switch_to_logo(void)
gKernelArgs.frame_buffer.physical_buffer.size, kDefaultPageFlags);
}
#endif
video_display_splash(sFrameBuffer, true);
video_display_splash(sFrameBuffer);
dump_vars();
spin(10000000);
platform_switch_to_text_mode();
+1 -1
View File
@@ -877,7 +877,7 @@ fallback:
gKernelArgs.frame_buffer.physical_buffer.size, kDefaultPageFlags);
}
video_display_splash(sFrameBuffer, true);
video_display_splash(sFrameBuffer);
}
+1 -1
View File
@@ -254,7 +254,7 @@ platform_switch_to_logo(void)
sGraphicsOutput->Mode->Info->PixelsPerScanLine
* gKernelArgs.frame_buffer.depth / 8;
video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start, false);
video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start);
}
@@ -16,7 +16,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
@@ -81,14 +80,31 @@ uncompress(const uint8 compressed[], unsigned int compressedSize,
extern "C" status_t
video_display_splash(addr_t frameBuffer, bool clear)
video_display_splash(addr_t frameBuffer)
{
if (!gKernelArgs.frame_buffer.enabled)
return B_NO_INIT;
if (clear)
memset((void*)frameBuffer, 0,
gKernelArgs.frame_buffer.physical_buffer.size);
addr_t pos = 0;
// Limit area to clear to estimated screen area
// UEFI can happily report a >256M framebuffer
addr_t size = min_c(gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height * 4,
gKernelArgs.frame_buffer.physical_buffer.size);
if (size >= 64) {
// Align writes
for (addr_t align = 8 - (frameBuffer & 7); pos < align; pos++)
*(char*)(frameBuffer + pos) = 0;
// Write eight bytes, many many times, but not too many
for (addr_t alignSize = size - 8; pos < alignSize; pos +=8) {
*(uint32*)(frameBuffer + pos) = 0;
*(uint32*)(frameBuffer + pos + 4) = 0;
}
}
// Write a few bytes more
for (; pos < size; pos++)
*(char*)(frameBuffer + pos) = 0;
uint8* uncompressedLogo = NULL;
unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
@@ -93,8 +93,7 @@ platform_switch_to_logo(void)
gKernelArgs.frame_buffer.enabled = true;
// the memory will be identity-mapped already
video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start,
true);
video_display_splash(gKernelArgs.frame_buffer.physical_buffer.start);
}
+1 -1
View File
@@ -89,7 +89,7 @@ platform_switch_to_logo(void)
return;
}
err = video_display_splash(gFramebuffer->Base(), true);
err = video_display_splash(gFramebuffer->Base());
}
}