Remove frame-capture abstraction

pull/55/head
Andri Yngvason 2020-06-26 21:44:58 +00:00
parent b0ec79acf8
commit 2b522ee596
4 changed files with 84 additions and 163 deletions

View File

@ -1,77 +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 <stdint.h>
#include <stdbool.h>
struct wl_output;
struct nvnc_fb;
struct renderer;
enum frame_capture_status {
CAPTURE_STOPPED = 0,
CAPTURE_IN_PROGRESS,
CAPTURE_FAILED,
CAPTURE_FATAL,
CAPTURE_DONE,
};
enum frame_capture_options {
CAPTURE_NOW = 1 << 0,
};
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 {
void (*render)(struct frame_capture*, struct renderer*,
struct nvnc_fb* fb);
int (*start)(struct frame_capture*, enum frame_capture_options);
void (*stop)(struct frame_capture*);
} backend;
};
static inline int frame_capture_start(struct frame_capture* self, enum frame_capture_options options)
{
return self->backend.start(self, options);
}
static inline void frame_capture_stop(struct frame_capture* self)
{
self->backend.stop(self);
}
static inline void frame_capture_render(struct frame_capture* self,
struct renderer* renderer,
struct nvnc_fb* fb)
{
return self->backend.render(self, renderer, fb);
}

View File

