feature (kernel): Implemented layer system and string rendering
This commit is contained in:
parent
65b2ba08f4
commit
d025ccaff2
|
@ -17,39 +17,51 @@
|
||||||
#define NOX_RENDERER_H
|
#define NOX_RENDERER_H
|
||||||
|
|
||||||
#include "utils/stdtypes.h"
|
#include "utils/stdtypes.h"
|
||||||
|
#include "utils/string.h"
|
||||||
#include "drivers/graphics/color.h"
|
#include "drivers/graphics/color.h"
|
||||||
#include "drivers/graphics/font.h"
|
#include "drivers/graphics/font.h"
|
||||||
#include "drivers/graphics/framebuffer.h"
|
#include "drivers/graphics/framebuffer.h"
|
||||||
#include "boot/boot_info.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;
|
typedef struct graphics_buffer_T graphics_buffer_T;
|
||||||
struct graphics_buffer_T {
|
struct graphics_buffer_T {
|
||||||
color_argb_T* buffer;
|
color_argb_T* buffer;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t pos_x;
|
uint32_t pos_x;
|
||||||
uint32_t pos_y;
|
uint32_t pos_y;
|
||||||
graphics_buffer_T* prev;
|
bool blocked;
|
||||||
graphics_buffer_T* next;
|
graphics_buffer_layer_E layer;
|
||||||
|
graphics_buffer_T* prev;
|
||||||
|
graphics_buffer_T* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
framebuffer_T framebuffer;
|
framebuffer_T framebuffer;
|
||||||
uint32_t* back_buffer;
|
uint32_t* back_buffer;
|
||||||
uint64_t buffer_size;
|
uint64_t buffer_size;
|
||||||
graphics_buffer_T* graphics_buffers;
|
graphics_buffer_T** graphics_buffer_layers;
|
||||||
font_T font;
|
font_T font;
|
||||||
|
bool initialized;
|
||||||
} graphics_renderer_T;
|
} 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_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);
|
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);
|
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_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_init (boot_info_T* boot_info);
|
||||||
void graphics_renderer_update ();
|
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_width ();
|
||||||
uint32_t graphics_renderer_get_height ();
|
uint32_t graphics_renderer_get_height ();
|
||||||
|
|
||||||
|
|
|
@ -16,25 +16,27 @@
|
||||||
#include "drivers/graphics/renderer.h"
|
#include "drivers/graphics/renderer.h"
|
||||||
#include "utils/memory.h"
|
#include "utils/memory.h"
|
||||||
#include "utils/math.h"
|
#include "utils/math.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/core.h"
|
||||||
|
|
||||||
graphics_renderer_T g_renderer;
|
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_T* graphics_buffer = memory_allocate(sizeof(graphics_buffer_T));
|
||||||
|
|
||||||
graphics_buffer->pos_x = pos_x;
|
graphics_buffer->pos_x = pos_x;
|
||||||
graphics_buffer->pos_y = pos_y;
|
graphics_buffer->pos_y = pos_y;
|
||||||
graphics_buffer->width = width;
|
graphics_buffer->width = width;
|
||||||
graphics_buffer->height = height;
|
graphics_buffer->height = height;
|
||||||
graphics_buffer->buffer = memory_allocate(width * height * sizeof(color_argb_T));
|
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));
|
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->prev = top_buffer;
|
||||||
graphics_buffer->next = NULL;
|
graphics_buffer->next = NULL;
|
||||||
if (top_buffer == NULL) {
|
if (top_buffer == NULL) {
|
||||||
g_renderer.graphics_buffers = graphics_buffer;
|
g_renderer.graphics_buffer_layers[layer] = graphics_buffer;
|
||||||
} else {
|
} else {
|
||||||
top_buffer->next = graphics_buffer;
|
top_buffer->next = graphics_buffer;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +48,7 @@ void graphics_buffer_destruct(graphics_buffer_T* graphics_buffer) {
|
||||||
if (graphics_buffer->prev != NULL) {
|
if (graphics_buffer->prev != NULL) {
|
||||||
graphics_buffer->prev->next = graphics_buffer->next;
|
graphics_buffer->prev->next = graphics_buffer->next;
|
||||||
} else {
|
} else {
|
||||||
g_renderer.graphics_buffers = graphics_buffer->next;
|
g_renderer.graphics_buffer_layers[graphics_buffer->layer] = graphics_buffer->next;
|
||||||
}
|
}
|
||||||
if (graphics_buffer->next != NULL) {
|
if (graphics_buffer->next != NULL) {
|
||||||
graphics_buffer->next->prev = graphics_buffer->prev;
|
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];
|
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) {
|
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];
|
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++){
|
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) {
|
void graphics_renderer_init(boot_info_T* boot_info_T) {
|
||||||
struct limine_framebuffer* framebuffer = boot_info_T->framebuffer->framebuffers[0];
|
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.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.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;
|
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);
|
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() {
|
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) {
|
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;
|
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);
|
memory_copy(g_renderer.back_buffer, g_renderer.framebuffer.address, g_renderer.buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics_buffer_T* graphics_renderer_get_top_buffer() {
|
graphics_buffer_T* graphics_renderer_get_top_buffer(graphics_buffer_layer_E layer) {
|
||||||
if (g_renderer.graphics_buffers == NULL) {
|
if (g_renderer.graphics_buffer_layers[layer] == NULL) {
|
||||||
return 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) {
|
while (graphics_buffer->next != NULL) {
|
||||||
graphics_buffer = graphics_buffer->next;
|
graphics_buffer = graphics_buffer->next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,19 +74,16 @@ void kmain(boot_info_T boot_info) {
|
||||||
limine_terminal_print(&boot_info, "Kernel initialized\n");
|
limine_terminal_print(&boot_info, "Kernel initialized\n");
|
||||||
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
|
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
|
||||||
|
|
||||||
graphics_buffer_T* buffer = 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);
|
// graphics_buffer_T* buffer2 = graphics_buffer_request(0, 0, 50, 50);
|
||||||
|
|
||||||
for (int x = 0; x < 50; x++) {
|
// for (int x = 0; x < 50; x++) {
|
||||||
for (int y = 0; y < 50; y++) {
|
// for (int y = 0; y < 50; y++) {
|
||||||
graphics_buffer_set_pixel(buffer2, x, y, (color_argb_T){0x80, 0xca, 0xca, 0xca});
|
// 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');
|
|
||||||
|
|
||||||
|
graphics_buffer_draw_string(buffer, 0, 0, (color_argb_T){0xFF, 0xFF, 0, 0}, "test string\n");
|
||||||
graphics_renderer_update();
|
graphics_renderer_update();
|
||||||
|
|
||||||
CORE_HALT_FOREVER
|
CORE_HALT_FOREVER
|
||||||
|
|
Loading…
Reference in New Issue