use std::collections::list instead of custom fifo

This commit is contained in:
Alessandro Mauri 2025-10-05 01:24:56 +02:00
parent d7cab085f7
commit 2bb907d523
4 changed files with 32 additions and 120 deletions

View File

@ -1,7 +1,7 @@
module ugui;
import std::ascii;
import std::io;
import std::collections::list;
// command type
enum CmdType {
@ -49,6 +49,10 @@ struct Cmd (Printable) {
}
}
// command queue
alias CmdQueue = list::List{Cmd};
fn int Cmd.compare_to(Cmd a, Cmd b)
{
if (a.z_index == b.z_index) return 0;
@ -87,21 +91,21 @@ macro bool cull_rect(Rect rect, Rect clip = {0,0,short.max,short.max})
}
// FIXME: this whole thing could be done at compile time, maybe
macro Ctx.push_cmd(&ctx, Cmd *cmd, int z_index)
macro Ctx.push_cmd(&ctx, Cmd cmd, int z_index)
{
cmd.z_index = z_index;
Rect rect;
switch (cmd.type) {
case CMD_RECT: rect = cmd.rect.rect;
case CMD_SPRITE: rect = cmd.sprite.rect;
default: return ctx.cmd_queue.enqueue(cmd);
default: return ctx.cmd_queue.push(cmd);
}
if (cull_rect(rect, ctx.div_scissor)) {
// println("NOPE: ", cmd.rect.rect, cmd.z_index);
// unreachable();
return;
}
return ctx.cmd_queue.enqueue(cmd);
return ctx.cmd_queue.push(cmd);
}
fn void? Ctx.push_scissor(&ctx, Rect rect, int z_index)
@ -110,10 +114,10 @@ fn void? Ctx.push_scissor(&ctx, Rect rect, int z_index)
.type = CMD_SCISSOR,
.scissor.rect = rect.intersection(ctx.div_scissor),
};
ctx.push_cmd(&sc, z_index)!;
ctx.push_cmd(sc, z_index);
}
fn void? Ctx.reset_scissor(&ctx, int z_index) => ctx.push_cmd(&&(Cmd){.type=CMD_SCISSOR,.scissor.rect=ctx.div_scissor}, z_index)!;
fn void? Ctx.reset_scissor(&ctx, int z_index) => ctx.push_cmd({.type=CMD_SCISSOR,.scissor.rect=ctx.div_scissor}, z_index);
fn void? Ctx.push_rect(&ctx, Rect rect, int z_index, Style* style)
{
@ -130,7 +134,7 @@ fn void? Ctx.push_rect(&ctx, Rect rect, int z_index, Style* style)
.rect.color = border_color,
.rect.radius = radius + border.x,
};
ctx.push_cmd(&cmd, z_index)!;
ctx.push_cmd(cmd, z_index);
}
Cmd cmd = {
@ -144,7 +148,7 @@ fn void? Ctx.push_rect(&ctx, Rect rect, int z_index, Style* style)
.rect.color = bg,
.rect.radius = radius,
};
ctx.push_cmd(&cmd, z_index)!;
ctx.push_cmd(cmd, z_index);
}
// TODO: accept a Sprite* instead of all this shit
@ -158,7 +162,7 @@ fn void? Ctx.push_sprite(&ctx, Rect bounds, Rect texture, Id texture_id, int z_i
.sprite.texture_id = texture_id,
.sprite.hue = hue,
};
ctx.push_cmd(&cmd, z_index)!;
ctx.push_cmd(cmd, z_index);
}
fn void? Ctx.push_update_atlas(&ctx, Atlas* atlas)
@ -174,7 +178,7 @@ fn void? Ctx.push_update_atlas(&ctx, Atlas* atlas)
},
};
// update the atlases before everything else
ctx.push_cmd(&up, -1)!;
ctx.push_cmd(up, -1);
}
macro Ctx.dbg_rect(&ctx, Rect r, uint c = 0xff000042u) => ctx.push_rect(r, int.max, &&(Style){.bg=c.to_rgba()})!!;

View File

