From a94332370a8ea572ef04b5d5b8c18b4905674393 Mon Sep 17 00:00:00 2001 From: koniifer Date: Sat, 19 Oct 2024 15:54:19 +0100 Subject: [PATCH] various render changes, implement sine & cosine for stn.math --- Cargo.lock | 38 ++++++------ .../holeybytes/kernel_services/mem_serve.rs | 9 --- sysdata/libraries/render/TODO.md | 33 +++++++++++ sysdata/libraries/render/src/image.hb | 41 ++++++++++++- sysdata/libraries/render/src/lib.hb | 2 + sysdata/libraries/render/src/software.hb | 58 ++++++++++--------- sysdata/libraries/stn/src/math.hb | 39 +++++++++++++ sysdata/programs/horizon/src/main.hb | 2 +- .../render_example/src/examples/image.hb | 10 ++-- .../render_example/src/examples/surface.hb | 17 ++++-- 10 files changed, 182 insertions(+), 67 deletions(-) create mode 100644 sysdata/libraries/render/TODO.md diff --git a/Cargo.lock b/Cargo.lock index bc371f9..8ad2b1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" [[package]] name = "autocfg" @@ -145,9 +145,9 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -350,12 +350,12 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6ad0b41759dacd5767b5c9cfbc1b3b11c025396a" [[package]] name = "hblang" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6ad0b41759dacd5767b5c9cfbc1b3b11c025396a" dependencies = [ "hashbrown 0.15.0", "hbbytecode", @@ -367,7 +367,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6ad0b41759dacd5767b5c9cfbc1b3b11c025396a" dependencies = [ "hbbytecode", ] @@ -420,9 +420,9 @@ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -567,9 +567,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "limine" @@ -718,9 +718,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -945,9 +945,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.14" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "ring", @@ -968,9 +968,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -1035,9 +1035,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "67d42a0bd4ac281beff598909bb56a86acaf979b84483e1c79c10dcaf98f8cf3" dependencies = [ "itoa", "memchr", diff --git a/kernel/src/holeybytes/kernel_services/mem_serve.rs b/kernel/src/holeybytes/kernel_services/mem_serve.rs index f08a81f..bacf2d5 100644 --- a/kernel/src/holeybytes/kernel_services/mem_serve.rs +++ b/kernel/src/holeybytes/kernel_services/mem_serve.rs @@ -31,15 +31,6 @@ unsafe fn memcpy(mut dest: *mut u8, mut src: *const u8, mut count: usize) { return; } - // let dest_misalignment = dest as usize & 7; - // if dest_misalignment != 0 { - // let align_bytes = 8 - dest_misalignment; - // src.copy_to_nonoverlapping(dest, align_bytes); - // dest = dest.add(align_bytes); - // src = src.add(align_bytes); - // count -= align_bytes; - // } - while count >= 8 { if (src as usize) & 7 == 0 && (dest as usize) & 7 == 0 { *(dest as *mut u64) = *(src as *const u64); diff --git a/sysdata/libraries/render/TODO.md b/sysdata/libraries/render/TODO.md new file mode 100644 index 0000000..746ca4b --- /dev/null +++ b/sysdata/libraries/render/TODO.md @@ -0,0 +1,33 @@ +# Images +- General over image format +- Support formats: + - PNG +- Animation + +# API +- Font Loader + - VGA fonts +- Colour operations: + - Alpha Composite + - Invert +- Surface Operations: + - FlipV + - FlipH + - Resize + - Wrap the colour operations + - Tile + - Gradient overlay +- Draw operations: + - Curve raster algorithm + - VGA font fast blit + - VGA font render + - Polygon + +# Backend +- SVGA Driver +- Support whatever vulkan stuff able is cooking + +# Bits and bobs on the table +- Funny 3D Renderer +- stn.memory.swap & kernel message +- Make memory.{copy, set} smart \ No newline at end of file diff --git a/sysdata/libraries/render/src/image.hb b/sysdata/libraries/render/src/image.hb index 1f55cbd..fd683f5 100644 --- a/sysdata/libraries/render/src/image.hb +++ b/sysdata/libraries/render/src/image.hb @@ -1,5 +1,5 @@ -.{Color, Surface} := @use("./lib.hb"); -.{log} := @use("../../stn/src/lib.hb") +.{Color, Surface, new_surface} := @use("./lib.hb"); +.{log, memory} := @use("../../stn/src/lib.hb") BitmapFileHeader := packed struct { img_type: u16, @@ -63,4 +63,41 @@ surface_from_bmp := fn(bmp: ^u8): Surface { } return .(@bitcast(bmp), @intcast(info_header.width), @intcast(info_header.height)) +} + +new_surface_from_bmp := fn(bmp: ^u8): Surface { + file_header := @as(^BitmapFileHeader, @bitcast(bmp)) + if file_header.img_type != 0x4D42 { + log.error("failed to load bmp image: not a bmp image, idiot\0") + return @as(Surface, idk) + } + info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader))) + bmp += file_header.offset + + width := @as(int, @intcast(info_header.width)) + height := @as(int, @intcast(info_header.height)) + + surface := new_surface(width, height) + top_start_idx := surface.buf + bottom_start_idx := surface.buf + width * (height - 1) + rows_to_copy := height + top_cursor := @as(^Color, @bitcast(bmp)) + bottom_cursor := top_cursor + width * (height - 1) + + loop if rows_to_copy <= 1 break else { + @inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(width)) + @inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(width)) + + top_start_idx += surface.width + bottom_start_idx -= surface.width + top_cursor += width + bottom_cursor -= width + rows_to_copy -= 2 + } + + if rows_to_copy == 1 { + @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(width)) + } + + return surface } \ No newline at end of file diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb index 9227f52..3132b3b 100644 --- a/sysdata/libraries/render/src/lib.hb +++ b/sysdata/libraries/render/src/lib.hb @@ -11,6 +11,8 @@ new_surface := mode.new_surface surface_from_ptr := mode.surface_from_ptr clone_surface := mode.clone_surface free_surface := mode.free_surface +index := mode.index +indexptr := mode.indexptr // Colours Color := packed struct {b: u8, g: u8, r: u8, a: u8} diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index 8cd0b74..038bbea 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -31,7 +31,7 @@ clone_surface := fn(surface: ^Surface): Surface { } free_surface := fn(surface: ^Surface): void { - // todo + // todo: depends on stn.memory.free return } @@ -56,18 +56,22 @@ sync := fn(surface: Surface): void { return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height)) } -screenidx := fn(surface: Surface, x: int, y: int): int { +index := fn(surface: Surface, x: int, y: int): int { return x + surface.width * y } +indexptr := fn(surface: Surface, x: int, y: int): ^Color { + return surface.buf + @inline(index, surface, x, y) +} + put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void { - *(surface.buf + @inline(screenidx, surface, pos.x, pos.y)) = color + *@inline(indexptr, surface, pos.x, pos.y) = color return } put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void { - top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y) - bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y - 1) + top_start_idx := @inline(indexptr, surface, pos.x, pos.y) + bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1) rows_to_fill := tr.y loop if rows_to_fill <= 1 break else { @@ -87,19 +91,19 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Co } put_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void { - start_idx := @inline(screenidx, surface, pos.x, pos.y) - end_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y) - right_start_idx := @inline(screenidx, surface, pos.x + tr.x, pos.y) + start_idx := @inline(indexptr, surface, pos.x, pos.y) + end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y) + right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y) loop if start_idx > end_idx break else { - *(surface.buf + start_idx) = color; - *(surface.buf + right_start_idx) = color + *start_idx = color; + *right_start_idx = color start_idx += surface.width right_start_idx += surface.width } - @inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y), @bitcast(tr.x + 1)) - @inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1)) + @inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1)) + @inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1)) return } @@ -116,7 +120,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color) y := p0.y x := p0.x loop if x == p1.x break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(indexptr, surface, x, y) = color if D > 0 { y += yi D += 2 * (dy - dx) @@ -140,7 +144,7 @@ put_line_high := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color x := p0.x y := p0.y loop if y == p1.y break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(indexptr, surface, x, y) = color if D > 0 { x += xi D += 2 * (dx - dy) @@ -169,16 +173,21 @@ put_line := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): vo return } -put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void { - top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y) - bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + top.height - 1) +put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int), flip_v: bool): void { + top_start_idx := @inline(indexptr, surface, pos.x, pos.y) + bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1) rows_to_copy := top.height top_cursor := top.buf bottom_cursor := top.buf + top.width * (top.height - 1) loop if rows_to_copy <= 1 break else { - @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width)) - @inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width)) + if flip_v { + @inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(top.width)) + @inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(top.width)) + } else { + @inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width)) + @inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width)) + } top_start_idx += surface.width bottom_start_idx -= surface.width @@ -208,7 +217,7 @@ put_trirect := fn(surface: Surface, pos: Vec2(int), size: Vec2(int), color0: Col target := pos + size loop if pos.x == target.x break else { - put_vline(surface, pos.x, pos.y, target.y, color0) + @inline(put_vline, surface, pos.x, pos.y, target.y, color0) @inline(put_vline, surface, pos.x, pos.y, start_y, color1) pos += step } @@ -226,7 +235,7 @@ put_vline := fn(surface: Surface, x: int, y0: int, y1: int, color: Color): void y := y0 loop if y == y1 break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color + *@inline(indexptr, surface, x, y) = color y += 1 } @@ -240,12 +249,7 @@ put_hline := fn(surface: Surface, y: int, x0: int, x1: int, color: Color): void x0 = x1 x1 = tmp } - x := x0 - - loop if x == x1 break else { - *(surface.buf + @inline(screenidx, surface, x, y)) = color - x += 1 - } + @inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1)) return } \ No newline at end of file diff --git a/sysdata/libraries/stn/src/math.hb b/sysdata/libraries/stn/src/math.hb index f4e0c84..563e9c3 100644 --- a/sysdata/libraries/stn/src/math.hb +++ b/sysdata/libraries/stn/src/math.hb @@ -10,7 +10,46 @@ max := fn($Expr: type, a: Expr, b: Expr): Expr { c := a - b return a - (c & c >> @intcast(@sizeof(Expr) - 1)) } +signum := fn($Expr: type, x: Expr): int { + if x > @as(Expr, @intcast(0)) { + return 1 + } else if x < @as(Expr, @intcast(0)) { + return -1 + } else { + return 0 + } +} +signincl := fn($Expr: type, x: Expr): int { + if x > @as(Expr, @intcast(0)) { + return 1 + } + return -1 +} Vec2 := fn($Expr: type): type { return struct {x: Expr, y: Expr} +} + +SIN_TABLE := [int].(0, 174, 348, 523, 697, 871, 1045, 1218, 1391, 1564, 1736, 1908, 2079, 2249, 2419, 2588, 2756, 2923, 3090, 3255, 3420, 3583, 3746, 3907, 4067, 4226, 4384, 4540, 4695, 4848, 5000, 5150, 5299, 5446, 5591, 5735, 5877, 6018, 6156, 6293, 6427, 6560, 6691, 6819, 6946, 7071, 7193, 7313, 7431, 7547, 7660, 7771, 7880, 7986, 8090, 8191, 8290, 8386, 8480, 8571, 8660, 8746, 8829, 8910, 8987, 9063, 9135, 9205, 9271, 9335, 9396, 9455, 9510, 9563, 9612, 9659, 9702, 9743, 9781, 9816, 9848, 9877, 9902, 9925, 9945, 9961, 9975, 9986, 9993, 9998, 10000) + +sin_i := fn(theta_deg: int, amplitude: int): int { + theta := theta_deg % 360 + if theta < 0 { + theta += 360 + } + + quadrant := theta / 90 + theta = theta % 90 + + sign := 1 - ((quadrant & 2) >> 1) * 2 + complement := quadrant & 1 + + index := theta * (1 - complement) + (90 - theta) * complement + sin_value := SIN_TABLE[index] * sign + + return (sin_value * amplitude + 5000) / 10000 +} + +cos_i := fn(theta_deg: int, amplitude: int): int { + return @inline(sin_i, theta_deg + 90, amplitude) } \ No newline at end of file diff --git a/sysdata/programs/horizon/src/main.hb b/sysdata/programs/horizon/src/main.hb index e9ba172..95e5cfb 100644 --- a/sysdata/programs/horizon/src/main.hb +++ b/sysdata/programs/horizon/src/main.hb @@ -71,7 +71,7 @@ main := fn(): int { // Apply the image to the screen pos := Vec2(int).(x, 100) - render.put_surface(screen, window, pos) + render.put_surface(screen, window, pos, false) if window_count >= 1 { x = 10 break diff --git a/sysdata/programs/render_example/src/examples/image.hb b/sysdata/programs/render_example/src/examples/image.hb index ce59daf..b7e1ba0 100644 --- a/sysdata/programs/render_example/src/examples/image.hb +++ b/sysdata/programs/render_example/src/examples/image.hb @@ -8,27 +8,27 @@ bmp_1 := @embed("./assets/able.bmp") bmp_2 := @embed("./assets/mini.bmp") example := fn(): void { - screen := render.init(true) images := [render.Surface; 2].( render.image.surface_from_bmp(@bitcast(&bmp_1)), render.image.surface_from_bmp(@bitcast(&bmp_2)), ) + screen := render.init(true) vel := Vec2(int).(1, 1) pos := Vec2(int).(100, 100) - n := -1 + n := 0 loop { image := images[n] - render.put_surface(screen, image, pos) + render.put_surface(screen, image, pos, false) render.sync(screen) render.clear(screen, render.black) if pos.x == 0 | pos.x == screen.width - image.width { vel.x = -vel.x - n = -1 - n + n = 1 - n } if pos.y == 0 | pos.y == screen.height - image.height { vel.y = -vel.y - n = -1 - n + n = 1 - n } pos += vel diff --git a/sysdata/programs/render_example/src/examples/surface.hb b/sysdata/programs/render_example/src/examples/surface.hb index a3b75ac..50353eb 100644 --- a/sysdata/programs/render_example/src/examples/surface.hb +++ b/sysdata/programs/render_example/src/examples/surface.hb @@ -14,7 +14,10 @@ example := fn(): void { side := image.width / 8 vel_inner := Vec2(int).(1, 1) pos_inner := Vec2(int).((image.width - side) / 2, (image.height - side) / 2) - color := random.range(render.Color, render.black, render.white) + // workaround for compiler bug + color := render.Color.(0, 0, 0, 0) + color = random.range(render.Color, render.black, render.white) + target_color := color loop { render.clear(screen, render.black) // color += .(1, 1, 1, 1) @@ -22,17 +25,17 @@ example := fn(): void { render.put_rect(image, pos_inner, .(side, side), render.black) render.put_rect(image, .(0, 0), .(image.width - 1, image.height - 1), color) - render.put_surface(screen, image, pos) + render.put_surface(screen, image, pos, false) render.put_rect(image, pos_inner, .(side, side), color) render.sync(screen) if pos_inner.x == 0 | pos_inner.x == image.width - side { vel_inner.x = -vel_inner.x - color = random.range(render.Color, render.black, render.white) + target_color = random.range(render.Color, render.black, render.white) } if pos_inner.y == 0 | pos_inner.y == image.height - side { vel_inner.y = -vel_inner.y - color = random.range(render.Color, render.black, render.white) + target_color = random.range(render.Color, render.black, render.white) } if pos.x == 0 | pos.x == screen.width - image.width { @@ -42,6 +45,12 @@ example := fn(): void { vel.y = -vel.y } + color += .( + @intcast(color.b < target_color.b) - @intcast(color.b > target_color.b), + @intcast(color.g < target_color.g) - @intcast(color.g > target_color.g), + @intcast(color.r < target_color.r) - @intcast(color.r > target_color.r), + 0, + ) pos += vel pos_inner += vel_inner }