sorting the command buffer

This commit is contained in:
Alessandro Mauri 2025-06-03 22:03:14 +02:00
parent c9b74aebc7
commit ac3fcae649
6 changed files with 69 additions and 32 deletions

View File

@ -1,8 +1,10 @@
module fifo::faults;
faultdef FULL, EMPTY;
module fifo{Type};
import std::core::mem;
faultdef FULL, EMPTY;
import std::sort;
// TODO: specify the allocator
@ -27,7 +29,7 @@ fn void Fifo.free(&fifo)
fn void? Fifo.enqueue(&fifo, Type *elem)
{
if (fifo.count >= fifo.arr.len) {
return FULL?;
return fifo::faults::FULL?;
}
usz in = (fifo.out + fifo.count) % fifo.arr.len;
fifo.arr[in] = *elem;
@ -37,7 +39,7 @@ fn void? Fifo.enqueue(&fifo, Type *elem)
fn Type*? Fifo.dequeue(&fifo)
{
if (fifo.count == 0) {
return EMPTY?;
return fifo::faults::EMPTY?;
}
Type *ret = &fifo.arr[fifo.out];
fifo.count--;
@ -64,3 +66,26 @@ macro usz Fifo.len(&fifo) @operator(len)
{
return fifo.count;
}
fn void? Fifo.sort(&fifo)
{
Type[] arr = mem::new_array(Type, fifo.count);
defer mem::free(arr);
foreach(i, c: fifo) {
arr[i] = c;
}
// doesn't keep ordering
//sort::quicksort(arr);
// seems to keep the right order but we will never know...
// also since most things are already ordered the time is closer to O(n) than to O(n^2)
sort::insertionsort(arr);
fifo.count = 0;
fifo.out = 0;
foreach (&c: arr) {
fifo.enqueue(c)!;
}
}

View File

@ -49,6 +49,12 @@ struct Cmd (Printable) {
}
}
fn int Cmd.compare_to(Cmd a, Cmd b)
{
if (a.z_index == b.z_index) return 0;
return a.z_index > b.z_index ? 1 : -1;
}
// implement the Printable interface
fn usz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
{

View File

@ -293,7 +293,7 @@ $if DEBUG == 1:
// draw mouse position
Cmd cmd = {
.type = CMD_RECT,
.z_index = int.max, // hopefully over everything else
.z_index = int.max-1, // hopefully over everything else
.rect.rect = {
.x = ctx.input.mouse.pos.x - 2,
.y = ctx.input.mouse.pos.y - 2,
@ -304,11 +304,16 @@ $if DEBUG == 1:
};
ctx.cmd_queue.enqueue(&cmd)!;
// dump the command buffer
io::printn("Command Buffer Dump:");
foreach(idx, c: ctx.cmd_queue) {
io::printfn("\t [%d] = {%s}", idx, c);
}
// dump the command buffer
// io::printn("Command Buffer Dump:");
// foreach(idx, c: ctx.cmd_queue) {
// io::printfn("\t [%d] = {%s}", idx, c);
// }
ctx.cmd_queue.sort()!;
// io::printn("Sorted Command Buffer Dump:");
// foreach(idx, c: ctx.cmd_queue) {
// io::printfn("\t [%d] = {%s}", idx, c);
// }
$endif
}

View File

@ -48,7 +48,6 @@ fn void? Ctx.div_begin(&ctx, String label, Rect size, bool scroll_x = false, boo
elem.div.scroll_x.enabled = scroll_x;
elem.div.scroll_y.enabled = scroll_y;
elem.div.z_index = parent.div.z_index + 1;
io::printn(elem.div.z_index);
// 2. layout the element
Rect wanted_size = {

View File

@ -112,8 +112,8 @@ fn void Ctx.input_mouse_button(&ctx, MouseButtons buttons)
// Mouse was moved, report absolute position
fn void Ctx.input_mouse_abs(&ctx, short x, short y)
{
ctx.input.mouse.pos.x = math::clamp(x, 0u16, ctx.width);
ctx.input.mouse.pos.y = math::clamp(y, 0u16, ctx.height);
ctx.input.mouse.pos.x = math::clamp(x, (short)0, ctx.width);
ctx.input.mouse.pos.y = math::clamp(y, (short)0, ctx.height);
short dx, dy;
dx = x - ctx.input.mouse.pos.x;
@ -135,8 +135,8 @@ fn void Ctx.input_mouse_delta(&ctx, short dx, short dy)
mx = ctx.input.mouse.pos.x + dx;
my = ctx.input.mouse.pos.y + dy;
ctx.input.mouse.pos.x = math::clamp(mx, 0u16, ctx.width);
ctx.input.mouse.pos.y = math::clamp(my, 0u16, ctx.height);
ctx.input.mouse.pos.x = math::clamp(mx, (short)0, ctx.width);
ctx.input.mouse.pos.y = math::clamp(my, (short)0, ctx.height);
ctx.input.events.mouse_move = dx != 0 || dy != 0;
}

View File

@ -1,3 +1,6 @@
module vtree::faults;
faultdef CANNOT_SHRINK, INVALID_REFERENCE, TREE_FULL, REFERENCE_NOT_PRESENT, INVALID_ARGUMENT;
module vtree{ElemType};
import std::core::mem;
@ -9,7 +12,6 @@ struct VTree {
isz[] refs, ordered_refs;
}
faultdef CANNOT_SHRINK, INVALID_REFERENCE, TREE_FULL, REFERENCE_NOT_PRESENT, INVALID_ARGUMENT;
macro VTree.ref_is_valid(&tree, isz ref) { return (ref >= 0 && ref < tree.refs.len); }
macro VTree.ref_is_present(&tree, isz ref) { return tree.refs[ref] >= 0; }
@ -88,14 +90,14 @@ fn void? VTree.resize(&tree, usz newsize)
{
// return error when shrinking with too many elements
if (newsize < tree.elements) {
return CANNOT_SHRINK?;
return vtree::faults::CANNOT_SHRINK?;
}
// pack the vector when shrinking to avoid data loss
if ((int)newsize < tree.size()) {
// FIXME: packing destroys all references to elements of vec
// so shrinking may cause dangling pointers
return CANNOT_SHRINK?;
return vtree::faults::CANNOT_SHRINK?;
}
usz old_size = tree.size();
@ -120,18 +122,18 @@ fn isz? VTree.add(&tree, ElemType elem, isz parent)
{
// invalid parent
if (!tree.ref_is_valid(parent)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
// no space left
if (tree.elements >= tree.size()) {
return TREE_FULL?;
return vtree::faults::TREE_FULL?;
}
// check if the parent exists
// if there are no elements in the tree the first add will set the root
if (!tree.ref_is_present(parent) && tree.elements != 0) {
return REFERENCE_NOT_PRESENT?;
return vtree::faults::REFERENCE_NOT_PRESENT?;
}
// get the first free spot
@ -143,7 +145,7 @@ fn isz? VTree.add(&tree, ElemType elem, isz parent)
}
}
if (free_spot < 0) {
return TREE_FULL?;
return vtree::faults::TREE_FULL?;
}
// finally add the element
@ -159,7 +161,7 @@ fn isz? VTree.add(&tree, ElemType elem, isz parent)
fn usz? VTree.prune(&tree, isz ref)
{
if (!tree.ref_is_valid(ref)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
if (!tree.ref_is_present(ref)) {
@ -193,7 +195,7 @@ fn usz VTree.nuke(&tree)
fn usz? VTree.subtree_size(&tree, isz ref)
{
if (!tree.ref_is_valid(ref)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
if (!tree.ref_is_present(ref)) {
@ -215,17 +217,17 @@ fn usz? VTree.subtree_size(&tree, isz ref)
fn isz? VTree.children_it(&tree, isz parent, isz *cursor)
{
if (cursor == null) {
return INVALID_ARGUMENT?;
return vtree::faults::INVALID_ARGUMENT?;
}
// if the cursor is out of bounds then we are done for sure
if (!tree.ref_is_valid(*cursor)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
// same for the parent, if it's invalid it can't have children
if (!tree.ref_is_valid(parent) || !tree.ref_is_present(parent)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
// find the first child, update the cursor and return the ref
@ -253,7 +255,7 @@ fn isz? VTree.children_it(&tree, isz parent, isz *cursor)
fn isz? VTree.level_order_it(&tree, isz ref, isz *cursor)
{
if (cursor == null) {
return INVALID_ARGUMENT?;
return vtree::faults::INVALID_ARGUMENT?;
}
isz[] queue = tree.ordered_refs;
@ -300,11 +302,11 @@ fn isz? VTree.level_order_it(&tree, isz ref, isz *cursor)
fn isz? VTree.parentof(&tree, isz ref)
{
if (!tree.ref_is_valid(ref)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
if (!tree.ref_is_present(ref)) {
return REFERENCE_NOT_PRESENT?;
return vtree::faults::REFERENCE_NOT_PRESENT?;
}
return tree.refs[ref];
@ -313,11 +315,11 @@ fn isz? VTree.parentof(&tree, isz ref)
fn ElemType? VTree.get(&tree, isz ref)
{
if (!tree.ref_is_valid(ref)) {
return INVALID_REFERENCE?;
return vtree::faults::INVALID_REFERENCE?;
}
if (!tree.ref_is_present(ref)) {
return REFERENCE_NOT_PRESENT?;
return vtree::faults::REFERENCE_NOT_PRESENT?;
}
return tree.vector[ref];