Implement frame buffer double-buffering
This slowed down drawing to video in QEMU/VirtualBox but greatly sped up doing so on real hardware (no longer reading from video memory). Despite the speed-up, it is still quite slow though.
This commit is contained in:
parent
55604468c8
commit
edba40b2c6
@ -13,8 +13,11 @@ import hulk.kfont;
|
||||
*/
|
||||
struct fb
|
||||
{
|
||||
/** Frame buffer base address. */
|
||||
private __gshared static uint * m_buffer;
|
||||
/** Device frame buffer base address. */
|
||||
private __gshared static uint * m_device_buffer;
|
||||
|
||||
/** Frame buffer 1 base address. */
|
||||
private __gshared static uint * m_buffer1;
|
||||
|
||||
/** Frame buffer width. */
|
||||
private __gshared static uint m_width;
|
||||
@ -47,14 +50,16 @@ struct fb
|
||||
/**
|
||||
* Initialize a frame buffer.
|
||||
*
|
||||
* @param buffer Frame buffer base address.
|
||||
* @param device_buffer Device frame buffer base address.
|
||||
* @param buffer1 Frame buffer 1 base address.
|
||||
* @param width Frame buffer width.
|
||||
* @param height Frame buffer height.
|
||||
* @param stride Frame buffer stride.
|
||||
*/
|
||||
static void initialize(uint * buffer, uint width, uint height, uint stride)
|
||||
static void initialize(uint * device_buffer, uint * buffer1, uint width, uint height, uint stride)
|
||||
{
|
||||
m_buffer = buffer;
|
||||
m_device_buffer = device_buffer;
|
||||
m_buffer1 = buffer1;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_stride = stride;
|
||||
@ -68,7 +73,8 @@ struct fb
|
||||
*/
|
||||
static void clear(uint color = 0u)
|
||||
{
|
||||
memset32(m_buffer, color, m_buffer_size);
|
||||
memset32(m_buffer1, color, m_buffer_size);
|
||||
memset32(m_device_buffer, color, m_buffer_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +91,8 @@ struct fb
|
||||
for (size_t iy = 0u; iy < height; iy++)
|
||||
{
|
||||
size_t buffer_index = buffer_index(x, y);
|
||||
memset32(&m_buffer[buffer_index], color, width);
|
||||
memset32(&m_buffer1[buffer_index], color, width);
|
||||
memset32(&m_device_buffer[buffer_index], color, width);
|
||||
y++;
|
||||
}
|
||||
}
|
||||
@ -101,7 +108,8 @@ struct fb
|
||||
static void hline(size_t x, size_t y, size_t width, uint color)
|
||||
{
|
||||
size_t buffer_index = buffer_index(x, y);
|
||||
memset32(&m_buffer[buffer_index], color, width);
|
||||
memset32(&m_buffer1[buffer_index], color, width);
|
||||
memset32(&m_device_buffer[buffer_index], color, width);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,7 +125,8 @@ struct fb
|
||||
size_t buffer_index = buffer_index(x, y);
|
||||
for (size_t iy = 0u; iy < height; iy++)
|
||||
{
|
||||
m_buffer[buffer_index] = color;
|
||||
m_buffer1[buffer_index] = color;
|
||||
m_device_buffer[buffer_index] = color;
|
||||
buffer_index -= m_stride;
|
||||
}
|
||||
}
|
||||
@ -153,17 +162,19 @@ struct fb
|
||||
size_t bitmap_index;
|
||||
for (size_t iy = 0u; iy < height; iy++)
|
||||
{
|
||||
size_t row_buffer_index = buffer_index(x, y);
|
||||
for (size_t ix = 0u; ix < width; ix++)
|
||||
{
|
||||
size_t buffer_index = buffer_index(x + ix, y);
|
||||
size_t buffer_index = row_buffer_index + ix;
|
||||
ubyte alpha = alpha_bitmap[bitmap_index];
|
||||
uint current_color = m_buffer[buffer_index];
|
||||
uint current_color = m_buffer1[buffer_index];
|
||||
uint in_color_scaled = scale_color(color, alpha);
|
||||
uint old_color_scaled = scale_color(current_color, 255u - alpha);
|
||||
uint new_color = old_color_scaled + in_color_scaled;
|
||||
m_buffer[buffer_index] = new_color;
|
||||
m_buffer1[buffer_index] = new_color;
|
||||
bitmap_index++;
|
||||
}
|
||||
memcpy32(&m_device_buffer[row_buffer_index], &m_buffer1[row_buffer_index], width);
|
||||
y--;
|
||||
}
|
||||
}
|
||||
@ -202,13 +213,15 @@ struct fb
|
||||
size_t bitmap_index;
|
||||
for (size_t iy = 0u; iy < height; iy++)
|
||||
{
|
||||
size_t row_buffer_index = buffer_index(x, y);
|
||||
for (size_t ix = 0u; ix < width; ix++)
|
||||
{
|
||||
size_t buffer_index = buffer_index(x + ix, y);
|
||||
size_t buffer_index = row_buffer_index + ix;
|
||||
ubyte alpha = alpha_bitmap[bitmap_index];
|
||||
m_buffer[buffer_index] = (alpha << 16u) | (alpha << 8u) | alpha;
|
||||
m_buffer1[buffer_index] = (alpha << 16u) | (alpha << 8u) | alpha;
|
||||
bitmap_index++;
|
||||
}
|
||||
memcpy32(&m_device_buffer[row_buffer_index], &m_buffer1[row_buffer_index], width);
|
||||
y--;
|
||||
}
|
||||
}
|
||||
@ -239,9 +252,14 @@ struct fb
|
||||
*/
|
||||
static void copy_rows_up(size_t y, size_t height, size_t offset)
|
||||
{
|
||||
memcpy32(&m_buffer[buffer_index(0u, y + height + offset - 1u)],
|
||||
&m_buffer[buffer_index(0u, y + height - 1u)],
|
||||
size_t dest_buffer_index = buffer_index(0u, y + height + offset - 1u);
|
||||
size_t src_buffer_index = buffer_index(0u, y + height - 1u);
|
||||
memcpy32(&m_buffer1[dest_buffer_index],
|
||||
&m_buffer1[src_buffer_index],
|
||||
(m_stride * height));
|
||||
memcpy32(&m_device_buffer[dest_buffer_index],
|
||||
&m_buffer1[dest_buffer_index],
|
||||
(m_stride * height));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +57,11 @@ void hulk_start()
|
||||
initialize_cpu();
|
||||
gdt.initialize();
|
||||
idt.initialize();
|
||||
fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride);
|
||||
fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
||||
cast(uint *)hulk_header.bootinfo.fb_buffer1_phys,
|
||||
hulk_header.bootinfo.fb.width,
|
||||
hulk_header.bootinfo.fb.height,
|
||||
hulk_header.bootinfo.fb.stride);
|
||||
console.initialize();
|
||||
console.clear();
|
||||
klog.initialize();
|
||||
|
@ -83,11 +83,16 @@ struct hurl
|
||||
header.bootinfo.stack_phys,
|
||||
header.stack_size,
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
/* Map HULK framebuffer. */
|
||||
/* Map device framebuffer. */
|
||||
map_range(HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
||||
cast(ulong)header.bootinfo.fb.buffer,
|
||||
header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u,
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
/* Map framebuffer buffer1. */
|
||||
map_range(cast(ulong)header.bootinfo.fb_buffer1_phys,
|
||||
cast(ulong)header.bootinfo.fb_buffer1_phys,
|
||||
header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u,
|
||||
PT_WRITABLE | PT_NO_EXECUTE);
|
||||
write_cr3(cast(ulong)m_pt_base);
|
||||
}
|
||||
|
||||
@ -143,12 +148,14 @@ struct hurl
|
||||
* 3) HULK BSS
|
||||
* 4) HULK stack
|
||||
* 5) bootloader page table pages
|
||||
* 6) framebuffer buffer1
|
||||
*/
|
||||
size_t usable_memory;
|
||||
size_t physical_address_limit;
|
||||
const(size_t) fb_size = (header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u + PAGE_SIZE - 1u) & ~(PAGE_SIZE - 1u);
|
||||
ulong[2][2] reserved = [
|
||||
[header.bootinfo.hulk_phys, LinkerAddresses.hulk_binary_size],
|
||||
[cast(ulong)header.bootinfo.fb.buffer, header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u],
|
||||
[cast(ulong)header.bootinfo.fb.buffer, fb_size],
|
||||
];
|
||||
for (size_t ri = 0u; ri < reserved.length; ri++)
|
||||
{
|
||||
@ -205,6 +212,7 @@ struct hurl
|
||||
|
||||
usable_memory += LinkerAddresses.hulk_bss_size;
|
||||
usable_memory += header.stack_size;
|
||||
usable_memory += fb_size;
|
||||
klog.writefln("Usable memory: %uKB", usable_memory >> 10u);
|
||||
klog.writefln("Kernel size: %uKB", (LinkerAddresses.hulk_binary_size + LinkerAddresses.hulk_bss_size + header.stack_size) >> 10u);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user