feature (kernel): Implemented graphics_buffers (canvases) and alpha blending
This commit is contained in:
parent
f5792bd43b
commit
885a7b1f31
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
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 ();
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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];
|
||||
|
||||
|
@ -75,7 +95,63 @@ 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);
|
||||
memory_set(g_renderer.back_buffer, 0, g_renderer.buffer_size);
|
||||
|
||||
g_renderer.graphics_buffers = NULL;
|
||||
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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue