feature (kernel): Implemented layer system and string rendering

This commit is contained in:
antifallobst 2023-02-21 15:58:04 +01:00
parent 65b2ba08f4
commit d025ccaff2
3 changed files with 119 additions and 59 deletions

View File

@ -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 ();

View File

@ -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;
}

View File

@ -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