reimplement fb_driver as software render interface. sufficiently jank double buffering implementation waiting on an intelligent design.
This commit is contained in:
parent
63e2f546c5
commit
1031ca6314
9
sysdata/libraries/render/README.md
Normal file
9
sysdata/libraries/render/README.md
Normal file
|
@ -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)
|
43
sysdata/libraries/render/src/lib.hb
Normal file
43
sysdata/libraries/render/src/lib.hb
Normal file
|
@ -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}
|
199
sysdata/libraries/render/src/software.hb
Normal file
199
sysdata/libraries/render/src/software.hb
Normal file
|
@ -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
|
||||||
|
}
|
68
sysdata/libraries/render/src/svga.hb
Normal file
68
sysdata/libraries/render/src/svga.hb
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -1,14 +1,15 @@
|
||||||
SIZEOF_INT := 31
|
shift := 31
|
||||||
|
|
||||||
|
// following only work for: int
|
||||||
abs := fn(x: int): int {
|
abs := fn(x: int): int {
|
||||||
mask := x >> SIZEOF_INT
|
mask := x >> shift
|
||||||
return (x ^ mask) - mask
|
return (x ^ mask) - mask
|
||||||
}
|
}
|
||||||
min := fn(a: int, b: int): int {
|
min := fn(a: int, b: int): int {
|
||||||
c := a - b
|
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
|
c := a - b
|
||||||
return a - (c & c >> SIZEOF_INT)
|
return a - (c & c >> shift)
|
||||||
}
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
integer := fn(min: int, max: int): int {
|
integer := fn(): int {
|
||||||
rng := @eca(int, 3, 4)
|
return @eca(int, 3, 4)
|
||||||
|
}
|
||||||
if min != 0 | max != 0 {
|
|
||||||
return rng % (max - min + 1) + min
|
integer_range := fn(min: int, max: int): int {
|
||||||
}
|
return @eca(int, 3, 4) % (max - min + 1) + min
|
||||||
return rng
|
|
||||||
}
|
}
|
|
@ -1,2 +0,0 @@
|
||||||
# Framebuffer Driver
|
|
||||||
A simple framebuffer driver.
|
|
|
@ -1,7 +0,0 @@
|
||||||
color.blend
|
|
||||||
|
|
||||||
lib.composite
|
|
||||||
lib.screen2rect
|
|
||||||
lib.rect2screen
|
|
||||||
|
|
||||||
draw.tri_line
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "fb_driver"
|
name = "render_driver"
|
||||||
authors = ["able", "aurlex"]
|
authors = ["koniifer"]
|
||||||
|
|
||||||
[dependants.libraries]
|
[dependants.libraries]
|
||||||
|
|
6
sysdata/programs/render_driver/src/main.hb
Normal file
6
sysdata/programs/render_driver/src/main.hb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
render := @use("../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
|
main := fn(): void {
|
||||||
|
@inline(render.init)
|
||||||
|
return
|
||||||
|
}
|
11
sysdata/programs/render_example/meta.toml
Normal file
11
sysdata/programs/render_example/meta.toml
Normal file
|
@ -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"
|
19
sysdata/programs/render_example/src/examples/amogus.hb
Normal file
19
sysdata/programs/render_example/src/examples/amogus.hb
Normal file
|
@ -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
|
||||||
|
}
|
20
sysdata/programs/render_example/src/examples/colors.hb
Normal file
20
sysdata/programs/render_example/src/examples/colors.hb
Normal file
|
@ -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
|
||||||
|
}
|
20
sysdata/programs/render_example/src/examples/lines.hb
Normal file
20
sysdata/programs/render_example/src/examples/lines.hb
Normal file
|
@ -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
|
||||||
|
}
|
16
sysdata/programs/render_example/src/examples/random.hb
Normal file
16
sysdata/programs/render_example/src/examples/random.hb
Normal file
|
@ -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
|
||||||
|
}
|
26
sysdata/programs/render_example/src/examples/square.hb
Normal file
26
sysdata/programs/render_example/src/examples/square.hb
Normal file
|
@ -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
|
||||||
|
}
|
14
sysdata/programs/render_example/src/examples/strobe.hb
Normal file
14
sysdata/programs/render_example/src/examples/strobe.hb
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
.{example} := @use("./examples/lines.hb")
|
.{example} := @use("./examples/lines.hb")
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): void {
|
||||||
@inline(example)
|
@inline(example)
|
||||||
return 0
|
return
|
||||||
}
|
}
|
|
@ -20,14 +20,17 @@ resolution = "1024x768x24"
|
||||||
# [boot.limine.ableos.modules.tests]
|
# [boot.limine.ableos.modules.tests]
|
||||||
# path = "boot:///tests.hbf"
|
# path = "boot:///tests.hbf"
|
||||||
|
|
||||||
|
[boot.limine.ableos.modules.0render_driver]
|
||||||
|
path = "boot:///render_driver.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.a_serial_driver]
|
[boot.limine.ableos.modules.a_serial_driver]
|
||||||
path = "boot:///a_serial_driver.hbf"
|
path = "boot:///a_serial_driver.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.diskio_driver]
|
[boot.limine.ableos.modules.diskio_driver]
|
||||||
path = "boot:///diskio_driver.hbf"
|
path = "boot:///diskio_driver.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.fb_driver]
|
[boot.limine.ableos.modules.render_example]
|
||||||
path = "boot:///fb_driver.hbf"
|
path = "boot:///render_example.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.serial_driver_test]
|
[boot.limine.ableos.modules.serial_driver_test]
|
||||||
path = "boot:///serial_driver_test.hbf"
|
path = "boot:///serial_driver_test.hbf"
|
||||||
|
|
Loading…
Reference in a new issue