From 1031ca63146ac9483a726bd7acdc65fb4a4af2dd Mon Sep 17 00:00:00 2001 From: koniifer Date: Sat, 7 Sep 2024 23:08:58 +0100 Subject: [PATCH] reimplement fb_driver as software render interface. sufficiently jank double buffering implementation waiting on an intelligent design. --- sysdata/libraries/render/README.md | 9 + sysdata/libraries/render/src/lib.hb | 43 ++++ sysdata/libraries/render/src/software.hb | 199 ++++++++++++++++++ sysdata/libraries/render/src/svga.hb | 68 ++++++ sysdata/libraries/stn/src/math.hb | 11 +- sysdata/libraries/stn/src/random.hb | 11 +- sysdata/programs/fb_driver/README.md | 2 - sysdata/programs/fb_driver/UNTESTED_FUNCTIONS | 7 - sysdata/programs/fb_driver/src/color.hb | 27 --- sysdata/programs/fb_driver/src/draw.hb | 113 ---------- .../programs/fb_driver/src/examples/amogus.hb | 26 --- .../fb_driver/src/examples/buffers.hb | 19 -- .../programs/fb_driver/src/examples/colors.hb | 27 --- .../programs/fb_driver/src/examples/lines.hb | 25 --- .../programs/fb_driver/src/examples/random.hb | 17 -- .../programs/fb_driver/src/examples/square.hb | 32 --- .../programs/fb_driver/src/examples/strobe.hb | 20 -- sysdata/programs/fb_driver/src/lib.hb | 88 -------- .../{fb_driver => render_driver}/meta.toml | 4 +- sysdata/programs/render_driver/src/main.hb | 6 + sysdata/programs/render_example/meta.toml | 11 + .../render_example/src/examples/amogus.hb | 19 ++ .../render_example/src/examples/colors.hb | 20 ++ .../render_example/src/examples/lines.hb | 20 ++ .../render_example/src/examples/random.hb | 16 ++ .../render_example/src/examples/square.hb | 26 +++ .../render_example/src/examples/strobe.hb | 14 ++ .../{fb_driver => render_example}/src/main.hb | 4 +- sysdata/system_config.toml | 7 +- 29 files changed, 471 insertions(+), 420 deletions(-) create mode 100644 sysdata/libraries/render/README.md create mode 100644 sysdata/libraries/render/src/lib.hb create mode 100644 sysdata/libraries/render/src/software.hb create mode 100644 sysdata/libraries/render/src/svga.hb delete mode 100644 sysdata/programs/fb_driver/README.md delete mode 100644 sysdata/programs/fb_driver/UNTESTED_FUNCTIONS delete mode 100644 sysdata/programs/fb_driver/src/color.hb delete mode 100644 sysdata/programs/fb_driver/src/draw.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/amogus.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/buffers.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/colors.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/lines.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/random.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/square.hb delete mode 100644 sysdata/programs/fb_driver/src/examples/strobe.hb delete mode 100644 sysdata/programs/fb_driver/src/lib.hb rename sysdata/programs/{fb_driver => render_driver}/meta.toml (71%) create mode 100644 sysdata/programs/render_driver/src/main.hb create mode 100644 sysdata/programs/render_example/meta.toml create mode 100644 sysdata/programs/render_example/src/examples/amogus.hb create mode 100644 sysdata/programs/render_example/src/examples/colors.hb create mode 100644 sysdata/programs/render_example/src/examples/lines.hb create mode 100644 sysdata/programs/render_example/src/examples/random.hb create mode 100644 sysdata/programs/render_example/src/examples/square.hb create mode 100644 sysdata/programs/render_example/src/examples/strobe.hb rename sysdata/programs/{fb_driver => render_example}/src/main.hb (67%) diff --git a/sysdata/libraries/render/README.md b/sysdata/libraries/render/README.md new file mode 100644 index 00000000..ac765ebf --- /dev/null +++ b/sysdata/libraries/render/README.md @@ -0,0 +1,9 @@ +Rendering interface for SVGA and Software renderers + +# TODO: + +- SVGA Driver + - needs pci driver + - needs init (requiring program) +- Double Buffer mode for Software renderer + - needs init (requiring program) \ No newline at end of file diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb new file mode 100644 index 00000000..3cb0274d --- /dev/null +++ b/sysdata/libraries/render/src/lib.hb @@ -0,0 +1,43 @@ +svga := @use("rel:svga.hb") +software := @use("rel:software.hb") + +default := software + +init := default.init + +// Colours +Color := default.Color +white := default.white +black := default.black +gray := default.gray +red := default.red +green := default.green +yellow := default.yellow +blue := default.blue +magenta := default.magenta +cyan := default.cyan +light_gray := default.light_gray +light_red := default.light_red +light_green := default.light_green +light_yellow := default.light_yellow +light_blue := default.light_blue +light_magenta := default.light_magenta +light_cyan := default.light_cyan + +// Drawing +put_pixel := default.put_pixel +put_rect := default.put_rect +put_filled_rect := default.put_filled_rect +put_line := default.put_line +clear := default.clear + +// Display +screen_width := default.screen_width +screen_height := default.screen_height +set_screen_height := default.set_screen_height +set_screen_width := default.set_screen_width +sync := default.sync + +// Math +UVec2 := struct {x: uint, y: uint} +IVec2 := struct {x: int, y: int} \ No newline at end of file diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb new file mode 100644 index 00000000..0da615ad --- /dev/null +++ b/sysdata/libraries/render/src/software.hb @@ -0,0 +1,199 @@ +.{log, math, memory, buffer} := @use("../../stn/src/lib.hb"); +.{IVec2} := @use("rel:lib.hb") + +Color := struct {b: u8, g: u8, r: u8, a: u8} +white := Color.(255, 255, 255, 255) +black := Color.(0, 0, 0, 255) +gray := Color.(127, 127, 127, 255) +red := Color.(0, 0, 205, 255) +green := Color.(0, 205, 0, 255) +yellow := Color.(0, 205, 205, 255) +blue := Color.(205, 0, 0, 255) +magenta := Color.(205, 0, 205, 255) +cyan := Color.(205, 205, 0, 255) +light_gray := Color.(229, 229, 229, 255) +light_red := Color.(0, 0, 255, 255) +light_green := Color.(0, 255, 0, 255) +light_yellow := Color.(0, 255, 255, 255) +light_blue := Color.(255, 0, 0, 255) +light_magenta := Color.(255, 0, 255, 255) +light_cyan := Color.(255, 255, 0, 255) + +fb_width := 1024 +fb_height := 768 +fb_pixels := fb_width * fb_height +fb_bytes := fb_pixels << 2 +copy_pixels := math.min(0x1800, fb_bytes) >> 2 +partitions := fb_pixels / copy_pixels +total_pages := 1 + fb_bytes >> 12 + +front_buffer := @as(^Color, @bitcast(0xFFFF8000C0000000)) +// jank back buffer time, im sure nothing will go wrong +// will be removed as soon as i can figure out a fast way of doing runtime global scope +back_buffer := @as(^Color, @bitcast(0xFFFF8000C0000000 + fb_bytes)) +// create_back_buffer := fn(): ^Color { +// if total_pages <= 0xFF { +// return @bitcast(@inline(memory.request_page, total_pages)) +// } +// ptr := @inline(memory.request_page, 255) +// remaining := total_pages - 0xFF +// loop if remaining <= 0 break else { +// if remaining < 0xFF { +// memory.request_page(remaining) +// } else { +// memory.request_page(0xFF) +// } +// remaining -= 0xFF +// } +// return @bitcast(ptr) +// } + +clear := fn(color: Color): void { + n := 0 + loop if n >= copy_pixels break else { + *(back_buffer + n) = color + n += 1 + } + n = 1 + loop if n >= partitions break else { + *(@as(^[Color; copy_pixels], @bitcast(back_buffer)) + n) = *@as(^[Color; copy_pixels], @bitcast(back_buffer)) + n += 1 + } + return +} + +sync := fn(): void { + n := 0 + loop if n >= partitions break else { + *(@as(^[Color; copy_pixels], @bitcast(front_buffer)) + n) = *(@as(^[Color; copy_pixels], @bitcast(back_buffer)) + n) + n += 1 + } + return +} + +screen_width := fn(): int { + return fb_width +} + +screen_height := fn(): int { + return fb_height +} + +screenidx := fn(x: int, y: int): int { + return x + fb_width * y +} + +put_pixel := fn(pos: IVec2, color: Color): void { + *(back_buffer + @inline(screenidx, pos.x, pos.y)) = color + return +} + +put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void { + x := pos.x + y := pos.y + end := pos + tr + loop if x == end.x break else { + loop if y == end.y break else { + *(back_buffer + @inline(screenidx, x, y)) = color + y += 1 + } + x += 1 + y = pos.y + } + return +} + +put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void { + x := pos.x + y := pos.y + end := pos + tr + loop if y == end.y break else { + *(back_buffer + @inline(screenidx, x, y)) = color; + *(back_buffer + @inline(screenidx, x + tr.x, y)) = color + y += 1 + } + y = pos.y + loop if x == end.x break else { + *(back_buffer + @inline(screenidx, x, y)) = color; + *(back_buffer + @inline(screenidx, x, y + tr.y)) = color + x += 1 + } + return +} + +put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void { + dx := p1.x - p0.x + dy := p1.y - p0.y + yi := 1 + if dy < 0 { + yi = 0 - 1 + dy = 0 - dy + } + D := 2 * dy - dx + y := p0.y + x := p0.x + loop if x == p1.x break else { + *(back_buffer + @inline(screenidx, x, y)) = color + if D > 0 { + y += yi + D += 2 * (dy - dx) + } else { + D += 2 * dy + } + x += 1 + } + return +} + +put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void { + dx := p1.x - p0.x + dy := p1.y - p0.y + xi := 1 + if dy < 0 { + xi = 0 - 1 + dx = 0 - dx + } + D := 2 * dx - dy + x := p0.x + y := p0.y + loop if y == p1.y break else { + *(back_buffer + @inline(screenidx, x, y)) = color + if D > 0 { + x += xi + D += 2 * (dx - dy) + } else { + D += 2 * dx + } + y += 1 + } + return +} + +put_line := fn(p0: IVec2, p1: IVec2, color: Color): void { + if @inline(math.abs, p1.y - p0.y) < @inline(math.abs, p1.x - p0.x) { + if p0.x > p1.x { + @inline(put_line_low, p1, p0, color) + } else { + @inline(put_line_low, p0, p1, color) + } + } else { + if p0.y > p1.y { + @inline(put_line_high, p1, p0, color) + } else { + @inline(put_line_high, p0, p1, color) + } + } + return +} + +set_screen_height := fn(new: int): void { + return +} + +set_screen_width := fn(new: int): void { + return +} + +init := fn(): void { + return +} \ No newline at end of file diff --git a/sysdata/libraries/render/src/svga.hb b/sysdata/libraries/render/src/svga.hb new file mode 100644 index 00000000..b1e9bf89 --- /dev/null +++ b/sysdata/libraries/render/src/svga.hb @@ -0,0 +1,68 @@ +.{log, math} := @use("../../stn/src/lib.hb"); +.{IVec2} := @use("rel:lib.hb") + +Color := struct {b: u8, g: u8, r: u8, a: u8} +white := Color.(255, 255, 255, 255) +black := Color.(0, 0, 0, 255) +gray := Color.(127, 127, 127, 255) +red := Color.(0, 0, 205, 255) +green := Color.(0, 205, 0, 255) +yellow := Color.(0, 205, 205, 255) +blue := Color.(205, 0, 0, 255) +magenta := Color.(205, 0, 205, 255) +cyan := Color.(205, 205, 0, 255) +light_gray := Color.(229, 229, 229, 255) +light_red := Color.(0, 0, 255, 255) +light_green := Color.(0, 255, 0, 255) +light_yellow := Color.(0, 255, 255, 255) +light_blue := Color.(255, 0, 0, 255) +light_magenta := Color.(255, 0, 255, 255) +light_cyan := Color.(255, 255, 0, 255) + +clear := fn(color: Color): void { + return +} + +screen_width := fn(): int { + return 0 +} + +screen_height := fn(): int { + return 0 +} + +put_pixel := fn(position: IVec2, color: Color): void { + return +} + +put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void { + return +} + +put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void { + return +} + +put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void { + return +} +// do not use, use line() instead +put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void { + return +} + +put_line := fn(p0: IVec2, p1: IVec2, color: Color): void { + return +} + +set_screen_height := fn(new: int): void { + return +} + +set_screen_width := fn(new: int): void { + return +} + +init := fn(): void { + return +} \ No newline at end of file diff --git a/sysdata/libraries/stn/src/math.hb b/sysdata/libraries/stn/src/math.hb index 94ee78a3..4c4f87e5 100644 --- a/sysdata/libraries/stn/src/math.hb +++ b/sysdata/libraries/stn/src/math.hb @@ -1,14 +1,15 @@ -SIZEOF_INT := 31 +shift := 31 +// following only work for: int abs := fn(x: int): int { - mask := x >> SIZEOF_INT + mask := x >> shift return (x ^ mask) - mask } min := fn(a: int, b: int): int { c := a - b - return b + (c & c >> SIZEOF_INT) + return b + (c & c >> shift) } -max := fn(a: int, b: int): int { +max := fn(a: int, b: uint): int { c := a - b - return a - (c & c >> SIZEOF_INT) + return a - (c & c >> shift) } \ No newline at end of file diff --git a/sysdata/libraries/stn/src/random.hb b/sysdata/libraries/stn/src/random.hb index dbff80a5..b515d1ca 100644 --- a/sysdata/libraries/stn/src/random.hb +++ b/sysdata/libraries/stn/src/random.hb @@ -1,8 +1,7 @@ -integer := fn(min: int, max: int): int { - rng := @eca(int, 3, 4) +integer := fn(): int { + return @eca(int, 3, 4) +} - if min != 0 | max != 0 { - return rng % (max - min + 1) + min - } - return rng +integer_range := fn(min: int, max: int): int { + return @eca(int, 3, 4) % (max - min + 1) + min } \ No newline at end of file diff --git a/sysdata/programs/fb_driver/README.md b/sysdata/programs/fb_driver/README.md deleted file mode 100644 index b354f04d..00000000 --- a/sysdata/programs/fb_driver/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Framebuffer Driver -A simple framebuffer driver. \ No newline at end of file diff --git a/sysdata/programs/fb_driver/UNTESTED_FUNCTIONS b/sysdata/programs/fb_driver/UNTESTED_FUNCTIONS deleted file mode 100644 index 7c7d0f5e..00000000 --- a/sysdata/programs/fb_driver/UNTESTED_FUNCTIONS +++ /dev/null @@ -1,7 +0,0 @@ -color.blend - -lib.composite -lib.screen2rect -lib.rect2screen - -draw.tri_line \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/color.hb b/sysdata/programs/fb_driver/src/color.hb deleted file mode 100644 index 802c1273..00000000 --- a/sysdata/programs/fb_driver/src/color.hb +++ /dev/null @@ -1,27 +0,0 @@ -ColorBGRA := struct {b: u8, g: u8, r: u8, a: u8} - -/* ALL the colo(u)rs you will ever need. - they dont work though, cause hblang bug (reg id leaked, again) */ -WHITE := ColorBGRA.{b: 255, g: 255, r: 255, a: 255} -BLACK := ColorBGRA.{b: 0, g: 0, r: 0, a: 255} -GRAY := ColorBGRA.{b: 127, g: 127, r: 127, a: 255} -RED := ColorBGRA.{b: 0, g: 0, r: 205, a: 255} -GREEN := ColorBGRA.{b: 0, g: 205, r: 0, a: 255} -YELLOW := ColorBGRA.{b: 0, g: 205, r: 205, a: 255} -BLUE := ColorBGRA.{b: 205, g: 0, r: 0, a: 255} -MAGENTA := ColorBGRA.{b: 205, g: 0, r: 205, a: 255} -CYAN := ColorBGRA.{b: 205, g: 205, r: 0, a: 255} -LIGHTGRAY := ColorBGRA.{b: 229, g: 229, r: 229, a: 255} -LIGHTRED := ColorBGRA.{b: 0, g: 0, r: 255, a: 255} -LIGHTGREEN := ColorBGRA.{b: 0, g: 255, r: 0, a: 255} -LIGHTYELLOW := ColorBGRA.{b: 0, g: 255, r: 255, a: 255} -LIGHTBLUE := ColorBGRA.{b: 255, g: 0, r: 0, a: 255} -LIGHTMAGENTA := ColorBGRA.{b: 255, g: 0, r: 255, a: 255} -LIGHTCYAN := ColorBGRA.{b: 255, g: 255, r: 0, a: 255} - -// i have no clue if this works. please don't me ask how it works. -koniifer -blend := fn(fg: ColorBGRA, bg: ColorBGRA): ColorBGRA { - s := fg + bg - m := s - ((fg ^ bg) & 0x1010100) & 0x1010100 - return (m >> 8 | 0x1000000 * (s < fg)) * 0xFF | s - m -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/draw.hb b/sysdata/programs/fb_driver/src/draw.hb deleted file mode 100644 index 089dc38e..00000000 --- a/sysdata/programs/fb_driver/src/draw.hb +++ /dev/null @@ -1,113 +0,0 @@ -.{draw_pixel, screenidx, Transform, Point, Rect, Buffer, FB_WIDTH} := @use("rel:lib.hb"); -.{math} := @use("../../../libraries/stn/src/lib.hb"); -.{ColorBGRA} := @use("rel:color.hb") - -/* draws a filled rectangle to the screen - will be optimised later */ -rect_fill := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA): void { - n := 0 - loop if n == tr.height * tr.width break else { - *(buffer.write + @inline(screenidx, .(n % tr.width + pos.x, n / tr.width + pos.y))) = color - n += 1 - } - return -} -/* draws a wireframe rectangle to the screen - will also be optimised later */ -rect_line := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA, thickness: int): void { - t := 0 - y := 0 - x := 0 - loop if t == thickness break else { - y = pos.y - x = pos.x - loop if y == pos.y + tr.height break else { - *(buffer.write + @inline(screenidx, .(pos.x + t, y))) = color; - *(buffer.write + @inline(screenidx, .(pos.x + tr.width - t, y))) = color - y += 1 - } - loop if x == pos.x + tr.width break else { - *(buffer.write + @inline(screenidx, .(x, pos.y + t))) = color; - *(buffer.write + @inline(screenidx, .(x, pos.y + tr.height - t))) = color - x += 1 - } - t += 1 - } - return -} - -// do not use, use line() instead -line_low := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void { - dx := p1.x - p0.x - dy := p1.y - p0.y - yi := 1 - if dy < 0 { - yi = 0 - 1 - dy = 0 - dy - } - D := 2 * dy - dx - y := p0.y - x := p0.x - loop if x == p1.x break else { - *(buffer.write + @inline(screenidx, .(x, y))) = color - if D > 0 { - y += yi - D += 2 * (dy - dx) - } else { - D += 2 * dy - } - x += 1 - } - return -} -// do not use, use line() instead -line_high := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void { - dx := p1.x - p0.x - dy := p1.y - p0.y - xi := 1 - if dy < 0 { - xi = 0 - 1 - dx = 0 - dx - } - D := 2 * dx - dy - x := p0.x - y := p0.y - loop if y == p1.y break else { - *(buffer.write + @inline(screenidx, .(x, y))) = color - if D > 0 { - x += xi - D += 2 * (dx - dy) - } else { - D += 2 * dx - } - y += 1 - } - return -} - -/* implementation of Bresenham's line algorithm - TODO: thickness, might need better math library */ -line := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA, thickness: int): void { - if @inline(math.abs, p1.y - p0.y) < @inline(math.abs, p1.x - p0.x) { - if p0.x > p1.x { - @inline(line_low, buffer, p1, p0, color) - } else { - @inline(line_low, buffer, p0, p1, color) - } - } else { - if p0.y > p1.y { - @inline(line_high, buffer, p1, p0, color) - } else { - @inline(line_high, buffer, p0, p1, color) - } - } - return -} - -// theoretically draws a wireframe polygon to the screen. untested. -tri_line := fn(buffer: Buffer, p0: Point, p1: Point, p2: Point, color: ColorBGRA, thickness: int): void { - line(buffer, p0, p1, color, thickness) - line(buffer, p1, p2, color, thickness) - line(buffer, p2, p0, color, thickness) - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/amogus.hb b/sysdata/programs/fb_driver/src/examples/amogus.hb deleted file mode 100644 index b045f471..00000000 --- a/sysdata/programs/fb_driver/src/examples/amogus.hb +++ /dev/null @@ -1,26 +0,0 @@ -.{rect_line} := @use("../draw.hb"); -.{present, create_buffer, clear} := @use("../lib.hb") - -/* expected result: - the impostor travels left and loops around the screen */ - -example := fn(): void { - // Creates a back buffer, which we write to, to avoid screen flickering - buffer := create_buffer() - x := 0 - loop { - // draw all our shapes to the back buffer - rect_line(buffer, .(200 - x, 80), .(430, 380), .(0, 0, 255, 0), 1) - rect_line(buffer, .(630 - x, 120), .(120, 300), .(0, 0, 255, 0), 1) - rect_line(buffer, .(200 - x, 460), .(160, 270), .(0, 0, 255, 0), 1) - rect_line(buffer, .(470 - x, 460), .(160, 270), .(0, 0, 255, 0), 1) - rect_line(buffer, .(140 - x, 140), .(340, 250), .(255, 255, 0, 0), 1) - /* push the back buffer to the front buffer - this displays our image to the screen */ - present(buffer) - // erase our old image - clear(buffer, .(0, 0, 0, 0)) - x += 1 - } - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/buffers.hb b/sysdata/programs/fb_driver/src/examples/buffers.hb deleted file mode 100644 index 41574089..00000000 --- a/sysdata/programs/fb_driver/src/examples/buffers.hb +++ /dev/null @@ -1,19 +0,0 @@ -.{front_buffer_ptr, front_buffer_copy, get_front_buffer, Buffer} := @use("../lib.hb"); - -example := fn(): void { - // you can get the raw frontbuffer pointer using - raw_buffer := front_buffer_ptr - // this buffer is the one that you write individual pixels to - - // you can gete the copy frontbuffer pointer using - copy_buffer := front_buffer_copy - /* this buffer is used for massive writing - operations by taking advantage of - static copying */ - - // you can construct a buffer like so - buffer := Buffer.{write: raw_buffer, copy: copy_buffer} - // this is the operation that get_front_buffer does - same_buffer := get_front_buffer() - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/colors.hb b/sysdata/programs/fb_driver/src/examples/colors.hb deleted file mode 100644 index 1d29d048..00000000 --- a/sysdata/programs/fb_driver/src/examples/colors.hb +++ /dev/null @@ -1,27 +0,0 @@ -.{clear, create_buffer, present} := @use("../lib.hb"); -.{ColorBGRA} := @use("../color.hb") - -/* expected result: - the screen fades from green to cyan - then wraps back to green - note that this may happen too fast for you to notice... */ - -example := fn(): void { - // creates a back buffer, which we write to, to avoid screen flickering - buffer := create_buffer() - color := ColorBGRA.(0, 255, 0, 255) - /* have to explicitly say 0 is a u8, or we do something crazy to the colors. - looks like a compiler bug */ - n := @as(u8, 0) - 1 - loop { - clear(buffer, color) - present(buffer) - /* because for some reason just comparing doesnt work. - also looks like a compiler bug */ - if (color.b & 255) == 255 | (color.b & 255) == 0 { - n = 0 - n - } - color.b += n - } - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/lines.hb b/sysdata/programs/fb_driver/src/examples/lines.hb deleted file mode 100644 index 11adde78..00000000 --- a/sysdata/programs/fb_driver/src/examples/lines.hb +++ /dev/null @@ -1,25 +0,0 @@ -.{line} := @use("../draw.hb"); -.{clear, create_buffer, present, FB_WIDTH, FB_HEIGHT, Point} := @use("../lib.hb") - -/* expected result: - a 3d-looking blue set of lines - created on a blue background */ - -example := fn(): void { - // creates a back buffer, which we write to, to avoid screen flickering - buffer := create_buffer() - // fill the screen in blue - clear(buffer, .(100, 50, 0, 255)) - p0 := Point.(0, 0 - 1) - p1 := Point.(0, FB_HEIGHT - 1) - loop if p0.y >= FB_HEIGHT break else { - // draw a line between p0 and p1 - line(buffer, p0, p1, .(255, 180, 100, 255), 3) - p0.y += FB_HEIGHT >> 6 - p1.x += FB_WIDTH >> 6 - } - /* push the back buffer to the front buffer - this displays our image to the screen */ - present(buffer) - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/random.hb b/sysdata/programs/fb_driver/src/examples/random.hb deleted file mode 100644 index 75ecb818..00000000 --- a/sysdata/programs/fb_driver/src/examples/random.hb +++ /dev/null @@ -1,17 +0,0 @@ -.{clear, get_front_buffer, screenidx} := @use("../lib.hb"); -.{ColorBGRA} := @use("../color.hb"); -.{random} := @use("../../../../libraries/stn/src/lib.hb") - -example := fn(): void { - buffer := get_front_buffer() - clear(buffer) - loop { - x := random.integer(0, 1024) - y := random.integer(0, 768) - r := random.integer(0, 255) - g := random.integer(0, 75) - b := random.integer(0, 155); - *(buffer.write + @inline(screenidx, .(x, y))) = ColorBGRA.(b, g, r, 255) - } - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/square.hb b/sysdata/programs/fb_driver/src/examples/square.hb deleted file mode 100644 index 84b39948..00000000 --- a/sysdata/programs/fb_driver/src/examples/square.hb +++ /dev/null @@ -1,32 +0,0 @@ -.{rect_line} := @use("../draw.hb"); -.{clear, create_buffer, present, Point, FB_HEIGHT, FB_WIDTH} := @use("../lib.hb") - -/* expected result: - the white outline of a square bounces around the screen */ - -example := fn(): void { - // creates a back buffer, which we write to, to avoid screen flickering - buffer := create_buffer() - vel := Point.{x: 1, y: 1} - pos := Point.{x: 100, y: 100} - loop { - // draw the square at our current position - rect_line(buffer, pos, .(100, 100), .(255, 255, 255, 255), 3) - /* push the back buffer to the front buffer - this displays our image to the screen */ - present(buffer) - // erase our old image - clear(buffer, .(0, 0, 0, 0)) - - // bounce the square if it touches the screen edges - if pos.x == 0 | pos.x == FB_WIDTH - 100 { - vel.x = 0 - vel.x - } - if pos.y == 0 | pos.y == FB_HEIGHT - 100 { - vel.y = 0 - vel.y - } - - pos += vel - } - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/examples/strobe.hb b/sysdata/programs/fb_driver/src/examples/strobe.hb deleted file mode 100644 index e46653c6..00000000 --- a/sysdata/programs/fb_driver/src/examples/strobe.hb +++ /dev/null @@ -1,20 +0,0 @@ -.{clear, create_buffer, present} := @use("../lib.hb") - -/* expected result: (EPILEPSY WARNING) - the screen rapidly flashes red then black */ - -example := fn(): void { - // creates a back buffer, which we write to, to avoid screen flickering - buffer := create_buffer() - loop { - // screen go red - clear(buffer, .(0, 0, 255, 0)) - // show the red - present(buffer) - // screen go black - clear(buffer, .(0, 255, 255, 0)) - // show the black - present(buffer) - } - return -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/lib.hb b/sysdata/programs/fb_driver/src/lib.hb deleted file mode 100644 index ca91a630..00000000 --- a/sysdata/programs/fb_driver/src/lib.hb +++ /dev/null @@ -1,88 +0,0 @@ -.{memory, math} := @use("../../../libraries/stn/src/lib.hb"); -.{ColorBGRA, blend} := @use("rel:color.hb") - -FB_WIDTH := 1024 -FB_HEIGHT := 768 -FB_PIXELS := FB_WIDTH * FB_HEIGHT -FB_BYTES := FB_PIXELS << 2 -// actual enforced max copy size is 0xFFFF, but this was faster -MAX_COPY_SIZE := 0x1800 -COPY_PIXELS := math.min(MAX_COPY_SIZE, FB_BYTES) >> 2 -PARTITIONS := FB_PIXELS / COPY_PIXELS -TOTAL_PAGES := 1 + FB_BYTES >> 12 - -Buffer := struct {write: ^ColorBGRA, copy: ^[ColorBGRA; COPY_PIXELS]} -Point := struct {x: int, y: int} -Transform := struct {width: int, height: int} - -front_buffer_ptr := @as(^ColorBGRA, @bitcast(0xFFFF8000C0000000)) -front_buffer_copy := @as(^[ColorBGRA; COPY_PIXELS], @bitcast(front_buffer_ptr)) - -get_front_buffer := fn(): Buffer { - // trying to return front_buffer_ptr or front_buffer_copy causes reg id leak - buffer := Buffer.{write: front_buffer_ptr, copy: front_buffer_copy} - return buffer -} -/* this is separate to create_raw_buffer because returning a Buffer from - create_raw_buffer causes reg id leak */ -create_buffer := fn(): Buffer { - ptr := @inline(create_raw_buffer) - buffer := Buffer.{write: ptr, copy: @as(^[ColorBGRA; COPY_PIXELS], @bitcast(ptr))} - return buffer -} -create_raw_buffer := fn(): ^ColorBGRA { - if TOTAL_PAGES <= 0xFF { - return @bitcast(@inline(memory.request_page, TOTAL_PAGES)) - } - ptr := @inline(memory.request_page, 255) - remaining := TOTAL_PAGES - 0xFF - loop if remaining <= 0 break else { - if remaining < 0xFF { - memory.request_page(remaining) - } else { - memory.request_page(0xFF) - } - remaining -= 0xFF - } - return @bitcast(ptr) -} -// sets the buffer to the color. very fast. -clear := fn(buffer: Buffer, color: ColorBGRA): void { - n := 0 - // write the first pixel chunk - loop if n >= COPY_PIXELS break else { - *(buffer.write + n) = color - n += 1 - } - n = 1 - // copy that pixel chunk through the buffer, taking advantage of memory copying - loop if n >= PARTITIONS break else { - *(buffer.copy + n) = *buffer.copy - n += 1 - } - return -} -// only required to be called when using a back buffer. if using single-buffered rendering, do not call this. -present := fn(buffer: Buffer): void { - n := 0 - // copy chunks of the read buffer to the front buffer - loop if n >= PARTITIONS break else { - *(front_buffer_copy + n) = *(buffer.copy + n) - n += 1 - } - return -} -// composites the contents of buffer1 into buffer2, accounting for alpha transparency -// i dont know if it works. i have not tested it. it probably doesnt work -composite := fn(buffer1: Buffer, buffer2: Buffer): void { - n := 0 - loop if n == FB_PIXELS break else { - bg := *(buffer2.write + n); - *(buffer2.write + n) = blend(*(buffer1.write + n), bg) - n += 1 - } - return -} -screenidx := fn(pos: Point): int { - return pos.x + FB_WIDTH * pos.y -} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/meta.toml b/sysdata/programs/render_driver/meta.toml similarity index 71% rename from sysdata/programs/fb_driver/meta.toml rename to sysdata/programs/render_driver/meta.toml index c2659bca..95bd66f0 100644 --- a/sysdata/programs/fb_driver/meta.toml +++ b/sysdata/programs/render_driver/meta.toml @@ -1,6 +1,6 @@ [package] -name = "fb_driver" -authors = ["able", "aurlex"] +name = "render_driver" +authors = ["koniifer"] [dependants.libraries] diff --git a/sysdata/programs/render_driver/src/main.hb b/sysdata/programs/render_driver/src/main.hb new file mode 100644 index 00000000..a92a5375 --- /dev/null +++ b/sysdata/programs/render_driver/src/main.hb @@ -0,0 +1,6 @@ +render := @use("../../../libraries/render/src/lib.hb") + +main := fn(): void { + @inline(render.init) + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/meta.toml b/sysdata/programs/render_example/meta.toml new file mode 100644 index 00000000..4712b537 --- /dev/null +++ b/sysdata/programs/render_example/meta.toml @@ -0,0 +1,11 @@ +[package] +name = "render_example" +authors = ["koniifer"] + +[dependants.libraries] + +[dependants.binaries] +hblang.version = "1.0.0" + +[build] +command = "hblang src/main.hb" diff --git a/sysdata/programs/render_example/src/examples/amogus.hb b/sysdata/programs/render_example/src/examples/amogus.hb new file mode 100644 index 00000000..77feba73 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/amogus.hb @@ -0,0 +1,19 @@ +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: + the impostor travels left and loops around the screen */ + +example := fn(): void { + x := 0 + loop { + render.put_rect(.(200 - x, 80), .(430, 380), render.red) + render.put_rect(.(630 - x, 120), .(120, 300), render.red) + render.put_rect(.(200 - x, 460), .(160, 270), render.red) + render.put_rect(.(470 - x, 460), .(160, 270), render.red) + render.put_rect(.(140 - x, 140), .(340, 250), render.cyan) + render.sync() + render.clear(render.black) + x += 1 + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/colors.hb b/sysdata/programs/render_example/src/examples/colors.hb new file mode 100644 index 00000000..b357d629 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/colors.hb @@ -0,0 +1,20 @@ +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: + the screen fades from cyan to green + then wraps back to cyan + note that this may happen too fast for you to notice... */ + +example := fn(): void { + color := render.light_cyan + n := @as(u8, 1) + loop { + render.clear(color) + render.sync() + if (color.b & 255) == 255 | (color.b & 255) == 0 { + n = 0 - n + } + color.b += n + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/lines.hb b/sysdata/programs/render_example/src/examples/lines.hb new file mode 100644 index 00000000..bd345f5c --- /dev/null +++ b/sysdata/programs/render_example/src/examples/lines.hb @@ -0,0 +1,20 @@ +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: + a 3d-looking set of blue lines + created on a blue background */ + +example := fn(): void { + render.clear(.(100, 50, 0, 255)) + width := render.screen_width() + height := render.screen_height() + p0 := render.IVec2.(0, 0 - 1) + p1 := render.IVec2.(0, height - 1) + loop if p0.y >= height break else { + render.put_line(p0, p1, .(255, 180, 100, 255)) + p0.y += height >> 6 + p1.x += width >> 6 + } + render.sync() + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/random.hb b/sysdata/programs/render_example/src/examples/random.hb new file mode 100644 index 00000000..5f8d982c --- /dev/null +++ b/sysdata/programs/render_example/src/examples/random.hb @@ -0,0 +1,16 @@ +.{random} := @use("../../../../libraries/stn/src/lib.hb") +render := @use("../../../../libraries/render/src/lib.hb") + +example := fn(): void { + render.clear(render.black) + loop { + x := random.integer_range(0, 1024) + y := random.integer_range(0, 768) + r := random.integer_range(0, 255) + g := random.integer_range(0, 75) + b := random.integer_range(0, 155) + render.put_pixel(.(x, y), .(b, g, r, 255)) + render.sync() + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/square.hb b/sysdata/programs/render_example/src/examples/square.hb new file mode 100644 index 00000000..975387bc --- /dev/null +++ b/sysdata/programs/render_example/src/examples/square.hb @@ -0,0 +1,26 @@ +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: + the white outline of a square bounces around the screen */ + +example := fn(): void { + vel := render.IVec2.(1, 1) + pos := render.IVec2.(100, 100) + width := render.screen_width() + height := render.screen_height() + loop { + render.put_rect(pos, .(100, 100), render.white) + render.sync() + render.clear(render.black) + + if pos.x == 0 | pos.x == width - 100 { + vel.x = 0 - vel.x + } + if pos.y == 0 | pos.y == height - 100 { + vel.y = 0 - vel.y + } + + pos += vel + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/strobe.hb b/sysdata/programs/render_example/src/examples/strobe.hb new file mode 100644 index 00000000..e3d0b498 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/strobe.hb @@ -0,0 +1,14 @@ +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: (EPILEPSY WARNING) + the screen rapidly flashes red then black */ + +example := fn(): void { + loop { + render.clear(render.red) + render.sync() + render.clear(render.yellow) + render.sync() + } + return +} \ No newline at end of file diff --git a/sysdata/programs/fb_driver/src/main.hb b/sysdata/programs/render_example/src/main.hb similarity index 67% rename from sysdata/programs/fb_driver/src/main.hb rename to sysdata/programs/render_example/src/main.hb index e1c71c26..63d63909 100644 --- a/sysdata/programs/fb_driver/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1,6 +1,6 @@ .{example} := @use("./examples/lines.hb") -main := fn(): int { +main := fn(): void { @inline(example) - return 0 + return } \ No newline at end of file diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index ee0625ca..52fb1875 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -20,14 +20,17 @@ resolution = "1024x768x24" # [boot.limine.ableos.modules.tests] # path = "boot:///tests.hbf" +[boot.limine.ableos.modules.0render_driver] +path = "boot:///render_driver.hbf" + [boot.limine.ableos.modules.a_serial_driver] path = "boot:///a_serial_driver.hbf" [boot.limine.ableos.modules.diskio_driver] path = "boot:///diskio_driver.hbf" -[boot.limine.ableos.modules.fb_driver] -path = "boot:///fb_driver.hbf" +[boot.limine.ableos.modules.render_example] +path = "boot:///render_example.hbf" [boot.limine.ableos.modules.serial_driver_test] path = "boot:///serial_driver_test.hbf"