diff options
Diffstat (limited to 'mirai.old/utils/graphics/pixel.zig')
| -rw-r--r-- | mirai.old/utils/graphics/pixel.zig | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/mirai.old/utils/graphics/pixel.zig b/mirai.old/utils/graphics/pixel.zig new file mode 100644 index 0000000..29bd446 --- /dev/null +++ b/mirai.old/utils/graphics/pixel.zig @@ -0,0 +1,197 @@ +//! Pixel and framebuffer utilities + +const boot = @import("../../boot/multiboot/multiboot.zig"); +const color = @import("color.zig"); +const video = @import("../../common/constants/video.zig"); + +pub inline fn ptr_32(addr: u64) [*]volatile u32 { + return @as([*]volatile u32, @ptrFromInt(addr)); +} + +pub inline fn ptr_8(addr: u64) [*]volatile u8 { + return @as([*]volatile u8, @ptrFromInt(addr)); +} + +pub inline fn offset_32(fb: boot.FramebufferInfo, x: u32, y: u32) usize { + return y * (fb.pitch / video.BYTES_PER_PIXEL_32) + x; +} + +pub inline fn offset_24(fb: boot.FramebufferInfo, x: u32, y: u32) usize { + return y * fb.pitch + x * video.BYTES_PER_PIXEL_24; +} + +pub inline fn pixels_per_row(fb: boot.FramebufferInfo) u32 { + return fb.pitch / video.BYTES_PER_PIXEL_32; +} + +pub fn put(fb: boot.FramebufferInfo, x: u32, y: u32, c: u32) void { + if (x >= fb.width or y >= fb.height) return; + + if (fb.bpp == video.BPP_32) { + put_32(fb, x, y, c); + } else if (fb.bpp == video.BPP_24) { + put_24(fb, x, y, c); + } +} + +pub fn put_32(fb: boot.FramebufferInfo, x: u32, y: u32, c: u32) void { + const pixels = ptr_32(fb.addr); + pixels[offset_32(fb, x, y)] = c; +} + +pub fn put_24(fb: boot.FramebufferInfo, x: u32, y: u32, c: u32) void { + const pixels = ptr_8(fb.addr); + const off = offset_24(fb, x, y); + const rgb = color.extract(c); + pixels[off] = rgb.b; + pixels[off + 1] = rgb.g; + pixels[off + 2] = rgb.r; +} + +pub fn fill(fb: boot.FramebufferInfo, c: u32) void { + if (fb.bpp == video.BPP_32) { + fill_32(fb, c); + } else if (fb.bpp == video.BPP_24) { + fill_24(fb, c); + } +} + +pub fn fill_32(fb: boot.FramebufferInfo, c: u32) void { + const pixels = ptr_32(fb.addr); + const total = fb.width * fb.height; + var i: usize = 0; + while (i < total) : (i += 1) { + pixels[i] = c; + } +} + +pub fn fill_24(fb: boot.FramebufferInfo, c: u32) void { + const pixels = ptr_8(fb.addr); + const rgb = color.extract(c); + + var y: u32 = 0; + while (y < fb.height) : (y += 1) { + var x: u32 = 0; + while (x < fb.width) : (x += 1) { + const off = offset_24(fb, x, y); + pixels[off] = rgb.b; + pixels[off + 1] = rgb.g; + pixels[off + 2] = rgb.r; + } + } +} + +pub fn fill_rect(fb: boot.FramebufferInfo, x: u32, y: u32, w: u32, h: u32, c: u32) void { + if (fb.bpp == video.BPP_32) { + fill_rect_32(fb, x, y, w, h, c); + } else if (fb.bpp == video.BPP_24) { + fill_rect_24(fb, x, y, w, h, c); + } +} + +pub fn fill_rect_32(fb: boot.FramebufferInfo, x: u32, y: u32, w: u32, h: u32, c: u32) void { + const pixels = ptr_32(fb.addr); + + var row: u32 = 0; + while (row < h) : (row += 1) { + var col: u32 = 0; + while (col < w) : (col += 1) { + const px = x + col; + const py = y + row; + if (px < fb.width and py < fb.height) { + pixels[offset_32(fb, px, py)] = c; + } + } + } +} + +pub fn fill_rect_24(fb: boot.FramebufferInfo, x: u32, y: u32, w: u32, h: u32, c: u32) void { + const pixels = ptr_8(fb.addr); + const rgb = color.extract(c); + + var row: u32 = 0; + while (row < h) : (row += 1) { + var col: u32 = 0; + while (col < w) : (col += 1) { + const px = x + col; + const py = y + row; + if (px < fb.width and py < fb.height) { + const off = offset_24(fb, px, py); + pixels[off] = rgb.b; + pixels[off + 1] = rgb.g; + pixels[off + 2] = rgb.r; + } + } + } +} + +pub fn copy_row(fb: boot.FramebufferInfo, dst_y: u32, src_y: u32) void { + if (fb.bpp == video.BPP_32) { + copy_row_32(fb, dst_y, src_y); + } else if (fb.bpp == video.BPP_24) { + copy_row_24(fb, dst_y, src_y); + } +} + +pub fn copy_row_32(fb: boot.FramebufferInfo, dst_y: u32, src_y: u32) void { + const pixels = ptr_32(fb.addr); + const ppr = pixels_per_row(fb); + + var x: u32 = 0; + while (x < fb.width) : (x += 1) { + pixels[dst_y * ppr + x] = pixels[src_y * ppr + x]; + } +} + +pub fn copy_row_24(fb: boot.FramebufferInfo, dst_y: u32, src_y: u32) void { + const pixels = ptr_8(fb.addr); + + var x: u32 = 0; + while (x < fb.width) : (x += 1) { + const src_off = offset_24(fb, x, src_y); + const dst_off = offset_24(fb, x, dst_y); + pixels[dst_off] = pixels[src_off]; + pixels[dst_off + 1] = pixels[src_off + 1]; + pixels[dst_off + 2] = pixels[src_off + 2]; + } +} + +pub fn clear_row(fb: boot.FramebufferInfo, y: u32, c: u32) void { + if (fb.bpp == video.BPP_32) { + clear_row_32(fb, y, c); + } else if (fb.bpp == video.BPP_24) { + clear_row_24(fb, y, c); + } +} + +pub fn clear_row_32(fb: boot.FramebufferInfo, y: u32, c: u32) void { + const pixels = ptr_32(fb.addr); + const ppr = pixels_per_row(fb); + + var x: u32 = 0; + while (x < fb.width) : (x += 1) { + pixels[y * ppr + x] = c; + } +} + +pub fn clear_row_24(fb: boot.FramebufferInfo, y: u32, c: u32) void { + const pixels = ptr_8(fb.addr); + const rgb = color.extract(c); + + var x: u32 = 0; + while (x < fb.width) : (x += 1) { + const off = offset_24(fb, x, y); + pixels[off] = rgb.b; + pixels[off + 1] = rgb.g; + pixels[off + 2] = rgb.r; + } +} + +pub fn line_width(fb: boot.FramebufferInfo) u32 { + if (fb.bpp == video.BPP_32) { + return fb.pitch / video.BYTES_PER_PIXEL_32; + } else if (fb.bpp == video.BPP_24) { + return fb.pitch / video.BYTES_PER_PIXEL_24; + } + return fb.width; +} |
