syscalls needed for doom (tell/eof/draw_fb) + minor fixes, compiler shut up etc
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* @author xamidev <xamidev@riseup.net>
|
||||
* @brief Screen/framebuffer system calls
|
||||
* @license GPL-3.0-only
|
||||
*/
|
||||
|
||||
// This is not part of POSIX or anything btw
|
||||
|
||||
#include <stdint.h>
|
||||
#include <kernel.h>
|
||||
|
||||
extern struct boot_context boot_ctx;
|
||||
|
||||
/*
|
||||
* pack_rbga_to_fb - Convert rgb values to rgba pixel for framebuffer
|
||||
* @r: red value
|
||||
* @g: green value
|
||||
* @b: blue value
|
||||
*
|
||||
* This function uses the mask sizes and shifts of the Limine
|
||||
* framebuffer to convert raw rgb values into usable pixels.
|
||||
*
|
||||
* Return:
|
||||
* <pixel> - usable pixel
|
||||
*/
|
||||
static uint32_t pack_rgba_to_fb(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
uint32_t pixel = 0;
|
||||
|
||||
if (boot_ctx.fb->red_mask_size) {
|
||||
pixel |= ((uint32_t)(r >> (8 - boot_ctx.fb->red_mask_size)) << boot_ctx.fb->red_mask_shift);
|
||||
}
|
||||
if (boot_ctx.fb->green_mask_size) {
|
||||
pixel |= ((uint32_t)(g >> (8 - boot_ctx.fb->green_mask_size)) << boot_ctx.fb->green_mask_shift);
|
||||
}
|
||||
if (boot_ctx.fb->blue_mask_size) {
|
||||
pixel |= ((uint32_t)(b >> (8 - boot_ctx.fb->blue_mask_size)) << boot_ctx.fb->blue_mask_shift);
|
||||
}
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
/*
|
||||
* sys_draw_fb - Draw a framebuffer subset
|
||||
* @src: Source frame
|
||||
* @width: width of the frame
|
||||
* @height: height of the frame
|
||||
* @channels: how many channels (RGB, RGBA)
|
||||
*
|
||||
* This system call draws the frame @src, having some
|
||||
* @width and @height, in the top right of the Limine
|
||||
* framebuffer. (Used for DOOM)
|
||||
*
|
||||
* Return:
|
||||
* %0 - on success
|
||||
* On error, a negative value with an error code is returned.
|
||||
*/
|
||||
int sys_draw_fb(const uint8_t* src, int width, int height, int channels)
|
||||
{
|
||||
if (!boot_ctx.fb || !src) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (channels != 4 || width <= 0 || height <= 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (boot_ctx.fb->bpp < 24) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
uint32_t* dst = (uint32_t*)boot_ctx.fb->address;
|
||||
uint64_t dst_w = boot_ctx.fb->width;
|
||||
uint64_t dst_h = boot_ctx.fb->height;
|
||||
uint64_t dst_pitch_px = boot_ctx.fb->pitch / 4;
|
||||
uint64_t scale = 2;
|
||||
uint64_t scaled_w = (uint64_t)width * scale;
|
||||
uint64_t scaled_h = (uint64_t)height * scale;
|
||||
|
||||
if (scaled_w > dst_w || scaled_h > dst_h) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint64_t dst_x = dst_w - scaled_w;
|
||||
uint64_t dst_y = 0;
|
||||
|
||||
for (uint64_t y = 0; y < (uint64_t)height; ++y) {
|
||||
const uint8_t* src_row = src + y * (uint64_t)width * 4ULL;
|
||||
uint32_t* dst_row0 = dst + (dst_y + y * scale) * dst_pitch_px + dst_x;
|
||||
uint32_t* dst_row1 = dst_row0 + dst_pitch_px;
|
||||
|
||||
for (uint64_t x = 0; x < (uint64_t)width; ++x) {
|
||||
const uint8_t* p = src_row + x * 4ULL;
|
||||
uint32_t pixel = pack_rgba_to_fb(p[0], p[1], p[2]);
|
||||
uint64_t dx = x * scale;
|
||||
|
||||
// Write 2x2 block. This is because source DOOM frame (320x200)
|
||||
// is quite small.
|
||||
dst_row0[dx + 0] = pixel;
|
||||
dst_row0[dx + 1] = pixel;
|
||||
dst_row1[dx + 0] = pixel;
|
||||
dst_row1[dx + 1] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user