diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 17:12:10 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 17:12:10 +0300 |
| commit | b7944e4bbfa64a6bb1a1d9e1f172827dde53aed2 (patch) | |
| tree | d73ff8e368039f67f824ad2dc9130643ef4947ae /src/platform/wayland | |
| parent | ac6f9f5e7711521455b83ceb843a25e091646d43 (diff) | |
Read back the last presented CPU frame
wsap_term writes PNG screenshots for its debug server and keeps its own
copy of the frame because YASL had no readback.
yasl_surface_read_pixels() copies the frame from the last successful
present, or reports its extent when the buffer is too small. X11 and
Cocoa keep it in their single CPU target until the next draw starts;
X11 now also forgets it when a resize replaces the target, and Cocoa
records the presented extent because a resize can change the size before
the next draw. Wayland remembers which buffer it committed and forgets it
when a draw reuses that buffer.
The backend test checks the copy on Wayland and X11, and that draws that
never present do not show through. The Cocoa path is not built or run
here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'src/platform/wayland')
| -rw-r--r-- | src/platform/wayland/api.h | 2 | ||||
| -rw-r--r-- | src/platform/wayland/backend.c | 7 | ||||
| -rw-r--r-- | src/platform/wayland/buffer.c | 14 | ||||
| -rw-r--r-- | src/platform/wayland/internal.h | 3 |
4 files changed, 26 insertions, 0 deletions
diff --git a/src/platform/wayland/api.h b/src/platform/wayland/api.h index 6c3154c..9f290f5 100644 --- a/src/platform/wayland/api.h +++ b/src/platform/wayland/api.h @@ -39,5 +39,7 @@ bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_vec bool wayland_surface_drag_carry(struct wayland_surface *s, struct yasl_vector2i offset); bool wayland_surface_place_under_pointer(struct wayland_surface *s, struct yasl_vector2i at); bool wayland_surface_bell(struct wayland_surface *s); +bool wayland_surface_read_pixels(struct wayland_surface *s, uint32_t *out, size_t cap, + struct yasl_vector2i *size); #endif diff --git a/src/platform/wayland/backend.c b/src/platform/wayland/backend.c index ad9ed4c..4585cd6 100644 --- a/src/platform/wayland/backend.c +++ b/src/platform/wayland/backend.c @@ -185,6 +185,12 @@ static bool impl_surface_place_under_pointer(struct yasl_surface *s, struct yasl return wayland_surface_place_under_pointer((struct wayland_surface *)s, at); } +static bool impl_surface_read_pixels(struct yasl_surface *s, uint32_t *out, size_t cap, + struct yasl_vector2i *size) +{ + return wayland_surface_read_pixels((struct wayland_surface *)s, out, cap, size); +} + static bool impl_surface_bell(struct yasl_surface *s) { return wayland_surface_bell((struct wayland_surface *)s); @@ -240,6 +246,7 @@ const struct yasl_backend_ops yasl_wayland_backend = { .surface_drag_carry = impl_surface_drag_carry, .surface_place_under_pointer = impl_surface_place_under_pointer, .surface_bell = impl_surface_bell, + .surface_read_pixels = impl_surface_read_pixels, .display_get_native_handle = impl_display_get_native_handle, .surface_get_native_handle = impl_surface_get_native_handle, }; diff --git a/src/platform/wayland/buffer.c b/src/platform/wayland/buffer.c index f5a2c0f..b906f4f 100644 --- a/src/platform/wayland/buffer.c +++ b/src/platform/wayland/buffer.c @@ -472,9 +472,20 @@ bool wayland_surface_present(struct wayland_surface *w, const struct yasl_frameb return false; commit_buffer(w, w->cur); w->frame_presented = true; + w->shown = w->cur; + w->has_shown = true; return true; } +bool wayland_surface_read_pixels(struct wayland_surface *w, uint32_t *out, size_t cap, + struct yasl_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); +} + void surface_draw_frame(struct wayland_surface *w) { if (w->closed || !w->configured) @@ -491,6 +502,9 @@ void surface_draw_frame(struct wayland_surface *w) w->frames_skipped++; return; } + /* Drawing reuses the presented buffer only after the compositor released it. */ + if (w->has_shown && idx == w->shown) + w->has_shown = false; if (buffer_prepare(w, &w->buffers[idx], w->width, w->height, &buffer_listener) < 0) { w->frames_skipped++; return; diff --git a/src/platform/wayland/internal.h b/src/platform/wayland/internal.h index 84a603d..34d4133 100644 --- a/src/platform/wayland/internal.h +++ b/src/platform/wayland/internal.h @@ -307,6 +307,8 @@ struct wayland_surface { int ime_shown_begin, ime_shown_end; int floating_width, floating_height; int cur; + /* Buffer holding the last presented frame, valid while has_shown is set. */ + int shown; int width, height; int logical_width, logical_height; int req_width, req_height; @@ -318,6 +320,7 @@ struct wayland_surface { /* 1-byte booleans packed tightly */ bool frame_active; bool frame_presented; + bool has_shown; bool size_pending; bool sample_refresh; bool has_pending_serial; |
