feature (kernel): Implemented graphics_buffers (canvases) and alpha blending

This commit is contained in:
antifallobst 2023-02-21 10:19:29 +01:00
parent f5792bd43b
commit 885a7b1f31
5 changed files with 168 additions and 40 deletions

View File

@ -25,4 +25,6 @@ typedef struct {
uint8_t blue;
} color_argb_T;
color_argb_T color_argb_blend_alpha(color_argb_T background, color_argb_T foreground);
#endif //NOX_COLOR_H

View File

@ -22,17 +22,35 @@
#include "drivers/graphics/framebuffer.h"
#include "boot/boot_info.h"
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;
};
typedef struct {
framebuffer_T framebuffer;
uint32_t* back_buffer;
uint64_t buffer_size;
font_T font;
framebuffer_T framebuffer;
uint32_t* back_buffer;
uint64_t buffer_size;
graphics_buffer_T* graphics_buffers;
font_T font;
} graphics_renderer_T;
void graphics_renderer_set_pixel (uint32_t x, uint32_t y, color_argb_T color);
color_argb_T graphics_renderer_get_pixel (uint32_t x, uint32_t y);
void graphics_renderer_draw_char (uint32_t x, uint32_t y, color_argb_T color, char chr);
void graphics_renderer_update ();
void graphics_renderer_init (boot_info_T* boot_info);
graphics_buffer_T* graphics_buffer_request (uint32_t pos_x, uint32_t pos_y, uint32_t width, uint32_t height);
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_renderer_init (boot_info_T* boot_info);
void graphics_renderer_update ();
graphics_buffer_T* graphics_renderer_get_top_buffer ();
uint32_t graphics_renderer_get_width ();
uint32_t graphics_renderer_get_height ();
#endif //NOX_RENDERER_H

View File

@ -0,0 +1,25 @@
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
*
* NoxOS is free software:
* you can redistribute it and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*/
#include "drivers/graphics/color.h"
color_argb_T color_argb_blend_alpha(color_argb_T background, color_argb_T foreground) {
color_argb_T color = foreground;
color.red += ((foreground.red * foreground.alpha) + (background.red * (0xFF - foreground.alpha))) / 0xFF;
color.green += ((foreground.green * foreground.alpha) + (background.green * (0xFF - foreground.alpha))) / 0xFF;
color.blue += ((foreground.blue * foreground.alpha) + (background.blue * (0xFF - foreground.alpha))) / 0xFF;
return color;
}

View File

