diff --git a/include/screencopy-interface.h b/include/screencopy-interface.h new file mode 100644 index 0000000..dd9de8c --- /dev/null +++ b/include/screencopy-interface.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include + +// TODO: Add a way to set the rate limit + +struct zext_screencopy_manager_v1; +struct wl_output; +struct wv_buffer; + +enum screencopy_result { + SCREENCOPY_DONE, + SCREENCOPY_FATAL, + SCREENCOPY_FAILED, +}; + +typedef void (*screencopy_done_fn)(enum screencopy_result, + struct wv_buffer* buffer, void* userdata); + +struct screencopy_impl { + struct screencopy* (*create)(struct wl_output*, bool render_cursor); + struct screencopy* (*create_cursor)(struct wl_output*); + void (*destroy)(struct screencopy*); + int (*start)(struct screencopy*, bool immediate); + void (*stop)(struct screencopy*); +}; + +struct screencopy { + struct screencopy_impl* impl; + + double rate_limit; + bool enable_linux_dmabuf; + + screencopy_done_fn on_done; + void (*cursor_enter)(void* userdata); + void (*cursor_leave)(void* userdata); + void (*cursor_hotspot)(int x, int y, void* userdata); + + void* userdata; +}; + +struct screencopy* screencopy_create(struct screencopy_impl* impl, + struct wl_output* output, bool render_cursor); +struct screencopy* screencopy_create_cursor(struct screencopy_impl* impl, + struct wl_output* output); +void screencopy_destroy(struct screencopy* self); + +int screencopy_start(struct screencopy* self, bool immediate); +void screencopy_stop(struct screencopy* self); diff --git a/include/screencopy.h b/include/screencopy.h deleted file mode 100644 index 205ebbc..0000000 --- a/include/screencopy.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 - 2020 Andri Yngvason - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#pragma once - -#include - -#include "wlr-screencopy-unstable-v1.h" -#include "smooth.h" -#include "buffer.h" - -struct zwlr_screencopy_manager_v1; -struct zwlr_screencopy_frame_v1; -struct wl_output; -struct wl_buffer; -struct wl_shm; -struct aml_timer; -struct renderer; - -enum screencopy_status { - SCREENCOPY_STOPPED = 0, - SCREENCOPY_IN_PROGRESS, - SCREENCOPY_FAILED, - SCREENCOPY_FATAL, - SCREENCOPY_DONE, -}; - -struct screencopy { - enum screencopy_status status; - - struct wv_buffer_pool* pool; - struct wv_buffer* front; - struct wv_buffer* back; - - struct zwlr_screencopy_manager_v1* manager; - struct zwlr_screencopy_frame_v1* frame; - - void* userdata; - void (*on_done)(struct screencopy*); - - uint64_t last_time; - uint64_t start_time; - struct aml_timer* timer; - - struct smooth delay_smoother; - double delay; - bool is_immediate_copy; - bool overlay_cursor; - struct wl_output* wl_output; - - uint32_t wl_shm_width, wl_shm_height, wl_shm_stride; - enum wl_shm_format wl_shm_format; - - bool have_linux_dmabuf; - bool enable_linux_dmabuf; - uint32_t dmabuf_width, dmabuf_height; - uint32_t fourcc; - - double rate_limit; -}; - -void screencopy_init(struct screencopy* self); -void screencopy_destroy(struct screencopy* self); - -int screencopy_start(struct screencopy* self); -int screencopy_start_immediate(struct screencopy* self); - -void screencopy_stop(struct screencopy* self); diff --git a/meson.build b/meson.build index c935436..a2dee4f 100644 --- a/meson.build +++ b/meson.build @@ -87,6 +87,7 @@ sources = [ 'src/strlcpy.c', 'src/shm.c', 'src/screencopy.c', + 'src/screencopy-interface.c', 'src/data-control.c', 'src/output.c', 'src/output-management.c', diff --git a/src/main.c b/src/main.c index 5bb8ebb..d1ca7ef 100644 --- a/src/main.c +++ b/src/main.c @@ -42,7 +42,7 @@ #include "wlr-output-management-unstable-v1.h" #include "linux-dmabuf-unstable-v1.h" #include "ext-transient-seat-v1.h" -#include "screencopy.h" +#include "screencopy-interface.h" #include "data-control.h" #include "strlcpy.h" #include "output.h" @@ -56,6 +56,7 @@ #include "ctl-server.h" #include "util.h" #include "option-parser.h" +#include "buffer.h" #ifdef ENABLE_PAM #include "pam_auth.h" @@ -100,7 +101,7 @@ struct wayvnc { struct output* selected_output; struct seat* selected_seat; - struct screencopy screencopy; + struct screencopy* screencopy; struct aml_handler* wayland_handler; struct aml_signal* signal_handler; @@ -126,6 +127,7 @@ struct wayvnc { bool is_initializing; bool start_detached; + bool overlay_cursor; struct wayvnc_client* master_layout_client; }; @@ -144,7 +146,8 @@ struct wayvnc_client { }; void wayvnc_exit(struct wayvnc* self); -void on_capture_done(struct screencopy* sc); +void on_capture_done(enum screencopy_result result, struct wv_buffer* buffer, + void* userdata); static void on_nvnc_client_new(struct nvnc_client* client); void switch_to_output(struct wayvnc*, struct output*); void switch_to_next_output(struct wayvnc*); @@ -164,6 +167,9 @@ struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf = NULL; struct gbm_device* gbm_device = NULL; struct zxdg_output_manager_v1* xdg_output_manager = NULL; struct zwlr_output_power_manager_v1* wlr_output_power_manager = NULL; +struct zwlr_screencopy_manager_v1* screencopy_manager = NULL; + +extern struct screencopy_impl wlr_screencopy_impl; static bool registry_add_input(void* data, struct wl_registry* registry, uint32_t id, const char* interface, @@ -275,7 +281,7 @@ static void registry_add(void* data, struct wl_registry* registry, } if (strcmp(interface, zwlr_screencopy_manager_v1_interface.name) == 0) { - self->screencopy.manager = + screencopy_manager = wl_registry_bind(registry, id, &zwlr_screencopy_manager_v1_interface, MIN(3, version)); @@ -417,7 +423,8 @@ static void wayland_detach(struct wayvnc* self) } self->selected_output = NULL; - self->screencopy.wl_output = NULL; + //TODO: Make output inert: + //self->screencopy->wl_output = NULL; output_list_destroy(&self->outputs); seat_list_destroy(&self->seats); @@ -426,12 +433,12 @@ static void wayland_detach(struct wayvnc* self) zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf); zwp_linux_dmabuf = NULL; - if (self->screencopy.manager) { - screencopy_stop(&self->screencopy); - screencopy_destroy(&self->screencopy); - zwlr_screencopy_manager_v1_destroy(self->screencopy.manager); + if (screencopy_manager) { + screencopy_stop(self->screencopy); + screencopy_destroy(self->screencopy); + zwlr_screencopy_manager_v1_destroy(screencopy_manager); } - self->screencopy.manager = NULL; + screencopy_manager = NULL; if (xdg_output_manager) zxdg_output_manager_v1_destroy(xdg_output_manager); @@ -458,6 +465,9 @@ static void wayland_detach(struct wayvnc* self) zwlr_data_control_manager_v1_destroy(self->data_control_manager); self->data_control_manager = NULL; + if (screencopy_manager) + zwlr_screencopy_manager_v1_destroy(screencopy_manager); + if (self->performance_ticker) { aml_stop(aml_get_default(), self->performance_ticker); aml_unref(self->performance_ticker); @@ -559,7 +569,7 @@ static int init_wayland(struct wayvnc* self, const char* display) goto failure; } - if (!self->screencopy.manager) { + if (!screencopy_manager) { nvnc_log(NVNC_LOG_ERROR, "Screencopy protocol not supported by compositor. Exiting. Refer to FAQ section in man page."); goto failure; } @@ -569,8 +579,8 @@ static int init_wayland(struct wayvnc* self, const char* display) goto failure; } - self->screencopy.on_done = on_capture_done; - self->screencopy.userdata = self; + self->screencopy->on_done = on_capture_done; + self->screencopy->userdata = self; self->wl_handler = aml_handler_new(wl_display_get_fd(self->display), on_wayland_event, self, NULL); @@ -976,7 +986,7 @@ failure: int wayvnc_start_capture(struct wayvnc* self) { - int rc = screencopy_start(&self->screencopy); + int rc = screencopy_start(self->screencopy, false); if (rc < 0) { nvnc_log(NVNC_LOG_ERROR, "Failed to start capture. Exiting..."); wayvnc_exit(self); @@ -997,7 +1007,7 @@ int wayvnc_start_capture_immediate(struct wayvnc* self) return 0; } - int rc = screencopy_start_immediate(&self->screencopy); + int rc = screencopy_start(self->screencopy, true); if (rc < 0) { nvnc_log(NVNC_LOG_ERROR, "Failed to start capture. Exiting..."); wayvnc_exit(self); @@ -1035,7 +1045,7 @@ void on_output_dimension_change(struct output* output) nvnc_log(NVNC_LOG_DEBUG, "Output dimensions changed. Restarting frame capturer..."); - screencopy_stop(&self->screencopy); + screencopy_stop(self->screencopy); wayvnc_start_capture_immediate(self); } @@ -1054,7 +1064,7 @@ static void on_output_power_change(struct output* output) break; case OUTPUT_POWER_OFF: nvnc_log(NVNC_LOG_WARNING, "Output is now off. Pausing frame capture"); - screencopy_stop(&self->screencopy); + screencopy_stop(self->screencopy); blank_screen(self); break; default: @@ -1079,10 +1089,9 @@ static uint32_t calculate_region_area(struct pixman_region16* region) return area; } -void wayvnc_process_frame(struct wayvnc* self) +void wayvnc_process_frame(struct wayvnc* self, struct wv_buffer* buffer) { - struct wv_buffer* buffer = self->screencopy.back; - self->screencopy.back = NULL; + // TODO: Back buffer used to be set to NULL here, what's that about? self->n_frames_captured++; self->damage_area_sum += @@ -1120,15 +1129,12 @@ void wayvnc_process_frame(struct wayvnc* self) wayvnc_start_capture(self); } -void on_capture_done(struct screencopy* sc) +void on_capture_done(enum screencopy_result result, struct wv_buffer* buffer, + void* userdata) { - struct wayvnc* self = sc->userdata; + struct wayvnc* self = userdata; - switch (sc->status) { - case SCREENCOPY_STOPPED: - break; - case SCREENCOPY_IN_PROGRESS: - break; + switch (result) { case SCREENCOPY_FATAL: nvnc_log(NVNC_LOG_ERROR, "Fatal error while capturing. Exiting..."); wayvnc_exit(self); @@ -1137,7 +1143,7 @@ void on_capture_done(struct screencopy* sc) wayvnc_restart_capture(self); break; case SCREENCOPY_DONE: - wayvnc_process_frame(self); + wayvnc_process_frame(self, buffer); break; } } @@ -1300,7 +1306,7 @@ static void client_destroy(void* obj) if (wayvnc->nr_clients == 0 && wayvnc->display) { nvnc_log(NVNC_LOG_INFO, "Stopping screen capture"); - screencopy_stop(&wayvnc->screencopy); + screencopy_stop(wayvnc->screencopy); stop_performance_ticker(wayvnc); } @@ -1524,7 +1530,8 @@ void set_selected_output(struct wayvnc* self, struct output* output) { self->selected_output->on_dimension_change = NULL; } self->selected_output = output; - self->screencopy.wl_output = output->wl_output; + // TODO: Change screencopy output: + // self->screencopy.wl_output = output->wl_output; output->on_dimension_change = on_output_dimension_change; output->on_power_change = on_output_power_change; output->userdata = self; @@ -1540,7 +1547,7 @@ void switch_to_output(struct wayvnc* self, struct output* output) output->name); return; } - screencopy_stop(&self->screencopy); + screencopy_stop(self->screencopy); set_selected_output(self, output); reinitialise_pointers(self); if (self->nr_clients > 0) @@ -1632,12 +1639,13 @@ static bool wayland_attach(struct wayvnc* self, const char* display, } } - screencopy_init(&self->screencopy); - if (!self->screencopy.manager) { + if (!screencopy_manager) { nvnc_log(NVNC_LOG_ERROR, "Attached display does not implement wlr-screencopy-v1"); wayland_detach(self); return false; } + self->screencopy = screencopy_create(&wlr_screencopy_impl, + self->selected_output->wl_output, self->overlay_cursor); set_selected_output(self, out); @@ -1801,6 +1809,7 @@ int main(int argc, char* argv[]) start_detached = !!option_parser_get_value(&option_parser, "detached"); self.start_detached = start_detached; + self.overlay_cursor = overlay_cursor; keyboard_options = option_parser_get_value(&option_parser, "keyboard"); if (keyboard_options) @@ -1905,9 +1914,6 @@ int main(int argc, char* argv[]) self.selected_seat = seat; } - self.screencopy.rate_limit = max_rate; - self.screencopy.enable_linux_dmabuf = enable_gpu_features; - #ifdef ENABLE_SCREENCOPY_DMABUF if (enable_gpu_features && init_render_node(&drm_fd) < 0) { nvnc_log(NVNC_LOG_ERROR, "Failed to initialise DRM render node. No GPU acceleration will be available."); @@ -1927,16 +1933,23 @@ int main(int argc, char* argv[]) goto nvnc_failure; if (!start_detached) { - if (self.screencopy.manager) - screencopy_init(&self.screencopy); + if (screencopy_manager) { + self.screencopy = screencopy_create(&wlr_screencopy_impl, + self.selected_output->wl_output, + overlay_cursor); + if (!self.screencopy) + goto screencopy_failure; - if (!self.screencopy.manager) { + self.screencopy->rate_limit = max_rate; + self.screencopy->enable_linux_dmabuf = enable_gpu_features; + } else { nvnc_log(NVNC_LOG_ERROR, "screencopy is not supported by compositor"); goto capture_failure; } } - self.screencopy.overlay_cursor = overlay_cursor; + self.screencopy->on_done = on_capture_done; + self.screencopy->userdata = &self; if (show_performance) self.performance_ticker = aml_ticker_new(1000000, on_perf_tick, @@ -1972,7 +1985,7 @@ int main(int argc, char* argv[]) nvnc_log(NVNC_LOG_INFO, "Exiting..."); if (self.display) - screencopy_stop(&self.screencopy); + screencopy_stop(self.screencopy); ctl_server_destroy(self.ctl); self.ctl = NULL; @@ -1981,6 +1994,10 @@ int main(int argc, char* argv[]) nvnc_close(self.nvnc); self.nvnc = NULL; wayvnc_destroy(&self); + if (zwp_linux_dmabuf) + zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf); + if (self.screencopy) + screencopy_destroy(self.screencopy); #ifdef ENABLE_SCREENCOPY_DMABUF if (gbm_device) { gbm_device_destroy(gbm_device); @@ -1993,6 +2010,7 @@ int main(int argc, char* argv[]) ctl_server_failure: capture_failure: +screencopy_failure: nvnc_display_unref(self.nvnc_display); nvnc_close(self.nvnc); nvnc_failure: diff --git a/src/screencopy-interface.c b/src/screencopy-interface.c new file mode 100644 index 0000000..53131b1 --- /dev/null +++ b/src/screencopy-interface.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "screencopy-interface.h" + +#include + +struct screencopy* screencopy_create(struct screencopy_impl* impl, + struct wl_output* output, bool render_cursor) +{ + return impl->create(output, render_cursor); +} + +struct screencopy* screencopy_create_cursor(struct screencopy_impl* impl, + struct wl_output* output) +{ + return impl->create_cursor ? impl->create_cursor(output) : NULL; +} + +void screencopy_destroy(struct screencopy* self) +{ + self->impl->destroy(self); +} + +int screencopy_start(struct screencopy* self, bool immediate) +{ + return self->impl->start(self, immediate); +} + +void screencopy_stop(struct screencopy* self) +{ + self->impl->stop(self); +} diff --git a/src/screencopy.c b/src/screencopy.c index afde112..49b5fa1 100644 --- a/src/screencopy.c +++ b/src/screencopy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 - 2020 Andri Yngvason + * Copyright (c) 2019 - 2022 Andri Yngvason * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +27,7 @@ #include "wlr-screencopy-unstable-v1.h" #include "buffer.h" #include "shm.h" -#include "screencopy.h" +#include "screencopy-interface.h" #include "smooth.h" #include "time-util.h" #include "usdt.h" @@ -37,11 +36,52 @@ #define DELAY_SMOOTHER_TIME_CONSTANT 0.5 // s -static void screencopy__stop(struct screencopy* self) +extern struct zwlr_screencopy_manager_v1* screencopy_manager; + +enum wlr_screencopy_status { + WLR_SCREENCOPY_STOPPED = 0, + WLR_SCREENCOPY_IN_PROGRESS, + WLR_SCREENCOPY_FAILED, + WLR_SCREENCOPY_FATAL, + WLR_SCREENCOPY_DONE, +}; + +struct wlr_screencopy { + struct screencopy parent; + + enum wlr_screencopy_status status; + + struct wv_buffer_pool* pool; + struct wv_buffer* front; + struct wv_buffer* back; + + struct zwlr_screencopy_frame_v1* frame; + + uint64_t last_time; + uint64_t start_time; + struct aml_timer* timer; + + struct smooth delay_smoother; + double delay; + bool is_immediate_copy; + bool overlay_cursor; + struct wl_output* wl_output; + + uint32_t wl_shm_width, wl_shm_height, wl_shm_stride; + enum wl_shm_format wl_shm_format; + + bool have_linux_dmabuf; + uint32_t dmabuf_width, dmabuf_height; + uint32_t fourcc; +}; + +struct screencopy_impl wlr_screencopy_impl; + +static void screencopy__stop(struct wlr_screencopy* self) { aml_stop(aml_get_default(), self->timer); - self->status = SCREENCOPY_STOPPED; + self->status = WLR_SCREENCOPY_STOPPED; if (self->frame) { zwlr_screencopy_frame_v1_destroy(self->frame); @@ -49,8 +89,10 @@ static void screencopy__stop(struct screencopy* self) } } -void screencopy_stop(struct screencopy* self) +void wlr_screencopy_stop(struct screencopy* ptr) { + struct wlr_screencopy* self = (struct wlr_screencopy*)ptr; + if (self->front) wv_buffer_pool_release(self->pool, self->front); self->front = NULL; @@ -63,7 +105,7 @@ static void screencopy_linux_dmabuf(void* data, uint32_t format, uint32_t width, uint32_t height) { #ifdef ENABLE_SCREENCOPY_DMABUF - struct screencopy* self = data; + struct wlr_screencopy* self = data; if (!(wv_buffer_get_available_types() & WV_BUFFER_DMABUF)) return; @@ -78,12 +120,12 @@ static void screencopy_linux_dmabuf(void* data, static void screencopy_buffer_done(void* data, struct zwlr_screencopy_frame_v1* frame) { - struct screencopy* self = data; + struct wlr_screencopy* self = data; uint32_t width, height, stride, fourcc; enum wv_buffer_type type = WV_BUFFER_UNSPEC; #ifdef ENABLE_SCREENCOPY_DMABUF - if (self->have_linux_dmabuf && self->enable_linux_dmabuf) { + if (self->have_linux_dmabuf && self->parent.enable_linux_dmabuf) { width = self->dmabuf_width; height = self->dmabuf_height; stride = 0; @@ -104,8 +146,8 @@ static void screencopy_buffer_done(void* data, struct wv_buffer* buffer = wv_buffer_pool_acquire(self->pool); if (!buffer) { screencopy__stop(self); - self->status = SCREENCOPY_FATAL; - self->on_done(self); + self->status = WLR_SCREENCOPY_FATAL; + self->parent.on_done(SCREENCOPY_FATAL, NULL, self->parent.userdata); return; } @@ -124,14 +166,14 @@ static void screencopy_buffer(void* data, enum wl_shm_format format, uint32_t width, uint32_t height, uint32_t stride) { - struct screencopy* self = data; + struct wlr_screencopy* self = data; self->wl_shm_format = format; self->wl_shm_width = width; self->wl_shm_height = height; self->wl_shm_stride = stride; - int version = zwlr_screencopy_manager_v1_get_version(self->manager); + int version = zwlr_screencopy_manager_v1_get_version(screencopy_manager); if (version < 3) { self->have_linux_dmabuf = false; screencopy_buffer_done(data, frame); @@ -145,7 +187,7 @@ static void screencopy_flags(void* data, { (void)frame; - struct screencopy* self = data; + struct wlr_screencopy* self = data; self->front->y_inverted = !!(flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT); @@ -155,7 +197,11 @@ static void screencopy_ready(void* data, struct zwlr_screencopy_frame_v1* frame, uint32_t sec_hi, uint32_t sec_lo, uint32_t nsec) { - struct screencopy* self = data; + (void)sec_hi; + (void)sec_lo; + (void)nsec; + + struct wlr_screencopy* self = data; uint64_t sec = (uint64_t)sec_hi << 32 | (uint64_t)sec_lo; uint64_t pts = sec * UINT64_C(1000000) + (uint64_t)nsec / UINT64_C(1000); @@ -179,14 +225,16 @@ static void screencopy_ready(void* data, nvnc_fb_set_pts(self->back->nvnc_fb, pts); - self->status = SCREENCOPY_DONE; - self->on_done(self); + self->status = WLR_SCREENCOPY_DONE; + self->parent.on_done(SCREENCOPY_DONE, self->back, self->parent.userdata); + + self->back = NULL; } static void screencopy_failed(void* data, struct zwlr_screencopy_frame_v1* frame) { - struct screencopy* self = data; + struct wlr_screencopy* self = data; DTRACE_PROBE1(wayvnc, screencopy_failed, self); @@ -196,8 +244,8 @@ static void screencopy_failed(void* data, wv_buffer_pool_release(self->pool, self->front); self->front = NULL; - self->status = SCREENCOPY_FAILED; - self->on_done(self); + self->status = WLR_SCREENCOPY_FAILED; + self->parent.on_done(SCREENCOPY_FAILED, NULL, self->parent.userdata); } static void screencopy_damage(void* data, @@ -205,14 +253,14 @@ static void screencopy_damage(void* data, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { - struct screencopy* self = data; + struct wlr_screencopy* self = data; DTRACE_PROBE1(wayvnc, screencopy_damage, self); wv_buffer_damage_rect(self->front, x, y, width, height); } -static int screencopy__start_capture(struct screencopy* self) +static int screencopy__start_capture(struct wlr_screencopy* self) { DTRACE_PROBE1(wayvnc, screencopy_start, self); @@ -228,8 +276,9 @@ static int screencopy__start_capture(struct screencopy* self) self->start_time = gettime_us(); - self->frame = zwlr_screencopy_manager_v1_capture_output(self->manager, - self->overlay_cursor, self->wl_output); + self->frame = zwlr_screencopy_manager_v1_capture_output( + screencopy_manager, self->overlay_cursor, + self->wl_output); if (!self->frame) return -1; @@ -241,23 +290,25 @@ static int screencopy__start_capture(struct screencopy* self) static void screencopy__poll(void* obj) { - struct screencopy* self = aml_get_userdata(obj); + struct wlr_screencopy* self = aml_get_userdata(obj); screencopy__start_capture(self); } -static int screencopy__start(struct screencopy* self, bool is_immediate_copy) +static int wlr_screencopy_start(struct screencopy* ptr, bool is_immediate_copy) { - if (self->status == SCREENCOPY_IN_PROGRESS) + struct wlr_screencopy* self = (struct wlr_screencopy*)ptr; + + if (self->status == WLR_SCREENCOPY_IN_PROGRESS) return -1; self->is_immediate_copy = is_immediate_copy; uint64_t now = gettime_us(); double dt = (now - self->last_time) * 1.0e-6; - int32_t time_left = (1.0 / self->rate_limit - dt - self->delay) * 1.0e6; + int32_t time_left = (1.0 / ptr->rate_limit - dt - self->delay) * 1.0e3; - self->status = SCREENCOPY_IN_PROGRESS; + self->status = WLR_SCREENCOPY_IN_PROGRESS; if (time_left > 0) { aml_set_duration(self->timer, time_left); @@ -267,18 +318,19 @@ static int screencopy__start(struct screencopy* self, bool is_immediate_copy) return screencopy__start_capture(self); } -int screencopy_start(struct screencopy* self) +static struct screencopy* wlr_screencopy_create(struct wl_output* output, + bool render_cursor) { - return screencopy__start(self, false); -} + struct wlr_screencopy* self = calloc(1, sizeof(*self)); + if (!self) + return NULL; -int screencopy_start_immediate(struct screencopy* self) -{ - return screencopy__start(self, true); -} + self->parent.impl = &wlr_screencopy_impl; + self->parent.rate_limit = 30; + + self->wl_output = output; + self->overlay_cursor = render_cursor; -void screencopy_init(struct screencopy* self) -{ self->pool = wv_buffer_pool_create(0, 0, 0, 0, 0); assert(self->pool); @@ -286,10 +338,13 @@ void screencopy_init(struct screencopy* self) assert(self->timer); self->delay_smoother.time_constant = DELAY_SMOOTHER_TIME_CONSTANT; + + return (struct screencopy*)self; } -void screencopy_destroy(struct screencopy* self) +static void wlr_screencopy_destroy(struct screencopy* ptr) { + struct wlr_screencopy* self = (struct wlr_screencopy*)ptr; aml_stop(aml_get_default(), self->timer); aml_unref(self->timer); @@ -303,3 +358,10 @@ void screencopy_destroy(struct screencopy* self) wv_buffer_pool_destroy(self->pool); } + +struct screencopy_impl wlr_screencopy_impl = { + .create = wlr_screencopy_create, + .destroy = wlr_screencopy_destroy, + .start = wlr_screencopy_start, + .stop = wlr_screencopy_stop, +};