ableos/sysdata/libraries/render/src/software.hb

264 lines
6.8 KiB
Plaintext
Raw Normal View History

.{math, memory, dt} := @use("../../stn/src/lib.hb");
2024-10-14 19:24:29 -05:00
.{Color, Surface, new_surface} := @use("lib.hb");
2024-10-12 15:39:09 -05:00
.{Vec2} := math
2024-09-13 16:41:31 -05:00
2024-10-14 19:24:29 -05:00
framebuffer := @as(^Color, idk)
// init := fn(): void {
// width := dt.get(int, "framebuffer/fb0/width\0")
// height := dt.get(int, "framebuffer/fb0/height\0")
// pixels := width * height
// back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
// ctx = Context.{
// fb: dt.get(^Color, "framebuffer/fb0/ptr\0"),
// bb: back_buffer,
// buf: back_buffer,
// width,
// height,
// pixels,
// double_buffer: true,
// }
// return
// }
init := fn(double_buffer: bool): Surface {
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
width := dt.get(int, "framebuffer/fb0/width\0")
height := dt.get(int, "framebuffer/fb0/height\0")
2024-10-14 19:24:29 -05:00
if double_buffer {
return new_surface(width, height)
2024-09-13 16:41:31 -05:00
} else {
2024-10-14 19:24:29 -05:00
return .(framebuffer, width, height)
2024-09-13 16:41:31 -05:00
}
}
2024-10-14 19:24:29 -05:00
clear := fn(surface: Surface, color: Color): void {
return @inline(memory.set, Color, &color, surface.buf, @bitcast(surface.width * surface.height))
2024-09-13 16:41:31 -05:00
}
2024-10-14 19:24:29 -05:00
sync := fn(surface: Surface): void {
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
2024-09-13 16:41:31 -05:00
}
2024-10-14 19:24:29 -05:00
screenidx := fn(surface: Surface, x: int, y: int): int {
return x + surface.width * y
2024-09-13 16:41:31 -05:00
}
2024-10-14 19:24:29 -05:00
put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void {
*(surface.buf + @inline(screenidx, surface, pos.x, pos.y)) = color
2024-09-13 16:41:31 -05:00
return
}
2024-10-14 19:24:29 -05:00
// put_filled_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)
// loop if start_idx >= end_idx break else {
// @inline(memory.set, Color, &color, surface.buf + start_idx, @bitcast(tr.x))
// start_idx += surface.width
// }
// return
// }
put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
top_start_idx := @inline(screenidx, surface, pos.x, pos.y)
bottom_start_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y / 2
top_cursor := 0
bottom_cursor := (tr.y - 1) * surface.width
i := 0
loop if i == rows_to_fill break else {
@inline(memory.set, Color, &color, surface.buf + top_start_idx, @bitcast(tr.x))
@inline(memory.set, Color, &color, surface.buf + bottom_start_idx, @bitcast(tr.x))
top_start_idx += surface.width
bottom_start_idx -= surface.width
i += 1
}
2024-10-13 19:31:23 -05:00
2024-10-14 19:24:29 -05:00
if tr.y % 2 != 0 {
middle_idx := @inline(screenidx, surface, pos.x, pos.y + rows_to_fill)
@inline(memory.set, Color, &color, surface.buf + middle_idx, @bitcast(tr.x))
2024-09-13 16:41:31 -05:00
}
2024-10-13 19:31:23 -05:00
2024-09-13 16:41:31 -05:00
return
}
2024-10-14 19:24:29 -05:00
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)
2024-10-13 19:31:23 -05:00
loop if start_idx > end_idx break else {
2024-10-14 19:24:29 -05:00
*(surface.buf + start_idx) = color;
*(surface.buf + right_start_idx) = color
start_idx += surface.width
right_start_idx += surface.width
2024-09-13 16:41:31 -05:00
}
2024-10-13 19:31:23 -05:00
2024-10-14 19:24:29 -05:00
@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))
2024-10-13 19:31:23 -05:00
2024-09-13 16:41:31 -05:00
return
}
2024-10-14 19:24:29 -05:00
put_line_low := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): void {
2024-09-13 16:41:31 -05:00
dx := p1.x - p0.x
dy := p1.y - p0.y
yi := 1
if dy < 0 {
yi = -1
dy = -dy
2024-09-13 16:41:31 -05:00
}
D := 2 * dy - dx
y := p0.y
x := p0.x
loop if x == p1.x break else {
2024-10-14 19:24:29 -05:00
*(surface.buf + @inline(screenidx, surface, x, y)) = color
2024-09-13 16:41:31 -05:00
if D > 0 {
y += yi
D += 2 * (dy - dx)
} else {
D += 2 * dy
}
x += 1
}
return
}
2024-10-14 19:24:29 -05:00
put_line_high := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): void {
2024-09-13 16:41:31 -05:00
dx := p1.x - p0.x
dy := p1.y - p0.y
xi := 1
if dy < 0 {
xi = -1
dx = -dx
2024-09-13 16:41:31 -05:00
}
D := 2 * dx - dy
x := p0.x
y := p0.y
loop if y == p1.y break else {
2024-10-14 19:24:29 -05:00
*(surface.buf + @inline(screenidx, surface, x, y)) = color
2024-09-13 16:41:31 -05:00
if D > 0 {
x += xi
D += 2 * (dx - dy)
} else {
D += 2 * dx
}
y += 1
}
return
}
2024-10-14 19:24:29 -05:00
put_line := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): void {
2024-10-12 15:39:09 -05:00
if math.abs(int, p1.y - p0.y) < math.abs(int, p1.x - p0.x) {
2024-09-13 16:41:31 -05:00
if p0.x > p1.x {
2024-10-14 19:24:29 -05:00
@inline(put_line_low, surface, p1, p0, color)
2024-09-13 16:41:31 -05:00
} else {
2024-10-14 19:24:29 -05:00
@inline(put_line_low, surface, p0, p1, color)
2024-09-13 16:41:31 -05:00
}
} else {
if p0.y > p1.y {
2024-10-14 19:24:29 -05:00
@inline(put_line_high, surface, p1, p0, color)
2024-09-13 16:41:31 -05:00
} else {
2024-10-14 19:24:29 -05:00
@inline(put_line_high, surface, p0, p1, color)
2024-09-13 16:41:31 -05:00
}
}
return
}
2024-10-14 19:24:29 -05:00
// put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void {
// start_idx := @inline(screenidx, surface, pos.x, pos.y)
// end_idx := @inline(screenidx, surface, pos.x, pos.y + top.height)
// cursor := top.width * top.height
// loop if start_idx >= end_idx break else {
// @inline(memory.copy, Color, top.buf + cursor, surface.buf + start_idx, @intcast(top.width))
// start_idx += surface.width
// cursor -= top.width
// }
// return
// }
put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void {
top_start_idx := @inline(screenidx, surface, pos.x, pos.y)
bottom_start_idx := @inline(screenidx, surface, pos.x, pos.y + top.height - 1)
rows_to_copy := top.height / 2
top_cursor := 0
bottom_cursor := top.width * (top.height - 1)
i := 0
loop if i == rows_to_copy break else {
@inline(memory.copy, Color, top.buf + top_cursor, surface.buf + top_start_idx, @intcast(top.width))
@inline(memory.copy, Color, top.buf + bottom_cursor, surface.buf + bottom_start_idx, @intcast(top.width))
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += top.width
bottom_cursor -= top.width
i += 1
}
2024-10-13 19:31:23 -05:00
2024-10-14 19:24:29 -05:00
if top.height % 2 != 0 {
middle_idx := @inline(screenidx, surface, pos.x, pos.y + rows_to_copy)
@inline(memory.copy, Color, top.buf + top_cursor, surface.buf + middle_idx, @intcast(top.width))
}
2024-10-14 19:24:29 -05:00
return
}
// peony-made
2024-10-14 19:24:29 -05:00
put_trirect := fn(surface: Surface, pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void {
step := Vec2(int).(1, 1)
if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y = size.y / size.x
}
start_y := pos.y
target := pos + size
loop if pos.x == target.x break else {
2024-10-14 19:24:29 -05:00
put_vline(surface, pos.x, pos.y, target.y, color0)
@inline(put_vline, surface, pos.x, pos.y, start_y, color1)
pos += step
}
return
}
// peony-made
2024-10-14 19:24:29 -05:00
put_vline := fn(surface: Surface, x: int, y0: int, y1: int, color: Color): void {
if y1 < y0 {
tmp := y0
y0 = y1
y1 = tmp
}
y := y0
loop if y == y1 break else {
2024-10-14 19:24:29 -05:00
*(surface.buf + @inline(screenidx, surface, x, y)) = color
y += 1
}
return
}
// peony-made
2024-10-14 19:24:29 -05:00
put_hline := fn(surface: Surface, y: int, x0: int, x1: int, color: Color): void {
if x1 < x0 {
tmp := x0
x0 = x1
x1 = tmp
}
x := x0
loop if x == x1 break else {
2024-10-14 19:24:29 -05:00
*(surface.buf + @inline(screenidx, surface, x, y)) = color
x += 1
}
2024-09-13 16:41:31 -05:00
return
}