@ -19,7 +19,6 @@
#include <stdbool.h> #include <stdbool.h>
#include "wlr-screencopy-unstable-v1.h" #include "wlr-screencopy-unstable-v1.h"
#include "frame-capture.h"
#include "smooth.h" #include "smooth.h"
#include "buffer.h" #include "buffer.h"
@ -32,14 +31,15 @@ struct aml_timer;
struct renderer; struct renderer;
enum screencopy_status { enum screencopy_status {
SCREENCOPY_STATUS_CAPTURING = 0, SCREENCOPY_STOPPED = 0,
SCREENCOPY_STATUS_FATAL, SCREENCOPY_IN_PROGRESS,
SCREENCOPY_STATUS_FAILED, SCREENCOPY_FAILED,
SCREENCOPY_STATUS_DONE, SCREENCOPY_FATAL,
SCREENCOPY_DONE,
}; };
struct screencopy { struct screencopy {
struct frame_capture frame_capture; enum screencopy_status status;
struct wv_buffer_pool* pool; struct wv_buffer_pool* pool;
struct wv_buffer* front; struct wv_buffer* front;
@ -49,6 +49,9 @@ struct screencopy {
struct zwlr_screencopy_frame_v1* frame; struct zwlr_screencopy_frame_v1* frame;
int version; int version;
void* userdata;
void (*on_done)(struct screencopy*);
uint64_t last_time; uint64_t last_time;
uint64_t start_time; uint64_t start_time;
struct aml_timer* timer; struct aml_timer* timer;
@ -56,6 +59,8 @@ struct screencopy {
struct smooth delay_smoother; struct smooth delay_smoother;
double delay; double delay;
bool is_immediate_copy; bool is_immediate_copy;
bool overlay_cursor;
struct wl_output* wl_output;
uint32_t wl_shm_width, wl_shm_height, wl_shm_stride; uint32_t wl_shm_width, wl_shm_height, wl_shm_stride;
enum wl_shm_format wl_shm_format; enum wl_shm_format wl_shm_format;
@ -67,3 +72,8 @@ struct screencopy {
void screencopy_init(struct screencopy* self); void screencopy_init(struct screencopy* self);
void screencopy_destroy(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);

View File

@ -37,7 +37,6 @@
#include <gbm.h> #include <gbm.h>
#include <xf86drm.h> #include <xf86drm.h>
#include "frame-capture.h"
#include "wlr-screencopy-unstable-v1.h" #include "wlr-screencopy-unstable-v1.h"
#include "wlr-virtual-pointer-unstable-v1.h" #include "wlr-virtual-pointer-unstable-v1.h"
#include "virtual-keyboard-unstable-v1.h" #include "virtual-keyboard-unstable-v1.h"
@ -76,8 +75,7 @@ struct wayvnc {
const struct output* selected_output; const struct output* selected_output;
const struct seat* selected_seat; const struct seat* selected_seat;
struct screencopy screencopy_backend; struct screencopy screencopy;
struct frame_capture* capture_backend;
struct pointer pointer_backend; struct pointer pointer_backend;
struct keyboard keyboard_backend; struct keyboard keyboard_backend;
@ -95,7 +93,7 @@ struct wayvnc {
}; };
void wayvnc_exit(struct wayvnc* self); void wayvnc_exit(struct wayvnc* self);
void on_capture_done(struct frame_capture* capture); void on_capture_done(struct screencopy* sc);
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb); static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
struct wl_shm* wl_shm = NULL; struct wl_shm* wl_shm = NULL;
@ -136,11 +134,11 @@ static void registry_add(void* data, struct wl_registry* registry,
} }
if (strcmp(interface, zwlr_screencopy_manager_v1_interface.name) == 0) { if (strcmp(interface, zwlr_screencopy_manager_v1_interface.name) == 0) {
self->screencopy_backend.manager = self->screencopy.manager =
wl_registry_bind(registry, id, wl_registry_bind(registry, id,
&zwlr_screencopy_manager_v1_interface, &zwlr_screencopy_manager_v1_interface,
version); version);
self->screencopy_backend.version = version; self->screencopy.version = version;
return; return;
} }
@ -251,8 +249,8 @@ void wayvnc_destroy(struct wayvnc* self)
zwlr_virtual_pointer_manager_v1_destroy(self->pointer_manager); zwlr_virtual_pointer_manager_v1_destroy(self->pointer_manager);
pointer_destroy(&self->pointer_backend); pointer_destroy(&self->pointer_backend);
if (self->screencopy_backend.manager) if (self->screencopy.manager)
zwlr_screencopy_manager_v1_destroy(self->screencopy_backend.manager); zwlr_screencopy_manager_v1_destroy(self->screencopy.manager);
wl_display_disconnect(self->display); wl_display_disconnect(self->display);
} }
@ -307,13 +305,13 @@ static int init_wayland(struct wayvnc* self)
wl_display_dispatch(self->display); wl_display_dispatch(self->display);
wl_display_roundtrip(self->display); wl_display_roundtrip(self->display);
if (!self->screencopy_backend.manager) { if (!self->screencopy.manager) {
log_error("Compositor doesn't support screencopy! Exiting.\n"); log_error("Compositor doesn't support screencopy! Exiting.\n");
goto failure; goto failure;
} }
self->screencopy_backend.frame_capture.on_done = on_capture_done; self->screencopy.on_done = on_capture_done;
self->screencopy_backend.frame_capture.userdata = self; self->screencopy.userdata = self;
return 0; return 0;
@ -454,9 +452,14 @@ failure:
return -1; return -1;
} }
int wayvnc_start_capture(struct wayvnc* self, enum frame_capture_options opt) int wayvnc_start_capture(struct wayvnc* self)
{ {
return frame_capture_start(self->capture_backend, opt); return screencopy_start(&self->screencopy);
}
int wayvnc_start_capture_immediate(struct wayvnc* self)
{
return screencopy_start_immediate(&self->screencopy);
} }
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb) static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
@ -464,11 +467,11 @@ static void on_render(struct nvnc_display* display, struct nvnc_fb* fb)
struct nvnc* nvnc = nvnc_display_get_server(display); struct nvnc* nvnc = nvnc_display_get_server(display);
struct wayvnc* self = nvnc_get_userdata(nvnc); struct wayvnc* self = nvnc_get_userdata(nvnc);
if (!self->screencopy_backend.back) if (!self->screencopy.back)
return; return;
enum wl_output_transform transform = self->selected_output->transform; enum wl_output_transform transform = self->selected_output->transform;
wv_pixman_render(fb, self->screencopy_backend.back, transform, wv_pixman_render(fb, self->screencopy.back, transform,
&self->current_damage); &self->current_damage);
pixman_region_clear(&self->current_damage); pixman_region_clear(&self->current_damage);
} }
@ -490,8 +493,8 @@ void wayvnc_process_frame(struct wayvnc* self)
nvnc_display_set_buffer(self->nvnc_display, self->buffer); nvnc_display_set_buffer(self->nvnc_display, self->buffer);
damage_refinery_init(&self->damage_refinery, damage_refinery_init(&self->damage_refinery,
self->screencopy_backend.back->width, self->screencopy.back->width,
self->screencopy_backend.back->height); self->screencopy.back->height);
} else { } else {
// TODO: Reallocate // TODO: Reallocate
assert(width == nvnc_fb_get_width(self->buffer)); assert(width == nvnc_fb_get_width(self->buffer));
@ -502,8 +505,8 @@ void wayvnc_process_frame(struct wayvnc* self)
pixman_region_init(&txdamage); pixman_region_init(&txdamage);
pixman_region_init(&refined); pixman_region_init(&refined);
damage_refine(&self->damage_refinery, &refined, damage_refine(&self->damage_refinery, &refined,
&self->screencopy_backend.back->damage, &self->screencopy.back->damage,
self->screencopy_backend.back); self->screencopy.back);
wv_region_transform(&txdamage, &refined, wv_region_transform(&txdamage, &refined,
self->selected_output->transform, self->selected_output->transform,
self->selected_output->width, self->selected_output->width,
@ -513,32 +516,32 @@ void wayvnc_process_frame(struct wayvnc* self)
pixman_region_fini(&refined); pixman_region_fini(&refined);
pixman_region_fini(&txdamage); pixman_region_fini(&txdamage);
if (wayvnc_start_capture(self, 0) < 0) { if (wayvnc_start_capture(self) < 0) {
log_error("Failed to start capture. Exiting...\n"); log_error("Failed to start capture. Exiting...\n");
wayvnc_exit(self); wayvnc_exit(self);
} }
} }
void on_capture_done(struct frame_capture* capture) void on_capture_done(struct screencopy* sc)
{ {
struct wayvnc* self = capture->userdata; struct wayvnc* self = sc->userdata;
switch (capture->status) { switch (sc->status) {
case CAPTURE_STOPPED: case SCREENCOPY_STOPPED:
break; break;
case CAPTURE_IN_PROGRESS: case SCREENCOPY_IN_PROGRESS:
break; break;
case CAPTURE_FATAL: case SCREENCOPY_FATAL:
log_error("Fatal error while capturing. Exiting...\n"); log_error("Fatal error while capturing. Exiting...\n");
wayvnc_exit(self); wayvnc_exit(self);
break; break;
case CAPTURE_FAILED: case SCREENCOPY_FAILED:
if (wayvnc_start_capture(self, CAPTURE_NOW) < 0) { if (wayvnc_start_capture_immediate(self) < 0) {
log_error("Failed to start capture. Exiting...\n"); log_error("Failed to start capture. Exiting...\n");
wayvnc_exit(self); wayvnc_exit(self);
} }
break; break;
case CAPTURE_DONE: case SCREENCOPY_DONE:
wayvnc_process_frame(self); wayvnc_process_frame(self);
break; break;
} }
@ -722,7 +725,7 @@ int main(int argc, char* argv[])
self.selected_output = out; self.selected_output = out;
self.selected_seat = seat; self.selected_seat = seat;
self.screencopy_backend.frame_capture.wl_output = out->wl_output; self.screencopy.wl_output = out->wl_output;
self.keyboard_backend.virtual_keyboard = self.keyboard_backend.virtual_keyboard =
zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
@ -766,21 +769,19 @@ int main(int argc, char* argv[])
if (init_nvnc(&self, address, port) < 0) if (init_nvnc(&self, address, port) < 0)
goto nvnc_failure; goto nvnc_failure;
if (self.screencopy_backend.manager) if (self.screencopy.manager)
screencopy_init(&self.screencopy_backend); screencopy_init(&self.screencopy);
if (!self.screencopy_backend.manager) { if (!self.screencopy.manager) {
log_error("screencopy is not supported by compositor\n"); log_error("screencopy is not supported by compositor\n");
goto capture_failure; goto capture_failure;
} }
self.capture_backend = &self.screencopy_backend.frame_capture;
pixman_region_init(&self.current_damage); pixman_region_init(&self.current_damage);
self.capture_backend->overlay_cursor = overlay_cursor; self.screencopy.overlay_cursor = overlay_cursor;
if (wayvnc_start_capture(&self, 0) < 0) if (wayvnc_start_capture(&self) < 0)
goto capture_failure; goto capture_failure;
wl_display_dispatch(self.display); wl_display_dispatch(self.display);
@ -791,7 +792,7 @@ int main(int argc, char* argv[])
aml_dispatch(aml); aml_dispatch(aml);
} }
frame_capture_stop(self.capture_backend); screencopy_stop(&self.screencopy);
if (self.buffer) nvnc_fb_unref(self.buffer); if (self.buffer) nvnc_fb_unref(self.buffer);
@ -801,8 +802,8 @@ int main(int argc, char* argv[])
nvnc_close(self.nvnc); nvnc_close(self.nvnc);
if (zwp_linux_dmabuf) if (zwp_linux_dmabuf)
zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf); zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf);
if (self.screencopy_backend.manager) if (self.screencopy.manager)
screencopy_destroy(&self.screencopy_backend); screencopy_destroy(&self.screencopy);
wayvnc_destroy(&self); wayvnc_destroy(&self);
aml_unref(aml); aml_unref(aml);

