diff --git a/include/frame-capture.h b/include/frame-capture.h new file mode 100644 index 0000000..3957799 --- /dev/null +++ b/include/frame-capture.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include + +struct wl_output; + +enum frame_capture_status { + CAPTURE_STOPPED = 0, + CAPTURE_IN_PROGRESS, + CAPTURE_FAILED, + CAPTURE_FATAL, + CAPTURE_DONE, +}; + +struct frame_capture { + enum frame_capture_status status; + + bool overlay_cursor; + struct wl_output* wl_output; + + void* userdata; + void (*on_done)(struct frame_capture*); + + struct { + uint32_t fourcc_format; + uint32_t width; + uint32_t height; + uint32_t stride; + } frame_info; + + struct { + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; + } damage_hint; + + struct { + int (*start)(struct frame_capture*); + void (*stop)(struct frame_capture*); + } backend; +}; + +static inline int frame_capture_start(struct frame_capture* self) +{ + return self->backend.start(self); +} + +static inline void frame_capture_stop(struct frame_capture* self) +{ + self->backend.stop(self); +} diff --git a/include/screencopy.h b/include/screencopy.h index e821837..10949ea 100644 --- a/include/screencopy.h +++ b/include/screencopy.h @@ -2,6 +2,7 @@ #include #include "wlr-screencopy-unstable-v1.h" +#include "frame-capture.h" struct zwlr_screencopy_manager_v1; struct zwlr_screencopy_frame_v1; @@ -17,6 +18,8 @@ enum screencopy_status { }; struct screencopy { + struct frame_capture frame_capture; + struct wl_shm* wl_shm; struct wl_buffer* buffer; @@ -25,26 +28,6 @@ struct screencopy { struct zwlr_screencopy_manager_v1* manager; struct zwlr_screencopy_frame_v1* frame; - - bool overlay_cursor; - struct wl_output* output; - enum screencopy_status status; - void (*on_done)(struct screencopy*); - - enum wl_shm_format format; - uint32_t width; - uint32_t height; - uint32_t stride; - - struct { - uint32_t x; - uint32_t y; - uint32_t width; - uint32_t height; - } damage; - - void* userdata; }; -int screencopy_start(struct screencopy* self); -void screencopy_stop(struct screencopy* self); +void screencopy_init(struct screencopy* self); diff --git a/src/main.c b/src/main.c index a45084c..506eead 100644 --- a/src/main.c +++ b/src/main.c @@ -58,6 +58,7 @@ struct wayvnc { struct dmabuf_capture dmabuf_backend; struct screencopy screencopy_backend; + struct frame_capture* capture_backend; uv_poll_t wayland_poller; uv_prepare_t flusher; @@ -73,7 +74,7 @@ struct wayvnc { }; void on_capture_done(struct dmabuf_capture* capture); -void on_screencopy_done(struct screencopy* capture); +void on_screencopy_done(struct frame_capture* capture); static void output_handle_geometry(void* data, struct wl_output* wl_output, int32_t x, int32_t y, int32_t phys_width, @@ -243,8 +244,8 @@ static int init_wayland(struct wayvnc* self) self->dmabuf_backend.on_done = on_capture_done; self->dmabuf_backend.userdata = self; - self->screencopy_backend.on_done = on_screencopy_done; - self->screencopy_backend.userdata = self; + self->screencopy_backend.frame_capture.on_done = on_screencopy_done; + self->screencopy_backend.frame_capture.userdata = self; return 0; @@ -262,7 +263,8 @@ int wayvnc_select_first_output(struct wayvnc* self) wl_list_for_each(out, &self->outputs, link) { self->selected_output = out; self->dmabuf_backend.output = out->wl_output; - self->screencopy_backend.output = out->wl_output; + self->screencopy_backend.frame_capture.wl_output + = out->wl_output; return 0; } @@ -359,7 +361,7 @@ int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port) int wayvnc_start_capture(struct wayvnc* self) { - return screencopy_start(&self->screencopy_backend); + return frame_capture_start(self->capture_backend); // return dmabuf_capture_start(&self->dmabuf_backend); } @@ -388,10 +390,10 @@ void wayvnc_update_vnc(struct wayvnc* self, struct nvnc_fb* fb) self->current_fb = fb; if (self->last_fb) { - uint32_t hint_x = self->screencopy_backend.damage.x; - uint32_t hint_y = self->screencopy_backend.damage.y; - uint32_t hint_width = self->screencopy_backend.damage.width; - uint32_t hint_height = self->screencopy_backend.damage.height; + uint32_t hint_x = self->capture_backend->damage_hint.x; + uint32_t hint_y = self->capture_backend->damage_hint.y; + uint32_t hint_width = self->capture_backend->damage_hint.width; + uint32_t hint_height = self->capture_backend->damage_hint.height; nvnc_check_damage(self->current_fb, self->last_fb, hint_x, hint_y, hint_width, hint_height, @@ -428,9 +430,10 @@ void wayvnc_process_screen(struct wayvnc* self) uint32_t format = fourcc_from_gl_format(self->renderer.read_format); void* pixels = self->screencopy_backend.pixels; - uint32_t width = self->screencopy_backend.width; - uint32_t height = self->screencopy_backend.height; - uint32_t stride = self->screencopy_backend.stride; + + uint32_t width = self->capture_backend->frame_info.width; + uint32_t height = self->capture_backend->frame_info.height; + uint32_t stride = self->capture_backend->frame_info.stride; struct nvnc_fb* fb = nvnc_fb_new(width, height, format); void* addr = nvnc_fb_get_addr(fb); @@ -468,24 +471,26 @@ void on_capture_done(struct dmabuf_capture* capture) } } -void on_screencopy_done(struct screencopy* capture) +void on_screencopy_done(struct frame_capture* capture) { struct wayvnc* self = capture->userdata; switch (capture->status) { - case SCREENCOPY_STATUS_CAPTURING: + case CAPTURE_STOPPED: break; - case SCREENCOPY_STATUS_FATAL: + case CAPTURE_IN_PROGRESS: + break; + case CAPTURE_FATAL: log_error("Fatal error while capturing. Exiting...\n"); wayvnc_exit(); break; - case SCREENCOPY_STATUS_FAILED: + case CAPTURE_FAILED: if (wayvnc_start_capture(self) < 0) { log_error("Failed to start capture. Exiting...\n"); wayvnc_exit(); } break; - case SCREENCOPY_STATUS_DONE: + case CAPTURE_DONE: self->n_frames++; wayvnc_process_screen(self); break; @@ -526,6 +531,9 @@ int main(int argc, char* argv[]) if (init_nvnc(&self, "0.0.0.0", 5900) < 0) goto nvnc_failure; + screencopy_init(&self.screencopy_backend); + self.capture_backend = &self.screencopy_backend.frame_capture; + if (wayvnc_start_capture(&self) < 0) goto capture_failure; diff --git a/src/screencopy.c b/src/screencopy.c index 1c70ca7..5605430 100644 --- a/src/screencopy.c +++ b/src/screencopy.c @@ -20,10 +20,20 @@ #include #include #include +#include #include "shm.h" #include "screencopy.h" +static uint32_t fourcc_from_wl_shm(enum wl_shm_format in) +{ + switch (in) { + case WL_SHM_FORMAT_ARGB8888: return DRM_FORMAT_ARGB8888; + case WL_SHM_FORMAT_XRGB8888: return DRM_FORMAT_XRGB8888; + default: return in; + } +} + static int screencopy_buffer_init(struct screencopy* self, enum wl_shm_format format, uint32_t width, uint32_t height, uint32_t stride) @@ -66,8 +76,10 @@ mmap_failure: return -1; } -void screencopy_stop(struct screencopy* self) +static void screencopy_stop(struct frame_capture* fc) { + struct screencopy* self = (void*)fc; + if (self->frame) { zwlr_screencopy_frame_v1_destroy(self->frame); self->frame = NULL; @@ -82,15 +94,16 @@ static void screencopy_buffer(void* data, struct screencopy* self = data; if (screencopy_buffer_init(self, format, width, height, stride) < 0) { - self->status = SCREENCOPY_STATUS_FATAL; - screencopy_stop(self); - self->on_done(self); + self->frame_capture.status = CAPTURE_FATAL; + screencopy_stop(&self->frame_capture); + self->frame_capture.on_done(&self->frame_capture); } - self->format = format; - self->width = width; - self->height = height; - self->stride = stride; + self->frame_capture.frame_info.fourcc_format = + fourcc_from_wl_shm(format); + self->frame_capture.frame_info.width = width; + self->frame_capture.frame_info.height = height; + self->frame_capture.frame_info.stride = stride; zwlr_screencopy_frame_v1_copy_with_damage(self->frame, self->buffer); } @@ -115,18 +128,21 @@ static void screencopy_ready(void* data, (void)nsec; struct screencopy* self = data; - screencopy_stop(self); - self->status = SCREENCOPY_STATUS_DONE; - self->on_done(self); + + screencopy_stop(&self->frame_capture); + + self->frame_capture.status = CAPTURE_DONE; + self->frame_capture.on_done(&self->frame_capture); } static void screencopy_failed(void* data, struct zwlr_screencopy_frame_v1* frame) { struct screencopy* self = data; - screencopy_stop(self); - self->status = SCREENCOPY_STATUS_FAILED; - self->on_done(self); + + screencopy_stop(&self->frame_capture); + self->frame_capture.status = CAPTURE_FAILED; + self->frame_capture.on_done(&self->frame_capture); } static void screencopy_damage(void* data, @@ -136,14 +152,16 @@ static void screencopy_damage(void* data, { struct screencopy* self = data; - self->damage.x = x; - self->damage.y = y; - self->damage.width = width; - self->damage.height = height; + self->frame_capture.damage_hint.x = x; + self->frame_capture.damage_hint.y = y; + self->frame_capture.damage_hint.width = width; + self->frame_capture.damage_hint.height = height; } -int screencopy_start(struct screencopy* self) +static int screencopy_start(struct frame_capture* fc) { + struct screencopy* self = (void*)fc; + static const struct zwlr_screencopy_frame_v1_listener frame_listener = { .buffer = screencopy_buffer, .flags = screencopy_flags, @@ -154,14 +172,20 @@ int screencopy_start(struct screencopy* self) self->frame = zwlr_screencopy_manager_v1_capture_output(self->manager, - self->overlay_cursor, - self->output); + fc->overlay_cursor, + fc->wl_output); if (!self->frame) return -1; zwlr_screencopy_frame_v1_add_listener(self->frame, &frame_listener, self); - self->status = SCREENCOPY_STATUS_CAPTURING; + fc->status = CAPTURE_IN_PROGRESS; return 0; } + +void screencopy_init(struct screencopy* self) +{ + self->frame_capture.backend.start = screencopy_start; + self->frame_capture.backend.stop = screencopy_stop; +}