implemented a frame skip request

This commit is contained in:
Alessandro Mauri 2025-10-11 22:32:00 +02:00
parent b5ef86d092
commit b9e91c3119
5 changed files with 26 additions and 0 deletions

View File

@ -9,6 +9,7 @@ enum CmdType {
CMD_UPDATE_ATLAS,
CMD_SPRITE,
CMD_SCISSOR,
CMD_REQ_SKIP_FRAME,
}
// command to draw a rect
@ -107,6 +108,8 @@ fn usz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
case CMD_UPDATE_ATLAS:
ret += f.print("CmdUpdateAtlas")!;
ret += io::struct_to_format(cmd.update_atlas, f, false)!;
case CMD_REQ_SKIP_FRAME:
ret += f.print("Skip Frame Request")!;
}
ret += f.print("}")!;

View File

@ -120,6 +120,8 @@ struct Ctx {
Font font;
SpriteAtlas sprite_atlas;
bool skip_frame;
bool has_focus;
InputData input, current_input;
@ -262,6 +264,8 @@ fn void? Ctx.frame_begin(&ctx)
elem.layout.h = @exact(ctx.height);
ctx.div_scissor = elem.bounds;
ctx.skip_frame = false;
}
fn void? Ctx.frame_end(&ctx)
@ -306,6 +310,11 @@ fn void? Ctx.frame_end(&ctx)
ctx.push_update_atlas(&ctx.sprite_atlas.atlas)!;
ctx.sprite_atlas.should_update = false;
}
// send skip frame request
if (ctx.skip_frame) {
ctx.cmd_queue.push({.type = CMD_REQ_SKIP_FRAME});
}
// sort the command buffer by the z-index
// FIXME: sorting the buffer fucks with scissor commands that have to be kept in place

View File

@ -208,6 +208,8 @@ macro Point Point.neg(Point p) @operator_s(-) => {-p.x, -p.y};
macro Point Point.max(Point a, Point b) => {.x = max(a.x, b.x), .y = max(a.y, b.y)};
macro Point Point.min(Point a, Point b) => {.x = min(a.x, b.x), .y = min(a.y, b.y)};
macro bool Point.equals(Point a, Point b) @operator_s(==) => a.x == b.x && a.y == b.y;
// ---------------------------------------------------------------------------------- //
// COLOR //
// ---------------------------------------------------------------------------------- //

View File

@ -211,6 +211,13 @@ fn bool? Ctx.popup_begin_id(&ctx,
.origin.y = pos.y - parent.bounds.y,
};
// if the position is not the one expected then request a frame-skip to not flash appear in the
// wrong position for one frame
if (elem.bounds.position() != pos) {
ctx.skip_frame = true;
return true;
}
ctx.push_rect(elem.bounds.pad(style.margin), elem.z_index, style)!;
// update the ctx scissor, it HAS to be after drawing the background

View File

@ -988,6 +988,7 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
self.start_render_pass("UGUI_PIPELINE");
self.bind_textures_id(self.font_atlas_id, self.sprite_atlas_id);
bool no_draws;
uint calls = 0;
uint off;
while (true) {
@ -997,6 +998,8 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
break;
}
switch (cmd.type) {
case CMD_REQ_SKIP_FRAME:
no_draws = true;
case CMD_UPDATE_ATLAS:
// TODO: verify the correct type
CmdUpdateAtlas u = cmd.update_atlas;
@ -1012,6 +1015,8 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
self.scissor_w = s.w;
self.scissor_h = s.h;
default:
if (no_draws) break;
self.set_scissor(self.scissor_x, self.scissor_y, self.scissor_w, self.scissor_h);
uint count = 1;
while (queue.len() != 0 && (queue.get(0).type == CMD_RECT || queue.get(0).type == CMD_SPRITE)) {