use std::collections::list instead of custom fifo
This commit is contained in:
parent
d7cab085f7
commit
2bb907d523
@ -1,7 +1,7 @@
|
|||||||
module ugui;
|
module ugui;
|
||||||
|
|
||||||
import std::ascii;
|
|
||||||
import std::io;
|
import std::io;
|
||||||
|
import std::collections::list;
|
||||||
|
|
||||||
// command type
|
// command type
|
||||||
enum CmdType {
|
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)
|
fn int Cmd.compare_to(Cmd a, Cmd b)
|
||||||
{
|
{
|
||||||
if (a.z_index == b.z_index) return 0;
|
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
|
// 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;
|
cmd.z_index = z_index;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
switch (cmd.type) {
|
switch (cmd.type) {
|
||||||
case CMD_RECT: rect = cmd.rect.rect;
|
case CMD_RECT: rect = cmd.rect.rect;
|
||||||
case CMD_SPRITE: rect = cmd.sprite.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)) {
|
if (cull_rect(rect, ctx.div_scissor)) {
|
||||||
// println("NOPE: ", cmd.rect.rect, cmd.z_index);
|
// println("NOPE: ", cmd.rect.rect, cmd.z_index);
|
||||||
// unreachable();
|
// unreachable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ctx.cmd_queue.enqueue(cmd);
|
return ctx.cmd_queue.push(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void? Ctx.push_scissor(&ctx, Rect rect, int z_index)
|
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,
|
.type = CMD_SCISSOR,
|
||||||
.scissor.rect = rect.intersection(ctx.div_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)
|
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.color = border_color,
|
||||||
.rect.radius = radius + border.x,
|
.rect.radius = radius + border.x,
|
||||||
};
|
};
|
||||||
ctx.push_cmd(&cmd, z_index)!;
|
ctx.push_cmd(cmd, z_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cmd cmd = {
|
Cmd cmd = {
|
||||||
@ -144,7 +148,7 @@ fn void? Ctx.push_rect(&ctx, Rect rect, int z_index, Style* style)
|
|||||||
.rect.color = bg,
|
.rect.color = bg,
|
||||||
.rect.radius = radius,
|
.rect.radius = radius,
|
||||||
};
|
};
|
||||||
ctx.push_cmd(&cmd, z_index)!;
|
ctx.push_cmd(cmd, z_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: accept a Sprite* instead of all this shit
|
// 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.texture_id = texture_id,
|
||||||
.sprite.hue = hue,
|
.sprite.hue = hue,
|
||||||
};
|
};
|
||||||
ctx.push_cmd(&cmd, z_index)!;
|
ctx.push_cmd(cmd, z_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void? Ctx.push_update_atlas(&ctx, Atlas* atlas)
|
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
|
// 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()})!!;
|
macro Ctx.dbg_rect(&ctx, Rect r, uint c = 0xff000042u) => ctx.push_rect(r, int.max, &&(Style){.bg=c.to_rgba()})!!;
|
||||||
|
@ -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
|
// Tuple of Element pointers, used when it is useful to get both parent and child
|
||||||
alias PElemTuple = pair::Pair{Elem*, Elem*};
|
alias PElemTuple = pair::Pair{Elem*, Elem*};
|
||||||
|
|
||||||
|
|
||||||
// relationships between elements are stored in a tree, it stores just the ids
|
// relationships between elements are stored in a tree, it stores just the ids
|
||||||
alias IdTree = mtree::MTree{Id};
|
alias IdTree = mtree::MTree{Id};
|
||||||
|
|
||||||
// elements themselves are kept in a cache
|
// elements themselves are kept in a cache
|
||||||
const uint MAX_ELEMENTS = 256;
|
|
||||||
alias ElemCache = cache::Cache{Id, Elem, MAX_ELEMENTS};
|
alias ElemCache = cache::Cache{Id, Elem, MAX_ELEMENTS};
|
||||||
|
|
||||||
alias CmdQueue = fifo::Fifo{Cmd};
|
|
||||||
|
|
||||||
faultdef INVALID_SIZE, EVENT_UNSUPPORTED, WRONG_ELEMENT_TYPE, WRONG_ID;
|
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 {
|
struct Ctx {
|
||||||
IdTree tree;
|
IdTree tree;
|
||||||
ElemCache cache;
|
ElemCache cache;
|
||||||
@ -216,7 +212,7 @@ fn void? Ctx.init(&ctx, Allocator allocator)
|
|||||||
ctx.cache.init(allocator)!;
|
ctx.cache.init(allocator)!;
|
||||||
defer catch { (void)ctx.cache.free(); }
|
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(); }
|
defer catch { (void)ctx.cmd_queue.free(); }
|
||||||
|
|
||||||
ctx.styles.init(allocator);
|
ctx.styles.init(allocator);
|
||||||
@ -311,13 +307,13 @@ $if $feature(DEBUG_POINTER):
|
|||||||
},
|
},
|
||||||
.rect.color = 0xff00ffffu.to_rgba()
|
.rect.color = 0xff00ffffu.to_rgba()
|
||||||
};
|
};
|
||||||
ctx.cmd_queue.enqueue(&cmd)!;
|
ctx.cmd_queue.push(cmd);
|
||||||
$endif
|
$endif
|
||||||
|
|
||||||
// sort the command buffer by the z-index
|
// sort the command buffer by the z-index
|
||||||
// FIXME: sorting the buffer fucks with scissor commands that have to be kept in place
|
// 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
|
// 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) {
|
// foreach (i, c: ctx.cmd_queue) {
|
||||||
// io::printf("[%d]: ", i);
|
// io::printf("[%d]: ", i);
|
||||||
|
@ -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)!;
|
|
||||||
}
|
|
||||||
}
|
|
@ -990,7 +990,12 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
|
|||||||
|
|
||||||
uint calls = 0;
|
uint calls = 0;
|
||||||
uint off;
|
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) {
|
switch (cmd.type) {
|
||||||
case CMD_UPDATE_ATLAS:
|
case CMD_UPDATE_ATLAS:
|
||||||
// TODO: verify the correct type
|
// TODO: verify the correct type
|
||||||
@ -1011,7 +1016,7 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
|
|||||||
uint count = 1;
|
uint count = 1;
|
||||||
while (queue.len() != 0 && (queue.get(0).type == CMD_RECT || queue.get(0).type == CMD_SPRITE)) {
|
while (queue.len() != 0 && (queue.get(0).type == CMD_RECT || queue.get(0).type == CMD_SPRITE)) {
|
||||||
count++;
|
count++;
|
||||||
(void)queue.dequeue();
|
(void)queue.pop_first();
|
||||||
}
|
}
|
||||||
self.draw_quads(off, count);
|
self.draw_quads(off, count);
|
||||||
off += count;
|
off += count;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user