forked from AbleOS/ableos
100 lines
3.3 KiB
Plaintext
100 lines
3.3 KiB
Plaintext
.{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))
|
|
} |