@ -20,46 +20,66 @@
graphics_renderer_T g_renderer;
void graphics_renderer_set_pixel(uint32_t x, uint32_t y, color_argb_T color) {
uint64_t position = y * g_renderer.framebuffer.width + x;
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 = memory_allocate(sizeof(graphics_buffer_T));
g_renderer.back_buffer[position] = (color.red << g_renderer.framebuffer.shift_red) |
(color.green << g_renderer.framebuffer.shift_green) |
(color.blue << g_renderer.framebuffer.shift_blue);
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));
memory_set(graphics_buffer->buffer, 0, width * height * sizeof(color_argb_T));
graphics_buffer_T* top_buffer = graphics_renderer_get_top_buffer();
graphics_buffer->prev = top_buffer;
graphics_buffer->next = NULL;
if (top_buffer == NULL) {
g_renderer.graphics_buffers = graphics_buffer;
} else {
top_buffer->next = graphics_buffer;
}
return graphics_buffer;
}
color_argb_T graphics_renderer_get_pixel(uint32_t x, uint32_t y) {
uint64_t position = y * g_renderer.framebuffer.width + x;
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;
}
if (graphics_buffer->next != NULL) {
graphics_buffer->next->prev = graphics_buffer->prev;
}
color_argb_T color;
color.alpha = 0xFF;
color.red = g_renderer.back_buffer[position] & (0xFF << g_renderer.framebuffer.shift_red);
color.green = g_renderer.back_buffer[position] & (0xFF << g_renderer.framebuffer.shift_green);
color.blue = g_renderer.back_buffer[position] & (0xFF << g_renderer.framebuffer.shift_blue);
return color;
memory_free(graphics_buffer->buffer);
memory_free(graphics_buffer);
}
void graphics_renderer_draw_char(uint32_t x, uint32_t y, color_argb_T color, char chr) {
void graphics_buffer_set_pixel(graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y, color_argb_T color) {
graphics_buffer->buffer[y * graphics_buffer->width + x] = color;
}
color_argb_T graphics_buffer_get_pixel(graphics_buffer_T* graphics_buffer, uint32_t x, uint32_t y) {
return graphics_buffer->buffer[y * graphics_buffer->width + x];
}
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++){
for (int x_pos = 0; x_pos < g_renderer.font.width; x_pos++){
if (*glyph & (1 << x_pos)) {
graphics_renderer_set_pixel(x + x_pos, y + y_pos, color);
graphics_buffer_set_pixel(graphics_buffer, x + x_pos, y + y_pos, color);
} else {
graphics_renderer_set_pixel(x + x_pos, y + y_pos, (color_argb_T){0x00, 0x00, 0x00, 0x00});
graphics_buffer_set_pixel(graphics_buffer, x + x_pos, y + y_pos, (color_argb_T){0x00, 0x00, 0x00, 0x00});
}
}
glyph++;
}
}
void graphics_renderer_update() {
memory_copy(g_renderer.back_buffer, g_renderer.framebuffer.address, g_renderer.buffer_size);
}
void graphics_renderer_init(boot_info_T* boot_info_T) {
struct limine_framebuffer* framebuffer = boot_info_T->framebuffer->framebuffers[0];
@ -73,9 +93,65 @@ void graphics_renderer_init(boot_info_T* boot_info_T) {
g_renderer.framebuffer.shift_green = framebuffer->green_mask_shift;
g_renderer.framebuffer.shift_blue = framebuffer->blue_mask_shift;
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);
memory_set(g_renderer.back_buffer, 0, g_renderer.buffer_size);
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.font = g_font;
g_renderer.font = g_font;
memory_set(g_renderer.back_buffer, 0, g_renderer.buffer_size);
}
void graphics_renderer_update() {
graphics_buffer_T* graphics_buffer = g_renderer.graphics_buffers;
while (graphics_buffer != NULL) {
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 = graphics_buffer->next;
}
// swap back_buffer into framebuffer
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) {
return NULL;
}
graphics_buffer_T* graphics_buffer = g_renderer.graphics_buffers;
while (graphics_buffer->next != NULL) {
graphics_buffer = graphics_buffer->next;
}
return graphics_buffer;
}
uint32_t graphics_renderer_get_width() {
return g_renderer.framebuffer.width;
}
uint32_t graphics_renderer_get_height() {
return g_renderer.framebuffer.height;
}

View File

@ -56,13 +56,20 @@ void kmain(boot_info_T boot_info) {
limine_terminal_print(&boot_info, "Kernel initialized\n");
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
graphics_renderer_draw_char(0, 0, (color_argb_T){0xFF, 0xFF, 0, 0}, 'R');
graphics_renderer_draw_char(8, 0, (color_argb_T){0xFF, 0, 0xFF, 0}, 'G');
graphics_renderer_draw_char(16, 0, (color_argb_T){0xFF, 0, 0, 0xFF}, 'B');
graphics_renderer_update();
graphics_buffer_T* buffer = graphics_buffer_request(0, 0, 50, 50);
graphics_buffer_T* buffer2 = graphics_buffer_request(0, 0, 50, 50);
color_argb_T color = graphics_renderer_get_pixel(0, 5);
log(LOG_DEBUG, "ALPHA[0x%xb] RED[0x%xb] GREEN[0x%xb] BLUE[0x%xb]", color.alpha, color.red, color.green, color.blue);
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');
graphics_renderer_update();
CORE_HALT_FOREVER
}