View File

@ -26,7 +26,6 @@
#include "wlr-screencopy-unstable-v1.h" #include "wlr-screencopy-unstable-v1.h"
#include "buffer.h" #include "buffer.h"
#include "frame-capture.h"
#include "shm.h" #include "shm.h"
#include "screencopy.h" #include "screencopy.h"
#include "smooth.h" #include "smooth.h"
@ -36,13 +35,12 @@
#define RATE_LIMIT 20.0 // Hz #define RATE_LIMIT 20.0 // Hz
#define DELAY_SMOOTHER_TIME_CONSTANT 0.5 // s #define DELAY_SMOOTHER_TIME_CONSTANT 0.5 // s
static void screencopy_stop(struct frame_capture* fc) void screencopy_stop(struct screencopy* self)
{ {
struct screencopy* self = (void*)fc;
aml_stop(aml_get_default(), self->timer); aml_stop(aml_get_default(), self->timer);
self->frame_capture.status = CAPTURE_STOPPED; self->status = SCREENCOPY_STOPPED;
if (self->frame) { if (self->frame) {
zwlr_screencopy_frame_v1_destroy(self->frame); zwlr_screencopy_frame_v1_destroy(self->frame);
@ -86,9 +84,9 @@ static void screencopy_buffer_done(void* data,
struct wv_buffer* buffer = wv_buffer_pool_acquire(self->pool); struct wv_buffer* buffer = wv_buffer_pool_acquire(self->pool);
if (!buffer) { if (!buffer) {
self->frame_capture.status = CAPTURE_FATAL; screencopy_stop(self);
screencopy_stop(&self->frame_capture); self->status = SCREENCOPY_FATAL;
self->frame_capture.on_done(&self->frame_capture); self->on_done(self);
return; return;
} }
@ -97,11 +95,6 @@ static void screencopy_buffer_done(void* data,
assert(!self->front); assert(!self->front);
self->front = buffer; self->front = buffer;
self->frame_capture.frame_info.fourcc_format = fourcc;
self->frame_capture.frame_info.width = width;
self->frame_capture.frame_info.height = height;
self->frame_capture.frame_info.stride = stride;
if (self->is_immediate_copy) if (self->is_immediate_copy)
zwlr_screencopy_frame_v1_copy(self->frame, buffer->wl_buffer); zwlr_screencopy_frame_v1_copy(self->frame, buffer->wl_buffer);
else else
@ -150,7 +143,7 @@ static void screencopy_ready(void* data,
DTRACE_PROBE1(wayvnc, screencopy_ready, self); DTRACE_PROBE1(wayvnc, screencopy_ready, self);
screencopy_stop(&self->frame_capture); screencopy_stop(self);
self->last_time = gettime_us(); self->last_time = gettime_us();
@ -167,8 +160,8 @@ static void screencopy_ready(void* data,
wv_buffer_map(self->back); wv_buffer_map(self->back);
self->frame_capture.status = CAPTURE_DONE; self->status = SCREENCOPY_DONE;
self->frame_capture.on_done(&self->frame_capture); self->on_done(self);
} }
static void screencopy_failed(void* data, static void screencopy_failed(void* data,
@ -178,9 +171,9 @@ static void screencopy_failed(void* data,
DTRACE_PROBE1(wayvnc, screencopy_failed, self); DTRACE_PROBE1(wayvnc, screencopy_failed, self);
screencopy_stop(&self->frame_capture); screencopy_stop(self);
self->frame_capture.status = CAPTURE_FAILED; self->status = SCREENCOPY_FAILED;
self->frame_capture.on_done(&self->frame_capture); self->on_done(self);
} }
static void screencopy_damage(void* data, static void screencopy_damage(void* data,
@ -195,10 +188,8 @@ static void screencopy_damage(void* data,
wv_buffer_damage_rect(self->front, x, y, width, height); wv_buffer_damage_rect(self->front, x, y, width, height);
} }
static int screencopy__start_capture(struct frame_capture* fc) static int screencopy__start_capture(struct screencopy* self)
{ {
struct screencopy* self = (void*)fc;
DTRACE_PROBE1(wayvnc, screencopy_start, self); DTRACE_PROBE1(wayvnc, screencopy_start, self);
static const struct zwlr_screencopy_frame_v1_listener frame_listener = { static const struct zwlr_screencopy_frame_v1_listener frame_listener = {
@ -213,10 +204,8 @@ static int screencopy__start_capture(struct frame_capture* fc)
self->start_time = gettime_us(); self->start_time = gettime_us();
self->frame = self->frame = zwlr_screencopy_manager_v1_capture_output(self->manager,
zwlr_screencopy_manager_v1_capture_output(self->manager, self->overlay_cursor, self->wl_output);
fc->overlay_cursor,
fc->wl_output);
if (!self->frame) if (!self->frame)
return -1; return -1;
@ -229,38 +218,40 @@ static int screencopy__start_capture(struct frame_capture* fc)
static void screencopy__poll(void* obj) static void screencopy__poll(void* obj)
{ {
struct screencopy* self = aml_get_userdata(obj); struct screencopy* self = aml_get_userdata(obj);
struct frame_capture* fc = (struct frame_capture*)self;
screencopy__start_capture(fc); screencopy__start_capture(self);
} }
static int screencopy_start(struct frame_capture* fc, static int screencopy__start(struct screencopy* self, bool is_immediate_copy)
enum frame_capture_options options)
{ {
struct screencopy* self = (void*)fc;
if (fc->status == CAPTURE_IN_PROGRESS) if (self->status == SCREENCOPY_IN_PROGRESS)
return -1; return -1;
self->is_immediate_copy = !!(options & CAPTURE_NOW); self->is_immediate_copy = is_immediate_copy;
uint64_t now = gettime_us(); uint64_t now = gettime_us();
double dt = (now - self->last_time) * 1.0e-6; double dt = (now - self->last_time) * 1.0e-6;
double time_left = (1.0 / RATE_LIMIT - dt - self->delay) * 1.0e3; double time_left = (1.0 / RATE_LIMIT - dt - self->delay) * 1.0e3;
fc->status = CAPTURE_IN_PROGRESS; self->status = SCREENCOPY_IN_PROGRESS;
if (time_left > 0) { if (time_left > 0) {
aml_set_duration(self->timer, time_left); aml_set_duration(self->timer, time_left);
return aml_start(aml_get_default(), self->timer); return aml_start(aml_get_default(), self->timer);
} }
return screencopy__start_capture(fc); return screencopy__start_capture(self);
} }
static void screencopy_render(struct frame_capture* fc, int screencopy_start(struct screencopy* self)
struct renderer* renderer, struct nvnc_fb* fb)
{ {
return screencopy__start(self, false);
}
int screencopy_start_immediate(struct screencopy* self)
{
return screencopy__start(self, true);
} }
void screencopy_init(struct screencopy* self) void screencopy_init(struct screencopy* self)
@ -272,10 +263,6 @@ void screencopy_init(struct screencopy* self)
assert(self->timer); assert(self->timer);
self->delay_smoother.time_constant = DELAY_SMOOTHER_TIME_CONSTANT; self->delay_smoother.time_constant = DELAY_SMOOTHER_TIME_CONSTANT;
self->frame_capture.backend.start = screencopy_start;
self->frame_capture.backend.stop = screencopy_stop;
self->frame_capture.backend.render = screencopy_render;
} }
void screencopy_destroy(struct screencopy* self) void screencopy_destroy(struct screencopy* self)