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
|
struct fb
|
||||||
{
|
{
|
||||||
/** Frame buffer base address. */
|
/** Device frame buffer base address. */
|
||||||
private __gshared static uint * m_buffer;
|
private __gshared static uint * m_device_buffer;
|
||||||
|
|
||||||
|
/** Frame buffer 1 base address. */
|
||||||
|
private __gshared static uint * m_buffer1;
|
||||||
|
|
||||||
/** Frame buffer width. */
|
/** Frame buffer width. */
|
||||||
private __gshared static uint m_width;
|
private __gshared static uint m_width;
|
||||||
@ -47,14 +50,16 @@ struct fb
|
|||||||
/**
|
/**
|
||||||
* Initialize a frame buffer.
|
* 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 width Frame buffer width.
|
||||||
* @param height Frame buffer height.
|
* @param height Frame buffer height.
|
||||||
* @param stride Frame buffer stride.
|
* @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_width = width;
|
||||||
m_height = height;
|
m_height = height;
|
||||||
m_stride = stride;
|
m_stride = stride;
|
||||||
@ -68,7 +73,8 @@ struct fb
|
|||||||
*/
|
*/
|
||||||
static void clear(uint color = 0u)
|
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++)
|
for (size_t iy = 0u; iy < height; iy++)
|
||||||
{
|
{
|
||||||
size_t buffer_index = buffer_index(x, y);
|
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++;
|
y++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +108,8 @@ struct fb
|
|||||||
static void hline(size_t x, size_t y, size_t width, uint color)
|
static void hline(size_t x, size_t y, size_t width, uint color)
|
||||||
{
|
{
|
||||||
size_t buffer_index = buffer_index(x, y);
|
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);
|
size_t buffer_index = buffer_index(x, y);
|
||||||
for (size_t iy = 0u; iy < height; iy++)
|
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;
|
buffer_index -= m_stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,17 +162,19 @@ struct fb
|
|||||||
size_t bitmap_index;
|
size_t bitmap_index;
|
||||||
for (size_t iy = 0u; iy < height; iy++)
|
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++)
|
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];
|
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 in_color_scaled = scale_color(color, alpha);
|
||||||
uint old_color_scaled = scale_color(current_color, 255u - alpha);
|
uint old_color_scaled = scale_color(current_color, 255u - alpha);
|
||||||
uint new_color = old_color_scaled + in_color_scaled;
|
uint new_color = old_color_scaled + in_color_scaled;
|
||||||
m_buffer[buffer_index] = new_color;
|
m_buffer1[buffer_index] = new_color;
|
||||||
bitmap_index++;
|
bitmap_index++;
|
||||||
}
|
}
|
||||||
|
memcpy32(&m_device_buffer[row_buffer_index], &m_buffer1[row_buffer_index], width);
|
||||||
y--;
|
y--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,13 +213,15 @@ struct fb
|
|||||||
size_t bitmap_index;
|
size_t bitmap_index;
|
||||||
for (size_t iy = 0u; iy < height; iy++)
|
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++)
|
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];
|
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++;
|
bitmap_index++;
|
||||||
}
|
}
|
||||||
|
memcpy32(&m_device_buffer[row_buffer_index], &m_buffer1[row_buffer_index], width);
|
||||||
y--;
|
y--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,9 +252,14 @@ struct fb
|
|||||||
*/
|
*/
|
||||||
static void copy_rows_up(size_t y, size_t height, size_t offset)
|
static void copy_rows_up(size_t y, size_t height, size_t offset)
|
||||||
{
|
{
|
||||||
memcpy32(&m_buffer[buffer_index(0u, y + height + offset - 1u)],
|
size_t dest_buffer_index = buffer_index(0u, y + height + offset - 1u);
|
||||||
&m_buffer[buffer_index(0u, y + height - 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));
|
(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();
|
initialize_cpu();
|
||||||
gdt.initialize();
|
gdt.initialize();
|
||||||
idt.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.initialize();
|
||||||
console.clear();
|
console.clear();
|
||||||
klog.initialize();
|
klog.initialize();
|
||||||
|
@ -83,11 +83,16 @@ struct hurl
|
|||||||
header.bootinfo.stack_phys,
|
header.bootinfo.stack_phys,
|
||||||
header.stack_size,
|
header.stack_size,
|
||||||
PT_WRITABLE | PT_NO_EXECUTE);
|
PT_WRITABLE | PT_NO_EXECUTE);
|
||||||
/* Map HULK framebuffer. */
|
/* Map device framebuffer. */
|
||||||
map_range(HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
map_range(HULK_VIRTUAL_FRAMEBUFFER_ADDRESS,
|
||||||
cast(ulong)header.bootinfo.fb.buffer,
|
cast(ulong)header.bootinfo.fb.buffer,
|
||||||
header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u,
|
header.bootinfo.fb.height * header.bootinfo.fb.stride * 4u,
|
||||||
PT_WRITABLE | PT_NO_EXECUTE);
|
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);
|
write_cr3(cast(ulong)m_pt_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +148,14 @@ struct hurl
|
|||||||
* 3) HULK BSS
|
* 3) HULK BSS
|
||||||
* 4) HULK stack
|
* 4) HULK stack
|
||||||
* 5) bootloader page table pages
|
* 5) bootloader page table pages
|
||||||
|
* 6) framebuffer buffer1
|
||||||
*/
|
*/
|
||||||
size_t usable_memory;
|
size_t usable_memory;
|
||||||
size_t physical_address_limit;
|
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 = [
|
ulong[2][2] reserved = [
|
||||||
[header.bootinfo.hulk_phys, LinkerAddresses.hulk_binary_size],
|
[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++)
|
for (size_t ri = 0u; ri < reserved.length; ri++)
|
||||||
{
|
{
|
||||||
@ -205,6 +212,7 @@ struct hurl
|
|||||||
|
|
||||||
usable_memory += LinkerAddresses.hulk_bss_size;
|
usable_memory += LinkerAddresses.hulk_bss_size;
|
||||||
usable_memory += header.stack_size;
|
usable_memory += header.stack_size;
|
||||||
|
usable_memory += fb_size;
|
||||||
klog.writefln("Usable memory: %uKB", usable_memory >> 10u);
|
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);
|
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