Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
graphic.c
Go to the documentation of this file.
1#include "graphic.h"
2#include "framebuffer.h"
3#include "hal/cpu/paging.h"
4#include "init/init.h"
5#include "libk/debug/debug.h"
6#include "memory/entry.h"
8#include "memory/vm_manager.h"
9#include "str.h"
10#include "type.h"
11#include "vfs/enum.h"
12#include <libk/serial.h>
13
14#pragma GCC diagnostic push
15#pragma GCC diagnostic ignored "-Wunknown-warning-option"
16
17#define _STRING_H_
18
19#define SSFN_memcmp memcmp
20
21#define SSFN_memset ssfn_memset
22static void* ssfn_memset(void* __s, int __c, size_t __n) {
23 unsigned char* p = (unsigned char*)__s;
24 while (__n--)
25 *p++ = (unsigned char)__c;
26 return __s;
27}
28
29#define SSFN_memcpy ssfn_memcpy
30static void* ssfn_memcpy(void* __restrict__ __dest,
31 const void* __restrict__ __src, size_t __n) {
32 unsigned char* d = (unsigned char*)__dest;
33 const unsigned char* s = (const unsigned char*)__src;
34 while (__n--)
35 *d++ = *s++;
36 return __dest;
37}
38
39#include <memory/kalloc.h>
40
41static void* ssfn_realloc(void* ptr, size_t new_size) {
42 if (new_size == 0) {
43 if (ptr)
44 kfree2(ptr);
45 return NULL;
46 }
47
48 if (!ptr)
49 return kalloc(new_size);
50
51 kalloc_metadata_t* meta =
54
55 size_t old_size = meta->size;
56 void* new_ptr = kalloc(new_size);
57 if (!new_ptr)
58 return NULL;
59
60 size_t copy = old_size < new_size ? old_size : new_size;
61 ssfn_memcpy(new_ptr, ptr, copy);
62 kfree2(ptr);
63
64 return new_ptr;
65}
66
67static void ssfn_free_(void* ptr) {
68 if (ptr)
69 kfree2(ptr);
70}
71
72#define SSFN_realloc ssfn_realloc
73#define SSFN_free ssfn_free_
74
75#define SSFN_IMPLEMENTATION
76#include <libk/ssfn.h>
77
78#undef _STRING_H_
79#pragma GCC diagnostic pop
80
83static ssfn_t ssfn_ctx = {0};
84
85static boolean_t ssfn_ready = false;
86
87INIT(graphic) {
88 g__fb = &ctx->framebuffer;
89 LOG2_DEBUG("FB", "Fb addr %lx", g__fb->framebuffer_addr);
90
91 if (g__fb->framebuffer_addr == 0)
92 return;
93
94 dentry_ptr font_dentry;
95 uint8_t* font_buff = 0;
96 if (resolve_dentry("/init/fonts/unifont.sfn", 0, &font_dentry, 0) ==
97 VFS_OK) {
98 LOG2_DEBUG("Graphic", "opened %s (%d kb)",
99 font_dentry->name->c_str,
100 font_dentry->vnode->size / 1024);
101 font_buff = (uint8_t*)kalloc(font_dentry->vnode->size);
102 ((vops_file_t*)font_dentry->vnode->ops)
103 ->read(font_dentry->vnode, font_buff,
104 font_dentry->vnode->size, 0);
105 } else {
106 LOG2_WARN("Graphic", "failed to load font");
107 }
108
109 for (uint64_t i = 0; i < ctx->memory.memory_entries; i++) {
110 memory_entry_t* entry = &ctx->memory.memory_map[i];
111 if (entry->type == ENTRY_MMAP_FRAMEBUFFER) {
113 0xFFFFFA0000000000, entry->base,
114 entry->length / PAGE_SIZE, 0b111);
115 vma_register(get_kernel_vmm_page(), entry->base, 0xFFFFFA0000000000,
116 entry->length / PAGE_SIZE);
117 g__fb->framebuffer_addr = 0xFFFFFA0000000000;
118 break;
119 }
120 }
121
122 serial2_printf("new framebuffer 0x%lx\n", g__fb->framebuffer_addr);
123
124 dst.ptr = (uint8_t*)g__fb->framebuffer_addr;
125 dst.w = g__fb->framebuffer_width;
126 dst.h = g__fb->framebuffer_height;
127 dst.p = (uint16_t)g__fb->framebuffer_pitch;
128 dst.x = 0;
129 dst.y = 0;
130 dst.fg = 0xFFFFFFFF;
131 dst.bg = 0xFF000000;
132
133 serial2_printf("dst: ptr=%lx w=%d h=%d p=%d\n", dst.ptr, dst.w, dst.h,
134 dst.p);
135
136 if (font_buff) {
137 int r = ssfn_load(&ssfn_ctx, font_buff);
138 if (r != SSFN_OK) {
139 LOG2_WARN("Graphic", "ssfn_load failed: %d", r);
140 return;
141 }
142
145 ssfn_ready = true;
146 }
147
148 KDEBUG(DEBUG_LEVEL_INFO, "graphic init done\n");
149}
150
151void putc(char c, int col, int row, uint32_t fg, uint32_t bg) {
152 if (!ssfn_ready || !dst.ptr)
153 return;
154
155 dst.fg = fg | 0xFF000000;
156 dst.bg = bg | 0xFF000000;
157 dst.x = col * (FONT_SIZE / 2);
158 dst.y = FONT_SIZE + row * FONT_SIZE;
159
160 char str[2] = {c, '\0'};
161 int r = ssfn_render(&ssfn_ctx, &dst, str);
162 if (r < 0)
163 serial2_printf("ssfn_render err: %d\n", r);
164}
165
166void putc_utf8(const char *s, int col, int row, uint32_t fg, uint32_t bg) {
167 if (!ssfn_ready || !dst.ptr)
168 return;
169
170 dst.fg = fg | 0xFF000000;
171 dst.bg = bg | 0xFF000000;
172 dst.x = col * (FONT_SIZE / 2);
173 dst.y = FONT_SIZE + row * FONT_SIZE;
174
175 int r = ssfn_render(&ssfn_ctx, &dst, s);
176 if (r < 0)
177 serial2_printf("ssfn_render err: %d\n", r);
178}
179
181 if ((c & 0x80) == 0)
182 return 1;
183 if ((c & 0xE0) == 0xC0)
184 return 2;
185 if ((c & 0xF0) == 0xE0)
186 return 3;
187 if ((c & 0xF8) == 0xF0)
188 return 4;
189 return 1;
190}
191
192void put_pixel(int x, int y, uint32_t color) {
193 pixel_t* pixel = (pixel_t*)((uint8_t*)g__fb->framebuffer_addr +
194 y * g__fb->framebuffer_pitch + x * 4);
195 pixel->r = color & 0xFF;
196 pixel->g = (color >> 8) & 0xFF;
197 pixel->b = (color >> 16) & 0xFF;
198 pixel->a = (color >> 24) & 0xFF;
199}
200
201static inline uint8_t blend(uint8_t src, uint8_t d, uint8_t a) {
202 // Gunakan multiply+shift yang lebih akurat
203 return ((src * a) + (d * (255 - a)) + 128) >> 8;
204 // +128 untuk rounding yang lebih baik
205}
206
207void put_pixel_alpha(int x, int y, pixel_t src) {
208 // Bounds check
209 if (x < 0 || y < 0 || x >= g__fb->framebuffer_width ||
210 y >= g__fb->framebuffer_height)
211 return;
212
213 // Early exit untuk fully transparent
214 if (src.a == 0)
215 return;
216
217 uint32_t* dst_ptr = (uint32_t*)PTR_ADD(
218 g__fb->framebuffer_addr, y * g__fb->framebuffer_pitch + x * 4);
219
220 // Fast path untuk fully opaque
221 if (src.a == 255) {
222 uint32_t r_val =
223 (src.r * ((1 << g__fb->red_mask_size) - 1)) / 255;
224 uint32_t g_val =
225 (src.g * ((1 << g__fb->green_mask_size) - 1)) / 255;
226 uint32_t b_val =
227 (src.b * ((1 << g__fb->blue_mask_size) - 1)) / 255;
228
229 *dst_ptr = (r_val << g__fb->red_mask_shift) |
230 (g_val << g__fb->green_mask_shift) |
231 (b_val << g__fb->blue_mask_shift);
232 return;
233 }
234
235 // Alpha blending path
236 uint32_t dst_color = *dst_ptr;
237
238 // Extract langsung tanpa struct intermediate
239 uint8_t dst_b = dst_color & 0xFF;
240 uint8_t dst_g = (dst_color >> 8) & 0xFF;
241 uint8_t dst_r = (dst_color >> 16) & 0xFF;
242
243 // Blend
244 uint8_t r = blend(src.r, dst_r, src.a);
245 uint8_t g = blend(src.g, dst_g, src.a);
246 uint8_t b = blend(src.b, dst_b, src.a);
247
248 // Color packing - gunakan shift instead of division jika mask size
249 // standard (8-bit)
250 uint32_t r_val = (r * ((1 << g__fb->red_mask_size) - 1)) / 255;
251 uint32_t g_val = (g * ((1 << g__fb->green_mask_size) - 1)) / 255;
252 uint32_t b_val = (b * ((1 << g__fb->blue_mask_size) - 1)) / 255;
253
254 *dst_ptr = (r_val << g__fb->red_mask_shift) |
255 (g_val << g__fb->green_mask_shift) |
256 (b_val << g__fb->blue_mask_shift);
257}
258
259void put_pixel_alpha_fast(int x, int y, pixel_t src) {
260 if (x < 0 || y < 0 || x >= g__fb->framebuffer_width ||
261 y >= g__fb->framebuffer_height)
262 return;
263
264 if (src.a == 0)
265 return;
266
267 uint32_t* dst_ptr =
268 (uint32_t*)(void*)(((uint8_t*)g__fb->framebuffer_addr +
269 y * g__fb->framebuffer_pitch + x * 4));
270
271 if (src.a == 255) {
272 *dst_ptr = (uint32_t)((src.r << 16) | (src.g << 8) | src.b);
273 return;
274 }
275
276 uint32_t dst_color = *dst_ptr;
277 uint32_t inv_a = 255 - src.a;
278
279 // Blend semua channel sekaligus dengan SIMD-like operations
280 uint32_t rb =
281 (((src.r * src.a) + ((dst_color >> 16) & 0xFF) * inv_a) & 0xFF00)
282 << 8 |
283 (((src.b * src.a) + (dst_color & 0xFF) * inv_a) >> 8);
284 uint32_t g =
285 ((src.g * src.a) + (((dst_color >> 8) & 0xFF) * inv_a)) & 0xFF00;
286
287 *dst_ptr = rb | g;
288}
289
291 memset((void *)g__fb->framebuffer_addr, color,
292 g__fb->framebuffer_pitch * g__fb->framebuffer_height);
293}
294
295__attribute__((unused)) static void scroll_up(int lines, uint32_t bg_color) {
296 int line_height = 15; // Asumsi tinggi karakter 15px
297 int scroll_amount = lines * line_height;
298
299 // Geser framebuffer ke atas
300 memcopy((void*)g__fb->framebuffer_addr,
301 (void*)(g__fb->framebuffer_addr +
302 (uint64_t)scroll_amount * g__fb->framebuffer_pitch),
303 (size_t)((g__fb->framebuffer_height - lines) *
304 g__fb->framebuffer_pitch));
305
306 // Bersihkan area kosong di bawah
307 for (int y = g__fb->framebuffer_height - scroll_amount;
308 y < g__fb->framebuffer_height; y++) {
309 for (int x = 0; x < g__fb->framebuffer_width; x++) {
310 put_pixel(x, y, bg_color);
311 }
312 }
313}
314
315uint32_t vxGetWidth(void) { return dst.w; }
316uint32_t vxGetHeight(void) { return dst.h; }
317
318void vxScroll(int px) {
319 uint32_t row_bytes = dst.p;
320 uint32_t total = row_bytes * (dst.h - px);
321 ssfn_memcpy(dst.ptr, dst.ptr + row_bytes * px, total);
322
323 ssfn_memset(dst.ptr + total, 0, row_bytes * px);
324}
325
326
328 uint32_t w = vxGetWidth();
329 if (w == 0)
330 return 80;
331 return (w / (FONT_SIZE / 2));
332}
335 if (h == 0)
336 return 25;
337 return (h / FONT_SIZE);
338}
339
340void fill_rect(int x, int y, int w, int h, uint32_t color) {
341 if (!dst.ptr) return;
342
343 for (int row = y; row < y + h; row++) {
344 uint32_t *line = (uint32_t*)((uint8_t*)g__fb->framebuffer_addr
345 + row * g__fb->framebuffer_pitch);
346 for (int col = x; col < x + w; col++) {
347 line[col] = color;
348 }
349 }
350}
struct SDT h
Definition acpi.h:0
@ DEBUG_LEVEL_INFO
Definition debug.h:8
#define KDEBUG(...)
Definition debug.h:16
struct dentry * dentry_ptr
Definition dentry.h:20
int resolve_dentry(char *path, dentry_ptr parent, dentry_ptr *out, uint8_t flag)
Resolves a path to a directory entry (dentry) with configurable start point and strictness.
a
Definition entry.h:6
@ ENTRY_MMAP_FRAMEBUFFER
Definition entry.h:14
@ VFS_OK
Definition enum.h:5
framebuffer_t
Definition framebuffer.h:19
static __inline__ uint8_t blend(uint8_t src, uint8_t d, uint8_t a)
Definition graphic.c:201
void put_pixel_alpha(int x, int y, pixel_t src)
Definition graphic.c:207
static ssfn_buf_t dst
Definition graphic.c:82
uint32_t screen_cols(void)
Definition graphic.c:327
void fill_rect(int x, int y, int w, int h, uint32_t color)
Definition graphic.c:340
int utf8_char_len(uint8_t c)
Definition graphic.c:180
uint32_t screen_rows(void)
Definition graphic.c:333
static void * ssfn_memset(void *__s, int __c, size_t __n)
Definition graphic.c:22
static boolean_t ssfn_ready
Definition graphic.c:85
void put_pixel(int x, int y, uint32_t color)
Definition graphic.c:192
void vxScroll(int px)
Definition graphic.c:318
volatile framebuffer_t * g__fb
Definition graphic.c:81
uint32_t vxGetWidth(void)
Definition graphic.c:315
static void ssfn_free_(void *ptr)
Definition graphic.c:67
static void * ssfn_realloc(void *ptr, size_t new_size)
Definition graphic.c:41
static ssfn_t ssfn_ctx
Definition graphic.c:83
static void * ssfn_memcpy(void *__restrict__ __dest, const void *__restrict__ __src, size_t __n)
Definition graphic.c:30
uint32_t vxGetHeight(void)
Definition graphic.c:316
void putc(char c, int col, int row, uint32_t fg, uint32_t bg)
Definition graphic.c:151
void clear_screen(uint32_t color)
Definition graphic.c:290
void putc_utf8(const char *s, int col, int row, uint32_t fg, uint32_t bg)
Definition graphic.c:166
void put_pixel_alpha_fast(int x, int y, pixel_t src)
Definition graphic.c:259
#define FONT_SIZE
Definition graphic.h:26
typedef __attribute__
Definition msi.c:47
#define INIT(fn)
Definition init.h:26
void serial2_printf(const char *fmt,...)
void * kalloc(size_t size)
#define KALLOC_REDZONE_SIZE
Definition kalloc.h:10
void kfree2(void *ptr)
#define PTR_ADD(ptr, off)
page_t paging_get_highest_page_map(void)
Definition paging.c:463
void vxMultipleMmap(page_t page_dir, uint64_t virt, uint64_t phys, uint64_t size, uint64_t flags)
Definition paging.c:340
#define PAGE_SIZE
Definition paging.h:6
#define LOG2_WARN(mod, fmt,...)
Definition serial.h:40
#define LOG2_DEBUG(mod, fmt,...)
Definition serial.h:35
#define SSFN_OK
Definition ssfn.h:141
int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size)
int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str)
#define SSFN_FAMILY_ANY
Definition ssfn.h:125
int ssfn_load(ssfn_t *ctx, const void *data)
#define SSFN_STYLE_REGULAR
Definition ssfn.h:78
void memset(void *ptr, int value, size_t num)
void memcopy(void *dest, void *src, size_t size)
kstring str(const char *str)
kstring name
Definition dentry.h:32
struct vnode * vnode
Definition dentry.h:33
char * c_str
Definition string.h:12
uint8_t r
Definition graphic.h:7
uint8_t b
Definition graphic.h:7
uint8_t g
Definition graphic.h:7
uint8_t a
Definition graphic.h:7
Definition ssfn.h:195
void * ops
Definition vnode.h:64
size_t size
Definition vnode.h:63
#define NULL
Definition type.h:76
unsigned short uint16_t
Definition type.h:13
unsigned int uint32_t
Definition type.h:19
uint8_t boolean_t
Definition type.h:89
unsigned long uintptr_t
Definition type.h:73
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
uint32_t y
Definition virtio-gpu.hpp:1
uint32_t x
Definition virtio-gpu.hpp:0
void vma_register(struct virtual_memory_page *page, uintptr_t phys_address, uintptr_t virt_addr, size_t size)
Definition vm_manager.c:101
struct virtual_memory_page * get_kernel_vmm_page()
uint64_t ptr
Definition xhci.hpp:0