@ -69,29 +69,25 @@ struct Elem {
}
}
const uint MAX_ELEMENTS = 256;
const uint MAX_COMMANDS = 2048;
const uint STACK_STEP = 10;
const uint ROOT_ID = 1;
const uint TEXT_MAX = 64;
// Tuple of Element pointers, used when it is useful to get both parent and child
alias PElemTuple = pair::Pair{Elem*, Elem*};
// relationships between elements are stored in a tree, it stores just the ids
alias IdTree = mtree::MTree{Id};
// elements themselves are kept in a cache
const uint MAX_ELEMENTS = 256;
alias ElemCache = cache::Cache{Id, Elem, MAX_ELEMENTS};
alias CmdQueue = fifo::Fifo{Cmd};
faultdef INVALID_SIZE, EVENT_UNSUPPORTED, WRONG_ELEMENT_TYPE, WRONG_ID;
const Rect DIV_FILL = { .x = 0, .y = 0, .w = 0, .h = 0 };
const uint STACK_STEP = 10;
const uint MAX_ELEMS = 128;
const uint MAX_CMDS = 2048;
const uint ROOT_ID = 1;
const uint TEXT_MAX = 64;
struct Ctx {
IdTree tree;
ElemCache cache;
@ -216,7 +212,7 @@ fn void? Ctx.init(&ctx, Allocator allocator)
ctx.cache.init(allocator)!;
defer catch { (void)ctx.cache.free(); }
ctx.cmd_queue.init(MAX_CMDS, allocator)!;
ctx.cmd_queue.init(allocator::mem, MAX_COMMANDS);
defer catch { (void)ctx.cmd_queue.free(); }
ctx.styles.init(allocator);
@ -311,13 +307,13 @@ $if $feature(DEBUG_POINTER):
},
.rect.color = 0xff00ffffu.to_rgba()
};
ctx.cmd_queue.enqueue(&cmd)!;
ctx.cmd_queue.push(cmd);
$endif
// sort the command buffer by the z-index
// FIXME: sorting the buffer fucks with scissor commands that have to be kept in place
// TODO: instead of sorting at the end perform ordered inserts into the command buffer
ctx.cmd_queue.sort()!;
//ctx.cmd_queue.sort()!;
// foreach (i, c: ctx.cmd_queue) {
// io::printf("[%d]: ", i);

View File

@ -1,93 +0,0 @@
module fifo::faults;
faultdef FULL, EMPTY;
module fifo{Type};
import std::core::mem;
import std::sort;
// TODO: specify the allocator
struct Fifo {
Allocator allocator;
Type[] arr;
usz out;
usz count;
}
fn void? Fifo.init(&fifo, usz size, Allocator allocator)
{
fifo.allocator = allocator;
fifo.arr = allocator::new_array(fifo.allocator, Type, size);
fifo.out = 0;
fifo.count = 0;
}
fn void Fifo.free(&fifo)
{
(void)allocator::free(fifo.allocator, fifo.arr);
}
fn void? Fifo.enqueue(&fifo, Type *elem)
{
if (fifo.count >= fifo.arr.len) {
return fifo::faults::FULL?;
}
usz in = (fifo.out + fifo.count) % fifo.arr.len;
fifo.arr[in] = *elem;
fifo.count++;
}
fn Type*? Fifo.dequeue(&fifo)
{
if (fifo.count == 0) {
return fifo::faults::EMPTY?;
}
Type *ret = &fifo.arr[fifo.out];
fifo.count--;
fifo.out = (fifo.out + 1) % fifo.arr.len;
return ret;
}
macro Type Fifo.get(&fifo, usz i) @operator([])
{
return fifo.arr[(fifo.out + i) % fifo.arr.len];
}
fn void Fifo.set(&fifo, usz i, Type val) @operator([]=)
{
fifo.arr[(fifo.out + i) % fifo.arr.len] = val;
}
macro Type* Fifo.get_ref(&fifo, usz i) @operator(&[])
{
return &fifo.arr[(fifo.out + i) % fifo.arr.len];
}
macro usz Fifo.len(&fifo) @operator(len)
{
return fifo.count;
}
fn void? Fifo.sort(&fifo)
{
Type[] arr = allocator::new_array(fifo.allocator, Type, fifo.count);
defer allocator::free(fifo.allocator, 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

@ -990,7 +990,12 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
uint calls = 0;
uint off;
for (Cmd* cmd; (cmd = queue.dequeue() ?? null) != null;) {
while (true) {
Cmd? cmd = queue.pop_first();
if (catch e = cmd) {
if (e != NO_MORE_ELEMENT) unreachable();
break;
}
switch (cmd.type) {
case CMD_UPDATE_ATLAS:
// TODO: verify the correct type
@ -1011,7 +1016,7 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
uint count = 1;
while (queue.len() != 0 && (queue.get(0).type == CMD_RECT || queue.get(0).type == CMD_SPRITE)) {
count++;
(void)queue.dequeue();
(void)queue.pop_first();
}
self.draw_quads(off, count);
off += count;