From 76073fe5fad8799e5850805f2f090af2cb62c741 Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Tue, 13 Oct 2026 23:41:31 +0300 Subject: Simplify the public event and CPU API Applications now need far less ceremony: hello.c is a 20-line loop that handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels. - Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size, scale and state; unchanged values send nothing. - Guarantee REFRESH once a window has a size and after every resize, never at size zero. - Merge DROP_HOVER into DROP with over/leave/data actions and give drag and drop actions enums. - Keep event strings valid until the next wait and drop yasl_event_release; empty or failed waits report NONE. - Replace copy-in presentation with a lent pixel buffer: yasl_cpu_pixels and yasl_cpu_present. - Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and comments that restated names. - Wayland: resize floating windows in request_size instead of reporting it unsupported, and stop marking new GPU surfaces as Vulkan so yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE. Also includes the in-progress public API refactor that was uncommitted in the tree (removal of the app/loop layer, new surface, GL and Vulkan entry points). Co-Authored-By: Claude Opus 5.5 --- src/platform/wayland/buffer.c | 93 ++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 42 deletions(-) (limited to 'src/platform/wayland/buffer.c') diff --git a/src/platform/wayland/buffer.c b/src/platform/wayland/buffer.c index 874cc76..bbc055d 100644 --- a/src/platform/wayland/buffer.c +++ b/src/platform/wayland/buffer.c @@ -24,7 +24,7 @@ static const struct wl_buffer_listener buffer_listener; int device_px(int logical, uint32_t scale_120) { - int64_t px = ((int64_t)logical * scale_120 + YASL_SCALE_UNIT / 2) / YASL_SCALE_UNIT; + int64_t px = ((int64_t)logical * scale_120 + YASL_PRIVATE_SCALE_UNIT / 2) / YASL_PRIVATE_SCALE_UNIT; return px > 0 && px <= INT_MAX ? (int)px : -1; } @@ -58,7 +58,7 @@ int buffer_reserve(struct wayland_surface *w, struct buffer *b, size_t needed) if (b->busy || needed > INT32_MAX) return -1; size_t capacity = b->capacity <= INT32_MAX / 2 ? b->capacity * 2 : INT32_MAX; if (capacity < needed) capacity = needed; - int fd = memfd_create("yasl_surface_buffer", MFD_CLOEXEC | MFD_ALLOW_SEALING); + int fd = memfd_create("yasl_private_surface_buffer", MFD_CLOEXEC | MFD_ALLOW_SEALING); if (fd < 0) return -1; if (!fd_truncate(fd, capacity) || fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL) < 0) { @@ -89,7 +89,7 @@ int buffer_prepare(struct wayland_surface *w, struct buffer *b, int width, int h { if (b->proxy && !b->busy && b->width == width && b->height == height) return 0; long faults_before = minor_faults(); - uint64_t t0 = yasl_loop_now_ns(); + uint64_t t0 = yasl_private_loop_now_ns(); size_t bytes; if (!buffer_size(width, height, &bytes) || buffer_reserve(w, b, bytes) < 0) return -1; @@ -104,7 +104,7 @@ int buffer_prepare(struct wayland_surface *w, struct buffer *b, int width, int h b->busy = false; b->presented = false; wl_buffer_add_listener(proxy, listener, b); - yasl_clock_note_resize(&w->clock, yasl_loop_now_ns() - t0); + yasl_private_clock_note_resize(&w->clock, yasl_private_loop_now_ns() - t0); long faults = minor_faults() - faults_before; if (faults > 0) w->clock.resize_minflt += faults; return 0; @@ -114,10 +114,10 @@ static void publish_surface_scale(struct wayland_surface *w) { if (w->viewport) { wp_viewport_set_destination(w->viewport, w->logical_width, w->logical_height); - } else if (w->scale_120 % YASL_SCALE_UNIT == 0 && + } else if (w->scale_120 % YASL_PRIVATE_SCALE_UNIT == 0 && wl_proxy_get_version((struct wl_proxy *)w->surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) { - wl_surface_set_buffer_scale(w->surface, (int32_t)(w->scale_120 / YASL_SCALE_UNIT)); + wl_surface_set_buffer_scale(w->surface, (int32_t)(w->scale_120 / YASL_PRIVATE_SCALE_UNIT)); } } @@ -137,16 +137,16 @@ int apply_pending_geometry(struct wayland_surface *w) return 0; } bool floating = !w->parent && !(w->base.state & - (YASL_STATE_MAXIMIZED | YASL_STATE_FULLSCREEN | YASL_STATE_TILED)); + (YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_TILED)); int free_w = floating && w->floating_width > 0 ? w->floating_width : w->logical_width; int free_h = floating && w->floating_height > 0 ? w->floating_height : w->logical_height; int logical_w = !w->parent && w->req_width > 0 ? w->req_width : free_w; int logical_h = !w->parent && w->req_height > 0 ? w->req_height : free_h; if (!w->parent) { - if (logical_w < YASL_MIN_LOGICAL_PX) logical_w = YASL_MIN_LOGICAL_PX; - if (logical_h < YASL_MIN_LOGICAL_PX) logical_h = YASL_MIN_LOGICAL_PX; + if (logical_w < YASL_PRIVATE_MIN_LOGICAL_PX) logical_w = YASL_PRIVATE_MIN_LOGICAL_PX; + if (logical_h < YASL_PRIVATE_MIN_LOGICAL_PX) logical_h = YASL_PRIVATE_MIN_LOGICAL_PX; } - if (!(w->base.state & YASL_STATE_FULLSCREEN)) { + if (!(w->base.state & YASL_PRIVATE_STATE_FULLSCREEN)) { if (w->bound_width > 0 && logical_w > w->bound_width) logical_w = w->bound_width; if (w->bound_height > 0 && logical_h > w->bound_height) @@ -155,7 +155,9 @@ int apply_pending_geometry(struct wayland_surface *w) int width = device_px(logical_w, w->pending_scale_120); int height = device_px(logical_h, w->pending_scale_120); size_t bytes; - if (!buffer_size(width, height, &bytes)) { + if (width <= 0 || height <= 0 || + (w->base.presenter == YASL_PRIVATE_PRESENTER_CPU && + !buffer_size(width, height, &bytes))) { return -1; } bool rescaled = w->scale_120 != w->pending_scale_120; @@ -169,13 +171,17 @@ int apply_pending_geometry(struct wayland_surface *w) return 0; w->scale_120 = w->pending_scale_120; - w->scale_factor = (double)w->scale_120 / YASL_SCALE_UNIT; + w->scale_factor = (double)w->scale_120 / YASL_PRIVATE_SCALE_UNIT; w->width = width; w->height = height; - w->base.size = (struct yasl_vector2i){width, height}; + w->base.size = (struct yasl_private_vector2i){width, height}; w->base.scale_120 = w->scale_120; w->logical_width = logical_w; w->logical_height = logical_h; +#if YASL_HAS_EGL + if (w->egl_window && (resized || rescaled)) + wl_egl_window_resize(w->egl_window, width, height, 0, 0); +#endif surface_update_opaque_region(w); if (resized || rescaled) { for (int i = 0; i < NBUF; i++) @@ -183,7 +189,7 @@ int apply_pending_geometry(struct wayland_surface *w) } publish_surface_scale(w); if (resized || rescaled) { - yasl_surface_notify_configure(&w->base, (struct yasl_geometry){ + yasl_private_surface_notify_configure(&w->base, (struct yasl_private_geometry){ .size = { .x = width, .y = height }, .scale_120 = w->scale_120, }); if (w->closed || w->destroyed) @@ -225,7 +231,7 @@ void surface_follow_outputs(struct wayland_surface *w) w->clock.refresh_ns = refresh; if (need_scale) - surface_request_scale(w, (uint32_t)max_scale * YASL_SCALE_UNIT); + surface_request_scale(w, (uint32_t)max_scale * YASL_PRIVATE_SCALE_UNIT); } static void surface_enter(void *data, struct wl_surface *surface, struct wl_output *output) @@ -250,7 +256,7 @@ static void surface_preferred_scale(void *data, struct wl_surface *surface, int3 struct wayland_surface *w = data; if (w->frac_scale || w->parent || factor <= 0) return; - surface_request_scale(w, (uint32_t)factor * YASL_SCALE_UNIT); + surface_request_scale(w, (uint32_t)factor * YASL_PRIVATE_SCALE_UNIT); } static void surface_preferred_transform(void *data, struct wl_surface *surface, @@ -285,13 +291,15 @@ static void frame_done(void *data, struct wl_callback *cb, uint32_t ms) wl_callback_destroy(cb); w->frame_cb = NULL; - uint64_t now = yasl_loop_now_ns(); + uint64_t now = yasl_private_loop_now_ns(); if (!w->conn->pres_clock_known) { - yasl_clock_presented(&w->clock, yasl_clock_extend_ms(ms, now), w->sample_refresh); - w->clock.source = YASL_TIMING_FRAME_CALLBACK; + yasl_private_clock_presented(&w->clock, yasl_private_clock_extend_ms(ms, now), w->sample_refresh); + w->clock.source = YASL_PRIVATE_TIMING_FRAME_CALLBACK; } - if (w->want_draw) + if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU) + yasl_private_surface_notify_refresh(&w->base); + else if (w->want_draw) wayland_surface_schedule_redraw(w); } @@ -299,14 +307,14 @@ static const struct wl_callback_listener frame_listener = { .done = frame_done, }; -static void arm_frame(struct wayland_surface *w) +void wayland_surface_arm_frame(struct wayland_surface *w) { if (!w->configured || w->closed || w->frame_cb) return; w->frame_cb = wl_surface_frame(w->surface); if (!w->frame_cb) { surface_fail(w); return; } w->sample_refresh = w->clock.last_present_ns && - yasl_loop_now_ns() - w->clock.last_present_ns < + yasl_private_loop_now_ns() - w->clock.last_present_ns < (uint64_t)(w->clock.refresh_ns / 2); if (wl_callback_add_listener(w->frame_cb, &frame_listener, w) < 0) { wl_callback_destroy(w->frame_cb); @@ -365,7 +373,7 @@ static void presented(void *data, struct wp_presentation_feedback *fb, (((uint64_t)tv_sec_hi << 32) | tv_sec_lo) * 1000000000ull + tv_nsec); if (refresh) w->clock.refresh_ns = refresh; w->clock.last_present_ns = ns; - w->clock.source = YASL_TIMING_PRESENTATION; + w->clock.source = YASL_PRIVATE_TIMING_PRESENTATION; } (void)fb; feedback_destroy(feedback); @@ -419,7 +427,7 @@ static void commit_buffer(struct wayland_surface *w, int idx) { wl_surface_attach(w->surface, w->buffers[idx].proxy, 0, 0); - const struct yasl_damage_list *d = &w->damage; + const struct yasl_private_damage_list *d = &w->damage; if (d->n < 0 || !w->buffers[idx].presented) wl_surface_damage_buffer(w->surface, 0, 0, w->width, w->height); else @@ -438,8 +446,8 @@ static void commit_buffer(struct wayland_surface *w, int idx) wp_fifo_v1_set_barrier(w->fifo); } if (w->commit_timer && w->conn->pres_clock_known) { - uint64_t now = yasl_loop_now_ns(); - uint64_t next = yasl_clock_next_present_ns(&w->clock); + uint64_t now = yasl_private_loop_now_ns(); + uint64_t next = yasl_private_clock_next_present_ns(&w->clock); bool soon = next > now && next - now < (uint64_t)(w->clock.refresh_ns * 1.5); next = conn_mono_to_pres(w->conn, next); if (soon) @@ -458,10 +466,11 @@ static void commit_buffer(struct wayland_surface *w, int idx) w->buffers[idx].presented = true; } -bool wayland_surface_present(struct wayland_surface *w, const struct yasl_framebuffer *fb, - const struct yasl_damage_list *damage) +bool wayland_surface_present(struct wayland_surface *w, const struct yasl_private_framebuffer *fb, + const struct yasl_private_damage_list *damage) { - if (!w || w->closed || !w->frame_active || w->frame_presented || !fb || + if (!w || w->base.presenter != YASL_PRIVATE_PRESENTER_CPU || + w->closed || !w->frame_active || w->frame_presented || !fb || !damage || fb->pixels != w->frame.target.pixels || fb->size.x != w->width || fb->size.y != w->height) return false; @@ -470,7 +479,7 @@ bool wayland_surface_present(struct wayland_surface *w, const struct yasl_frameb w->damage.bounds = damage->bounds; if (damage->n > 0) memcpy(w->damage.rects, damage->rects, (size_t)damage->n * sizeof(damage->rects[0])); - arm_frame(w); + wayland_surface_arm_frame(w); if (w->closed) return false; commit_buffer(w, w->cur); @@ -481,17 +490,17 @@ bool wayland_surface_present(struct wayland_surface *w, const struct yasl_frameb } bool wayland_surface_read_pixels(struct wayland_surface *w, uint32_t *out, size_t cap, - struct yasl_vector2i *size) + struct yasl_private_vector2i *size) { if (!w || w->closed || w->frame_active || !w->has_shown) return false; const struct buffer *b = &w->buffers[w->shown]; if (!b->pixels) return false; - return yasl_copy_frame(b->pixels, (struct yasl_vector2i){b->width, b->height}, out, cap, size); + return yasl_private_copy_frame(b->pixels, (struct yasl_private_vector2i){b->width, b->height}, out, cap, size); } void surface_draw_frame(struct wayland_surface *w) { - if (w->closed || !w->configured) + if (w->closed || !w->configured || w->base.presenter != YASL_PRIVATE_PRESENTER_CPU) return; if (apply_pending_geometry(w) < 0) { surface_fail(w); @@ -517,18 +526,18 @@ void surface_draw_frame(struct wayland_surface *w) if (w->parent) memset(w->buffers[idx].pixels, 0, (size_t)w->width * (size_t)w->height * sizeof(uint32_t)); - w->damage = (struct yasl_damage_list){0}; - w->frame = (struct yasl_frame){ + w->damage = (struct yasl_private_damage_list){0}; + w->frame = (struct yasl_private_frame){ .surface = &w->base, .target = { - .generation = yasl_frame_begin(&w->base), + .generation = yasl_private_frame_begin(&w->base), .pixels = w->buffers[idx].pixels, .size = { .x = w->width, .y = w->height }, }, }; w->frame_active = true; w->frame_presented = false; - yasl_surface_draw(&w->base, &w->frame); + yasl_private_surface_draw(&w->base, &w->frame); if (w->closed || w->destroyed) return; w->frame_active = false; @@ -555,21 +564,21 @@ int surface_init_scaling(struct wayland_surface *w) void wayland_surface_set_title(struct wayland_surface *w, const char *title) { if (!w || !w->toplevel || !title) return; - char *copy = yasl_utf8_sanitize_dup(title); + char *copy = yasl_private_utf8_sanitize_dup(title); if (!copy) return; xdg_toplevel_set_title(w->toplevel, copy); free(copy); } -struct yasl_timing wayland_surface_timing(const struct wayland_surface *w) +struct yasl_private_timing wayland_surface_timing(const struct wayland_surface *w) { - struct yasl_timing t = { + struct yasl_private_timing t = { .refresh_ns = w->clock.refresh_ns, .last_present_ns = w->clock.last_present_ns, - .next_present_ns = yasl_clock_next_present_ns(&w->clock), + .next_present_ns = yasl_private_clock_next_present_ns(&w->clock), .frames_skipped = w->frames_skipped, .source = w->clock.source, }; - yasl_clock_resize_stats(&w->clock, &t.resize); + yasl_private_clock_resize_stats(&w->clock, &t.resize); return t; } -- cgit v1.2.3