forked from koniifer/ableos
Merge pull request 'fb driver' (#16) from aurlex/ableos-framebuffer:master into master
Reviewed-on: https://git.ablecorp.us/AbleOS/ableos/pulls/16
This commit is contained in:
commit
db08a249e1
|
@ -336,8 +336,8 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||||
"-drive", "file=target/disk.img,format=raw",
|
"-drive", "file=target/disk.img,format=raw",
|
||||||
"-m", "4G",
|
"-m", "4G",
|
||||||
"-smp", "cores=4",
|
"-smp", "cores=4",
|
||||||
// "-enable-kvm",
|
"-enable-kvm",
|
||||||
"-cpu", "Broadwell-v4",
|
"-cpu", "host",
|
||||||
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04"
|
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04"
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
string := @use("rel:string.hb")
|
string := @use("rel:string.hb")
|
||||||
log := @use("rel:log.hb")
|
log := @use("rel:log.hb")
|
||||||
memory := @use("rel:memory.hb")
|
memory := @use("rel:memory.hb")
|
||||||
buffer := @use("rel:buffer.hb")
|
buffer := @use("rel:buffer.hb")
|
||||||
|
math := @use("rel:math.hb")
|
7
sysdata/libraries/stn/src/math.hb
Normal file
7
sysdata/libraries/stn/src/math.hb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
abs := fn(x: int): int {
|
||||||
|
mask := x >> 31
|
||||||
|
return (x ^ mask) - mask
|
||||||
|
}
|
||||||
|
min := fn(a: int, b: int): int {
|
||||||
|
return b + (a - b & a - b >> 31)
|
||||||
|
}
|
7
sysdata/programs/fb_driver/UNTESTED_FUNCTIONS
Normal file
7
sysdata/programs/fb_driver/UNTESTED_FUNCTIONS
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
color.blend
|
||||||
|
|
||||||
|
lib.composite
|
||||||
|
lib.screen2rect
|
||||||
|
lib.rect2screen
|
||||||
|
|
||||||
|
draw.tri_line
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "fb_driver"
|
name = "fb_driver"
|
||||||
authors = ["able"]
|
authors = ["able", "aurlex"]
|
||||||
|
|
||||||
[dependants.libraries]
|
[dependants.libraries]
|
||||||
|
|
||||||
|
|
27
sysdata/programs/fb_driver/src/color.hb
Normal file
27
sysdata/programs/fb_driver/src/color.hb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
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. -aurlex
|
||||||
|
blend := fn(fg: ColorBGRA, bg: ColorBGRA): ColorBGRA {
|
||||||
|
s := fg + bg
|
||||||
|
m := s - ((fg ^ bg) & 16843008) & 16843008
|
||||||
|
return (m >> 8 | 16777216 * (s < fg)) * 255 | s - m
|
||||||
|
}
|
113
sysdata/programs/fb_driver/src/draw.hb
Normal file
113
sysdata/programs/fb_driver/src/draw.hb
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
.{draw_pixel, screenidx, Transform, Point, Rect, Buffer, FB_WIDTH} := @use("rel:lib.hb")
|
||||||
|
ColorBGRA := @use("rel:color.hb").ColorBGRA
|
||||||
|
math := @use("../../../libraries/stn/src/lib.hb").math
|
||||||
|
|
||||||
|
/* 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 + 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 + pos.x + t + FB_WIDTH * y) = color;
|
||||||
|
*(buffer.write + pos.x + tr.width - t + FB_WIDTH * y) = color
|
||||||
|
y += 1
|
||||||
|
}
|
||||||
|
loop if x == pos.x + tr.width break else {
|
||||||
|
*(buffer.write + x + (pos.y + t) * FB_WIDTH) = color;
|
||||||
|
*(buffer.write + x + (pos.y + tr.height - t) * FB_WIDTH) = 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 + x + y * FB_WIDTH) = 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 + x + y * FB_WIDTH) = 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 math.abs(p1.y - p0.y) < math.abs(p1.x - p0.x) {
|
||||||
|
if p0.x > p1.x {
|
||||||
|
line_low(buffer, p1, p0, color)
|
||||||
|
} else {
|
||||||
|
line_low(buffer, p0, p1, color)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if p0.y > p1.y {
|
||||||
|
line_high(buffer, p1, p0, color)
|
||||||
|
} else {
|
||||||
|
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
|
||||||
|
}
|
26
sysdata/programs/fb_driver/src/examples/amogus.hb
Normal file
26
sysdata/programs/fb_driver/src/examples/amogus.hb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
.{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
|
||||||
|
}
|
27
sysdata/programs/fb_driver/src/examples/colors.hb
Normal file
27
sysdata/programs/fb_driver/src/examples/colors.hb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
.{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(i8, @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
|
||||||
|
}
|
19
sysdata/programs/fb_driver/src/examples/front_buffer.hb
Normal file
19
sysdata/programs/fb_driver/src/examples/front_buffer.hb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
.{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 := copy_buffer_ptr
|
||||||
|
/* 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
|
||||||
|
}
|
25
sysdata/programs/fb_driver/src/examples/lines.hb
Normal file
25
sysdata/programs/fb_driver/src/examples/lines.hb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
.{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
|
||||||
|
}
|
32
sysdata/programs/fb_driver/src/examples/square.hb
Normal file
32
sysdata/programs/fb_driver/src/examples/square.hb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
.{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
|
||||||
|
}
|
20
sysdata/programs/fb_driver/src/examples/strobe.hb
Normal file
20
sysdata/programs/fb_driver/src/examples/strobe.hb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
.{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
|
||||||
|
}
|
100
sysdata/programs/fb_driver/src/lib.hb
Normal file
100
sysdata/programs/fb_driver/src/lib.hb
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
.{memory, log, 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 (1 << 16) - 1, but this was faster
|
||||||
|
MAX_COPY_SIZE := 6144
|
||||||
|
// see stn.math.min, cant use here due to compiler bug (reg id leaked)
|
||||||
|
COPY_PIXELS := MAX_COPY_SIZE + (FB_BYTES - MAX_COPY_SIZE & FB_BYTES - MAX_COPY_SIZE >> 31) >> 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}
|
||||||
|
Rect := struct {p1: Point, p2: Point}
|
||||||
|
|
||||||
|
front_buffer_ptr := @as(^ColorBGRA, @bitcast(18446603339442421760))
|
||||||
|
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
|
||||||
|
return Buffer.{write: @as(^ColorBGRA, @bitcast(18446603339442421760)), copy: @as(^[ColorBGRA; COPY_PIXELS], @bitcast(18446603339442421760))}
|
||||||
|
}
|
||||||
|
/* this is separate to create_raw_buffer because returning a Buffer from
|
||||||
|
create_raw_buffer causes reg id leak */
|
||||||
|
create_buffer := fn(): Buffer {
|
||||||
|
ptr := create_raw_buffer()
|
||||||
|
ptr_copy := @as(^[ColorBGRA; COPY_PIXELS], @bitcast(ptr))
|
||||||
|
// same here, bitcasting inside the struct literal causes reg id leak
|
||||||
|
buffer := Buffer.{write: ptr, copy: ptr_copy}
|
||||||
|
return buffer
|
||||||
|
}
|
||||||
|
create_raw_buffer := fn(): ^ColorBGRA {
|
||||||
|
// helps to trace allocation bugs
|
||||||
|
log.info("Creating buffer. This will allocate.\0")
|
||||||
|
if TOTAL_PAGES <= 255 {
|
||||||
|
return @bitcast(memory.request_page(TOTAL_PAGES))
|
||||||
|
}
|
||||||
|
ptr := memory.request_page(255)
|
||||||
|
remaining := TOTAL_PAGES - 255
|
||||||
|
loop if remaining <= 0 break else {
|
||||||
|
if remaining < 255 {
|
||||||
|
memory.request_page(remaining)
|
||||||
|
} else {
|
||||||
|
memory.request_page(255)
|
||||||
|
}
|
||||||
|
remaining -= 255
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
offset := 0
|
||||||
|
// copy chunks of the read buffer to the front buffer
|
||||||
|
loop if offset >= PARTITIONS break else {
|
||||||
|
*(front_buffer_copy + offset) = *(buffer.copy + offset)
|
||||||
|
offset += 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
|
||||||
|
}
|
||||||
|
// really need to be able to inline this please - aurlex
|
||||||
|
screenidx := fn(pos: Point): int {
|
||||||
|
return pos.x + FB_WIDTH * pos.y
|
||||||
|
}
|
||||||
|
point2rect := fn(pos: Point, tr: Transform): Rect {
|
||||||
|
return .(pos, .(pos.x + tr.x, pos.y + tr.y))
|
||||||
|
}
|
||||||
|
rect2point := fn(rect: Rect): struct {point: Point, transform: Transform} {
|
||||||
|
return .(.(0, 0), .(0, 0))
|
||||||
|
}
|
|
@ -1,15 +1,7 @@
|
||||||
frame_buffer := @as(^u8, @bitcast(18446603339442421760))
|
// change "lines.hb" to another example to see it onscreen
|
||||||
|
example := @use("examples/lines.hb").example
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
color := 17
|
example()
|
||||||
loop {
|
|
||||||
len := 786432 * 4 + 1
|
|
||||||
loop if len == 0 break else {
|
|
||||||
fb := frame_buffer + len;
|
|
||||||
*fb = color
|
|
||||||
len -= 1
|
|
||||||
color += len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
Loading…
Reference in a new issue