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/cocoa/window.m | |
| 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/cocoa/window.m')
| -rw-r--r-- | src/platform/cocoa/window.m | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/src/platform/cocoa/window.m b/src/platform/cocoa/window.m index 1efff59..2f9f8e5 100644 --- a/src/platform/cocoa/window.m +++ b/src/platform/cocoa/window.m @@ -89,6 +89,8 @@ struct cocoa_surface { struct yasl_frame frame; struct yasl_damage_list damage; bool did_present; + /* Extent of the frame in pixels, valid while did_present is set. */ + struct yasl_vector2i shown_size; unsigned idle_frames; bool want_draw; bool frame_due; @@ -1073,6 +1075,7 @@ bool cocoa_surface_present(struct cocoa_surface *w, const struct yasl_framebuffe } yasl_clock_presented(&w->clock, yasl_loop_now_ns(), false); w->did_present = true; + w->shown_size = w->size; return true; } @@ -2198,6 +2201,17 @@ static bool impl_surface_place_under_pointer(struct yasl_surface *s, struct yasl return cocoa_surface_place_under_pointer((struct cocoa_surface *)s, at); } +static bool impl_surface_read_pixels(struct yasl_surface *s, uint32_t *out, size_t cap, + struct yasl_vector2i *size) +{ + struct cocoa_surface *w = (struct cocoa_surface *)s; + /* did_present stays set from the last draw until the next one starts, and + * pixels are reallocated only when a draw starts. */ + if (w->closed || w->rendering || !w->did_present || !w->software_queue || !w->pixels) + return false; + return yasl_copy_frame(w->pixels, w->shown_size, out, cap, size); +} + static bool impl_surface_bell(struct yasl_surface *s) { assert([NSThread isMainThread]); @@ -2266,6 +2280,7 @@ const struct yasl_backend_ops yasl_cocoa_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, .surface_get_native_frame = impl_surface_get_native_frame, |
