diff --git a/kernel/inc/drivers/graphics/renderer.h b/kernel/inc/drivers/graphics/renderer.h index a76a5e9..0a5ebb0 100644 --- a/kernel/inc/drivers/graphics/renderer.h +++ b/kernel/inc/drivers/graphics/renderer.h @@ -17,39 +17,51 @@ #define NOX_RENDERER_H #include "utils/stdtypes.h" +#include "utils/string.h" #include "drivers/graphics/color.h" #include "drivers/graphics/font.h" #include "drivers/graphics/framebuffer.h" #include "boot/boot_info.h" +typedef enum { + GRAPHICS_BUFFER_STANDARD, + GRAPHICS_BUFFER_OVERLAY, + + GRAPHICS_BUFFER_ENUM_MAX +} graphics_buffer_layer_E; + typedef struct graphics_buffer_T graphics_buffer_T; struct graphics_buffer_T { - color_argb_T* buffer; - uint32_t width; - uint32_t height; - uint32_t pos_x; - uint32_t pos_y; - graphics_buffer_T* prev; - graphics_buffer_T* next; + color_argb_T* buffer; + uint32_t width; + uint32_t height; + uint32_t pos_x; + uint32_t pos_y; + bool blocked; + graphics_buffer_layer_E layer; + graphics_buffer_T* prev; + graphics_buffer_T* next; }; typedef struct { framebuffer_T framebuffer; uint32_t* back_buffer; uint64_t buffer_size; - graphics_buffer_T* graphics_buffers; + graphics_buffer_T** graphics_buffer_layers; font_T font; + bool initialized; } graphics_renderer_T; -graphics_buffer_T* graphics_buffer_request (uint32_t pos_x, uint32_t pos_y, uint32_t width, uint32_t height); +graphics_buffer_T* graphics_buffer_request (uint32_t pos_x, uint32_t pos_y, uint32_t width, uint32_t height, graphics_buffer_layer_E layer); void graphics_buffer_destruct (graphics_buffer_T* graphics_buffer); void graphics_buffer_set_pixel (graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y, color_argb_T color); color_argb_T graphics_buffer_get_pixel (graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y); void graphics_buffer_draw_char (graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y, color_argb_T color, char chr); +void graphics_buffer_draw_string (graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y, color_argb_T color, string_t string); void graphics_renderer_init (boot_info_T* boot_info); void graphics_renderer_update (); -graphics_buffer_T* graphics_renderer_get_top_buffer (); +graphics_buffer_T* graphics_renderer_get_top_buffer (graphics_buffer_layer_E layer); uint32_t graphics_renderer_get_width (); uint32_t graphics_renderer_get_height (); diff --git a/kernel/src/drivers/graphics/renderer.c b/kernel/src/drivers/graphics/renderer.c index a057bcc..665c98f 100644 --- a/kernel/src/drivers/graphics/renderer.c +++ b/kernel/src/drivers/graphics/renderer.c @@ -16,25 +16,27 @@ #include "drivers/graphics/renderer.h" #include "utils/memory.h" #include "utils/math.h" -#include "utils/logger.h" +#include "utils/core.h" graphics_renderer_T g_renderer; -graphics_buffer_T* graphics_buffer_request(uint32_t pos_x, uint32_t pos_y, uint32_t width, uint32_t height) { +graphics_buffer_T* graphics_buffer_request(uint32_t pos_x, uint32_t pos_y, uint32_t width, uint32_t height, graphics_buffer_layer_E layer) { graphics_buffer_T* graphics_buffer = memory_allocate(sizeof(graphics_buffer_T)); - graphics_buffer->pos_x = pos_x; - graphics_buffer->pos_y = pos_y; - graphics_buffer->width = width; - graphics_buffer->height = height; - graphics_buffer->buffer = memory_allocate(width * height * sizeof(color_argb_T)); + graphics_buffer->pos_x = pos_x; + graphics_buffer->pos_y = pos_y; + graphics_buffer->width = width; + graphics_buffer->height = height; + graphics_buffer->blocked = false; + graphics_buffer->layer = layer; + graphics_buffer->buffer = memory_allocate(width * height * sizeof(color_argb_T)); memory_set(graphics_buffer->buffer, 0, width * height * sizeof(color_argb_T)); - graphics_buffer_T* top_buffer = graphics_renderer_get_top_buffer(); + graphics_buffer_T* top_buffer = graphics_renderer_get_top_buffer(layer); graphics_buffer->prev = top_buffer; graphics_buffer->next = NULL; if (top_buffer == NULL) { - g_renderer.graphics_buffers = graphics_buffer; + g_renderer.graphics_buffer_layers[layer] = graphics_buffer; } else { top_buffer->next = graphics_buffer; } @@ -46,7 +48,7 @@ void graphics_buffer_destruct(graphics_buffer_T* graphics_buffer) { if (graphics_buffer->prev != NULL) { graphics_buffer->prev->next = graphics_buffer->next; } else { - g_renderer.graphics_buffers = graphics_buffer->next; + g_renderer.graphics_buffer_layers[graphics_buffer->layer] = graphics_buffer->next; } if (graphics_buffer->next != NULL) { graphics_buffer->next->prev = graphics_buffer->prev; @@ -64,8 +66,8 @@ color_argb_T graphics_buffer_get_pixel(graphics_buffer_T* graphics_buffer, uint3 return graphics_buffer->buffer[y * graphics_buffer->width + x]; } +// this function is not thread safe, consider using `graphics_buffer_draw_string` instead void graphics_buffer_draw_char(graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y, color_argb_T color, char chr) { - uint8_t* glyph = &g_renderer.font.buffer[g_renderer.font.glyph_size * chr]; for (int y_pos = 0; y_pos < g_renderer.font.height; y_pos++){ @@ -80,6 +82,38 @@ void graphics_buffer_draw_char(graphics_buffer_T* graphics_buffer, uint32_t x, u } } +void graphics_buffer_draw_string(graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y, color_argb_T color, string_t string) { + CORE_HALT_WHILE(graphics_buffer->blocked) + graphics_buffer->blocked = true; + + uint64_t strlen = string_length(string); + for (int i = 0; i < strlen; i++) { + switch (string[i]) { + case '\n': { + x = 0; + y += g_renderer.font.height; + break; + } + case '\r': { + x = 0; + break; + } + + default: { + if (x + g_renderer.font.width >= graphics_buffer->width) { + x = 0; + y += g_renderer.font.height; + } + graphics_buffer_draw_char(graphics_buffer, x, y, color, string[i]); + x += g_renderer.font.width; + break; + } + } + } + + graphics_buffer->blocked = false; +} + void graphics_renderer_init(boot_info_T* boot_info_T) { struct limine_framebuffer* framebuffer = boot_info_T->framebuffer->framebuffers[0]; @@ -95,39 +129,55 @@ void graphics_renderer_init(boot_info_T* boot_info_T) { g_renderer.buffer_size = g_renderer.framebuffer.width * g_renderer.framebuffer.height * g_renderer.framebuffer.bytes_per_pixel; g_renderer.back_buffer = memory_allocate(g_renderer.buffer_size); - g_renderer.graphics_buffers = NULL; + g_renderer.graphics_buffer_layers = memory_allocate(GRAPHICS_BUFFER_ENUM_MAX * sizeof(graphics_buffer_T*)); g_renderer.font = g_font; + memory_set(g_renderer.graphics_buffer_layers, 0, GRAPHICS_BUFFER_ENUM_MAX * sizeof(graphics_buffer_T*)); memory_set(g_renderer.back_buffer, 0, g_renderer.buffer_size); + + g_renderer.initialized = true; +} + +bool graphics_renderer_is_initialized() { + return g_renderer.initialized; +} + +void graphics_renderer_update_graphics_buffer(graphics_buffer_T* graphics_buffer) { + uint32_t size_x = MIN(graphics_buffer->pos_x + graphics_buffer->width, g_renderer.framebuffer.width); + uint32_t size_y = MIN(graphics_buffer->pos_y + graphics_buffer->height, g_renderer.framebuffer.height); + + for (uint32_t y = graphics_buffer->pos_y; y < size_y; y++) { + for (uint32_t x = graphics_buffer->pos_x; x < size_x; x++) { + color_argb_T color = graphics_buffer->buffer[(y - graphics_buffer->pos_y) * graphics_buffer->width + (x - graphics_buffer->pos_x)]; + + color_argb_T original; + original.alpha = 0xFF; + original.red = (g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] >> g_renderer.framebuffer.shift_red) & 0xFF; + original.green = (g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] >> g_renderer.framebuffer.shift_green) & 0xFF; + original.blue = (g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] >> g_renderer.framebuffer.shift_blue) & 0xFF; + + // apply transparency + color = color_argb_blend_alpha(original, color); + + // write into back_buffer + g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] = (color.red << g_renderer.framebuffer.shift_red) | + (color.green << g_renderer.framebuffer.shift_green) | + (color.blue << g_renderer.framebuffer.shift_blue); + } + } } void graphics_renderer_update() { - graphics_buffer_T* graphics_buffer = g_renderer.graphics_buffers; + graphics_buffer_T* graphics_buffer = g_renderer.graphics_buffer_layers[GRAPHICS_BUFFER_STANDARD]; while (graphics_buffer != NULL) { + graphics_renderer_update_graphics_buffer(graphics_buffer); + graphics_buffer = graphics_buffer->next; + } - uint32_t size_x = MIN(graphics_buffer->pos_x + graphics_buffer->width, g_renderer.framebuffer.width); - uint32_t size_y = MIN(graphics_buffer->pos_y + graphics_buffer->height, g_renderer.framebuffer.height); - - for (uint32_t y = graphics_buffer->pos_y; y < size_y; y++) { - for (uint32_t x = graphics_buffer->pos_x; x < size_x; x++) { - color_argb_T color = graphics_buffer->buffer[(y - graphics_buffer->pos_y) * graphics_buffer->width + (x - graphics_buffer->pos_x)]; - - color_argb_T original; - original.alpha = 0xFF; - original.red = (g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] >> g_renderer.framebuffer.shift_red) & 0xFF; - original.green = (g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] >> g_renderer.framebuffer.shift_green) & 0xFF; - original.blue = (g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] >> g_renderer.framebuffer.shift_blue) & 0xFF; - - // apply transparency - color = color_argb_blend_alpha(original, color); - - // write into back_buffer - g_renderer.back_buffer[y * g_renderer.framebuffer.width + x] = (color.red << g_renderer.framebuffer.shift_red) | - (color.green << g_renderer.framebuffer.shift_green) | - (color.blue << g_renderer.framebuffer.shift_blue); - } - } + graphics_buffer = g_renderer.graphics_buffer_layers[GRAPHICS_BUFFER_OVERLAY]; + while (graphics_buffer != NULL) { + graphics_renderer_update_graphics_buffer(graphics_buffer); graphics_buffer = graphics_buffer->next; } @@ -135,12 +185,13 @@ void graphics_renderer_update() { memory_copy(g_renderer.back_buffer, g_renderer.framebuffer.address, g_renderer.buffer_size); } -graphics_buffer_T* graphics_renderer_get_top_buffer() { - if (g_renderer.graphics_buffers == NULL) { +graphics_buffer_T* graphics_renderer_get_top_buffer(graphics_buffer_layer_E layer) { + if (g_renderer.graphics_buffer_layers[layer] == NULL) { return NULL; } - graphics_buffer_T* graphics_buffer = g_renderer.graphics_buffers; + graphics_buffer_T* graphics_buffer = g_renderer.graphics_buffer_layers[layer]; + while (graphics_buffer->next != NULL) { graphics_buffer = graphics_buffer->next; } diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 9c75811..727a159 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -74,19 +74,16 @@ void kmain(boot_info_T boot_info) { limine_terminal_print(&boot_info, "Kernel initialized\n"); log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n"); - graphics_buffer_T* buffer = graphics_buffer_request(0, 0, 50, 50); - graphics_buffer_T* buffer2 = graphics_buffer_request(0, 0, 50, 50); + graphics_buffer_T* buffer = graphics_buffer_request(0, 0, graphics_renderer_get_width() / 2, graphics_renderer_get_height(), GRAPHICS_BUFFER_OVERLAY); +// graphics_buffer_T* buffer2 = graphics_buffer_request(0, 0, 50, 50); - for (int x = 0; x < 50; x++) { - for (int y = 0; y < 50; y++) { - graphics_buffer_set_pixel(buffer2, x, y, (color_argb_T){0x80, 0xca, 0xca, 0xca}); - } - } - - graphics_buffer_draw_char(buffer, 0, 0, (color_argb_T){0xFF, 0xFF, 0, 0}, 'R'); - graphics_buffer_draw_char(buffer, 8, 0, (color_argb_T){0xFF, 0, 0xFF, 0}, 'G'); - graphics_buffer_draw_char(buffer, 16, 0, (color_argb_T){0xFF, 0, 0, 0xFF}, 'B'); +// for (int x = 0; x < 50; x++) { +// for (int y = 0; y < 50; y++) { +// graphics_buffer_set_pixel(buffer2, x, y, (color_argb_T){0x80, 0xca, 0xca, 0xca}); +// } +// } + graphics_buffer_draw_string(buffer, 0, 0, (color_argb_T){0xFF, 0xFF, 0, 0}, "test string\n"); graphics_renderer_update(); CORE_HALT_FOREVER