diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-11 23:27:41 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-11 23:27:41 +0300 |
| commit | 472ed3e4e50a165638acecaf071ec3c2c13c451f (patch) | |
| tree | d1894debde800d8e87d3c242ae6c3f4760c68787 /src/wayland/surface.c | |
| parent | 8d9f7c7cb39359d62bf28ef1775b944a7dddd6fb (diff) | |
core: optimize struct layouts, eliminate branches, and fix event loop dispatch
- Fix Wayland event loop lockout by properly decoupling read arming and adding poll-backed dispatching
- Support standalone display lifecycle without requiring caller to manage a loop
- Eliminate alignment holes across yasl_surface, yasl_display, seat, touch_point, and conn_drag using pahole
- Replace branching state/button decoders with compile-time locked LUTs and branchless bitwise operations
- Accelerate UTF-8 validation with 64-bit word scanning for ASCII runs
Diffstat (limited to 'src/wayland/surface.c')
| -rw-r--r-- | src/wayland/surface.c | 118 |
1 files changed, 99 insertions, 19 deletions
diff --git a/src/wayland/surface.c b/src/wayland/surface.c index da334e4..5138201 100644 --- a/src/wayland/surface.c +++ b/src/wayland/surface.c @@ -83,6 +83,14 @@ static int display_ready(int fd, short revents, void *ud) else if (wl_display_read_events(c->wl) < 0) revents |= POLLERR; } + if (revents & POLLOUT) { + if (wl_display_flush(c->wl) >= 0) { + if (c->loop && c->watch > 0) + yasl_loop_set_fd_events(c->loop, c->watch, POLLIN); + } else if (errno != EAGAIN) { + display_lose(c); + } + } if (wl_display_dispatch_pending(c->wl) < 0 || (revents & (POLLERR | POLLHUP | POLLNVAL))) display_lose(c); @@ -90,35 +98,92 @@ static int display_ready(int fd, short revents, void *ud) return 0; } -void yasl_display_dispatch(struct yasl_display *c) -{ - if (!c || c->lost || c->reading) - return; - display_enter(c); - if (wl_display_dispatch_pending(c->wl) < 0) - display_lose(c); - display_leave(c); -} - -static void display_arm(struct yasl_display *c) +static bool display_arm(struct yasl_display *c) { + bool had_pending = false; while (!c->reading && wl_display_prepare_read(c->wl) != 0) { + had_pending = true; if (wl_display_dispatch_pending(c->wl) < 0) { display_lose(c); - return; + return false; } } c->reading = true; short events = POLLIN; if (wl_display_flush(c->wl) < 0) { if (errno != EAGAIN) { + display_cancel_read(c); display_lose(c); - return; + return false; } events |= POLLOUT; } - if (c->loop) + if (c->loop && c->watch > 0) yasl_loop_set_fd_events(c->loop, c->watch, events); + return had_pending; +} + +static bool display_has_immediate_work(const struct yasl_display *c) +{ + if (!c || c->lost) return false; + for (struct yasl_surface *w = c->surfaces; w; w = w->conn_next) { + if (w->closed) continue; + if (w->input.count > 0) + return true; + if (w->want_draw && !w->frame_cb && w->configured) + return true; + } + return false; +} + +int yasl_display_dispatch_timeout(struct yasl_display *c, int timeout_ms) +{ + if (!c || c->lost) + return -1; + + display_enter(c); + + if (wl_display_dispatch_pending(c->wl) < 0) { + display_lose(c); + display_leave(c); + return -1; + } + + bool had_pending = display_arm(c); + if (c->lost) { + display_leave(c); + return -1; + } + + if (had_pending && timeout_ms != 0 && display_has_immediate_work(c)) { + timeout_ms = 0; + } + + int n = 0; + if (c->loop) { + n = yasl_loop_step(c->loop, timeout_ms); + } + + if (c->reading) { + display_cancel_read(c); + } + + if (wl_display_dispatch_pending(c->wl) < 0) { + display_lose(c); + display_leave(c); + return -1; + } + + display_leave(c); + return n; +} + +void yasl_display_dispatch(struct yasl_display *c) +{ + if (!c || c->lost) + return; + int timeout = display_has_immediate_work(c) ? 0 : -1; + yasl_display_dispatch_timeout(c, timeout); } void yasl_display_flush(struct yasl_display *c) @@ -130,8 +195,10 @@ void yasl_display_flush(struct yasl_display *c) next = w->conn_next; surface_draw_frame(w); } - if (!c->lost) - display_arm(c); + if (!c->lost && c->wl) { + if (wl_display_flush(c->wl) < 0 && errno != EAGAIN) + display_lose(c); + } display_leave(c); } @@ -163,6 +230,10 @@ static void display_free(struct yasl_display *c) if (c->compositor) wl_compositor_destroy(c->compositor); if (c->registry) wl_registry_destroy(c->registry); if (c->wl) wl_display_disconnect(c->wl); + if (c->owns_loop && c->loop) { + yasl_loop_destroy(c->loop); + c->loop = NULL; + } free(c->app_id); free(c); } @@ -171,7 +242,13 @@ struct yasl_display *yasl_display_open(struct yasl_loop *loop, const struct yasl { struct yasl_display *c = calloc(1, sizeof(*c)); if (!c) return NULL; - c->loop = loop; + if (!loop) { + c->loop = yasl_loop_create(); + c->owns_loop = true; + } else { + c->loop = loop; + } + if (!c->loop) goto err; if (spec) { c->cbs = spec->cbs; c->ud = spec->ud; @@ -189,7 +266,7 @@ struct yasl_display *yasl_display_open(struct yasl_loop *loop, const struct yasl surface_init_cursor(c); if (c->loop) { - c->watch = yasl_loop_add_fd(loop, wl_display_get_fd(c->wl), POLLIN, display_ready, c); + c->watch = yasl_loop_add_fd(c->loop, wl_display_get_fd(c->wl), POLLIN, display_ready, c); if (c->watch <= 0) { c->watch = 0; goto err; } } if (display_input_init(c) < 0) @@ -371,7 +448,10 @@ struct yasl_display *yasl_surface_display(const struct yasl_surface *w) void yasl_surface_schedule_redraw(struct yasl_surface *w) { - if (w) w->want_draw = true; + if (!w || w->closed) return; + w->want_draw = true; + if (w->conn && w->conn->loop) + yasl_loop_kick(w->conn->loop); } struct yasl_vector2i yasl_surface_size(const struct yasl_surface *w) |
