Remove frame-capture abstraction
parent
b0ec79acf8
commit
2b522ee596
|
@ -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);
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "wlr-screencopy-unstable-v1.h"
|
||||
#include "frame-capture.h"
|
||||
#include "smooth.h"
|
||||
#include "buffer.h"
|
||||
|
||||
|
@ -32,14 +31,15 @@ struct aml_timer;
|
|||
struct renderer;
|
||||
|
||||
enum screencopy_status {
|
||||
SCREENCOPY_STATUS_CAPTURING = 0,
|
||||
SCREENCOPY_STATUS_FATAL,
|
||||
SCREENCOPY_STATUS_FAILED,
|
||||
SCREENCOPY_STATUS_DONE,
|
||||
SCREENCOPY_STOPPED = 0,
|
||||
SCREENCOPY_IN_PROGRESS,
|
||||
SCREENCOPY_FAILED,
|
||||
SCREENCOPY_FATAL,
|
||||
SCREENCOPY_DONE,
|
||||
};
|
||||
|
||||
struct screencopy {
|
||||
struct frame_capture frame_capture;
|
||||
enum screencopy_status status;
|
||||
|
||||
struct wv_buffer_pool* pool;
|
||||
struct wv_buffer* front;
|
||||
|
@ -49,6 +49,9 @@ struct screencopy {
|
|||
struct zwlr_screencopy_frame_v1* frame;
|
||||
int version;
|
||||
|
||||
void* userdata;
|
||||
void (*on_done)(struct screencopy*);
|
||||
|
||||
uint64_t last_time;
|
||||
uint64_t start_time;
|
||||
struct aml_timer* timer;
|
||||
|
@ -56,6 +59,8 @@ struct screencopy {
|
|||
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;
|
||||
|
@ -67,3 +72,8 @@ struct screencopy {
|
|||
|
||||
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);
|
||||
|
|
81
src/main.c
81
src/main.c
|
@ -37,7 +37,6 @@
|
|||
#include <gbm.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "frame-capture.h"
|
||||
#include "wlr-screencopy-unstable-v1.h"
|
||||
#include "wlr-virtual-pointer-unstable-v1.h"
|
||||
#include "virtual-keyboard-unstable-v1.h"
|
||||
|
@ -76,8 +75,7 @@ struct wayvnc {
|
|||
const struct output* selected_output;
|
||||
const struct seat* selected_seat;
|
||||
|
||||
struct screencopy screencopy_backend;
|
||||
struct frame_capture* capture_backend;
|
||||
struct screencopy screencopy;
|
||||
struct pointer pointer_backend;
|
||||
struct keyboard keyboard_backend;
|
||||
|
||||
|
@ -95,7 +93,7 @@ struct wayvnc {
|
|||
};
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
self->screencopy_backend.manager =
|
||||
self->screencopy.manager =
|
||||
wl_registry_bind(registry, id,
|
||||
&zwlr_screencopy_manager_v1_interface,
|
||||
version);
|
||||
self->screencopy_backend.version = version;
|
||||
self->screencopy.version = version;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -251,8 +249,8 @@ void wayvnc_destroy(struct wayvnc* self)
|
|||
zwlr_virtual_pointer_manager_v1_destroy(self->pointer_manager);
|
||||
pointer_destroy(&self->pointer_backend);
|
||||
|
||||
if (self->screencopy_backend.manager)
|
||||
zwlr_screencopy_manager_v1_destroy(self->screencopy_backend.manager);
|
||||
if (self->screencopy.manager)
|
||||
zwlr_screencopy_manager_v1_destroy(self->screencopy.manager);
|
||||
|
||||
wl_display_disconnect(self->display);
|
||||
}
|
||||
|
@ -307,13 +305,13 @@ static int init_wayland(struct wayvnc* self)
|
|||
wl_display_dispatch(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");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
self->screencopy_backend.frame_capture.on_done = on_capture_done;
|
||||
self->screencopy_backend.frame_capture.userdata = self;
|
||||
self->screencopy.on_done = on_capture_done;
|
||||
self->screencopy.userdata = self;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -454,9 +452,14 @@ failure:
|
|||
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)
|
||||
|
@ -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 wayvnc* self = nvnc_get_userdata(nvnc);
|
||||
|
||||
if (!self->screencopy_backend.back)
|
||||
if (!self->screencopy.back)
|
||||
return;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
damage_refinery_init(&self->damage_refinery,
|
||||
self->screencopy_backend.back->width,
|
||||
self->screencopy_backend.back->height);
|
||||
self->screencopy.back->width,
|
||||
self->screencopy.back->height);
|
||||
} else {
|
||||
// TODO: Reallocate
|
||||
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(&refined);
|
||||
damage_refine(&self->damage_refinery, &refined,
|
||||
&self->screencopy_backend.back->damage,
|
||||
self->screencopy_backend.back);
|
||||
&self->screencopy.back->damage,
|
||||
self->screencopy.back);
|
||||
wv_region_transform(&txdamage, &refined,
|
||||
self->selected_output->transform,
|
||||
self->selected_output->width,
|
||||
|
@ -513,32 +516,32 @@ void wayvnc_process_frame(struct wayvnc* self)
|
|||
pixman_region_fini(&refined);
|
||||
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");
|
||||
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) {
|
||||
case CAPTURE_STOPPED:
|
||||
switch (sc->status) {
|
||||
case SCREENCOPY_STOPPED:
|
||||
break;
|
||||
case CAPTURE_IN_PROGRESS:
|
||||
case SCREENCOPY_IN_PROGRESS:
|
||||
break;
|
||||
case CAPTURE_FATAL:
|
||||
case SCREENCOPY_FATAL:
|
||||
log_error("Fatal error while capturing. Exiting...\n");
|
||||
wayvnc_exit(self);
|
||||
break;
|
||||
case CAPTURE_FAILED:
|
||||
if (wayvnc_start_capture(self, CAPTURE_NOW) < 0) {
|
||||
case SCREENCOPY_FAILED:
|
||||
if (wayvnc_start_capture_immediate(self) < 0) {
|
||||
log_error("Failed to start capture. Exiting...\n");
|
||||
wayvnc_exit(self);
|
||||
}
|
||||
break;
|
||||
case CAPTURE_DONE:
|
||||
case SCREENCOPY_DONE:
|
||||
wayvnc_process_frame(self);
|
||||
break;
|
||||
}
|
||||
|
@ -722,7 +725,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
self.selected_output = out;
|
||||
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 =
|
||||
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)
|
||||
goto nvnc_failure;
|
||||
|
||||
if (self.screencopy_backend.manager)
|
||||
screencopy_init(&self.screencopy_backend);
|
||||
if (self.screencopy.manager)
|
||||
screencopy_init(&self.screencopy);
|
||||
|
||||
if (!self.screencopy_backend.manager) {
|
||||
if (!self.screencopy.manager) {
|
||||
log_error("screencopy is not supported by compositor\n");
|
||||
goto capture_failure;
|
||||
}
|
||||
|
||||
self.capture_backend = &self.screencopy_backend.frame_capture;
|
||||
|
||||
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;
|
||||
|
||||
wl_display_dispatch(self.display);
|
||||
|
@ -791,7 +792,7 @@ int main(int argc, char* argv[])
|
|||
aml_dispatch(aml);
|
||||
}
|
||||
|
||||
frame_capture_stop(self.capture_backend);
|
||||
screencopy_stop(&self.screencopy);
|
||||
|
||||
if (self.buffer) nvnc_fb_unref(self.buffer);
|
||||
|
||||
|
@ -801,8 +802,8 @@ int main(int argc, char* argv[])
|
|||
nvnc_close(self.nvnc);
|
||||
if (zwp_linux_dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf);
|
||||
if (self.screencopy_backend.manager)
|
||||
screencopy_destroy(&self.screencopy_backend);
|
||||
if (self.screencopy.manager)
|
||||
screencopy_destroy(&self.screencopy);
|
||||
wayvnc_destroy(&self);
|
||||
aml_unref(aml);
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include "wlr-screencopy-unstable-v1.h"
|
||||
#include "buffer.h"
|
||||
#include "frame-capture.h"
|
||||
#include "shm.h"
|
||||
#include "screencopy.h"
|
||||
#include "smooth.h"
|
||||
|
@ -36,13 +35,12 @@
|
|||
#define RATE_LIMIT 20.0 // Hz
|
||||
#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);
|
||||
|
||||
self->frame_capture.status = CAPTURE_STOPPED;
|
||||
self->status = SCREENCOPY_STOPPED;
|
||||
|
||||
if (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);
|
||||
if (!buffer) {
|
||||
self->frame_capture.status = CAPTURE_FATAL;
|
||||
screencopy_stop(&self->frame_capture);
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
screencopy_stop(self);
|
||||
self->status = SCREENCOPY_FATAL;
|
||||
self->on_done(self);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -97,11 +95,6 @@ static void screencopy_buffer_done(void* data,
|
|||
assert(!self->front);
|
||||
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)
|
||||
zwlr_screencopy_frame_v1_copy(self->frame, buffer->wl_buffer);
|
||||
else
|
||||
|
@ -150,7 +143,7 @@ static void screencopy_ready(void* data,
|
|||
|
||||
DTRACE_PROBE1(wayvnc, screencopy_ready, self);
|
||||
|
||||
screencopy_stop(&self->frame_capture);
|
||||
screencopy_stop(self);
|
||||
|
||||
self->last_time = gettime_us();
|
||||
|
||||
|
@ -167,8 +160,8 @@ static void screencopy_ready(void* data,
|
|||
|
||||
wv_buffer_map(self->back);
|
||||
|
||||
self->frame_capture.status = CAPTURE_DONE;
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
self->status = SCREENCOPY_DONE;
|
||||
self->on_done(self);
|
||||
}
|
||||
|
||||
static void screencopy_failed(void* data,
|
||||
|
@ -178,9 +171,9 @@ static void screencopy_failed(void* data,
|
|||
|
||||
DTRACE_PROBE1(wayvnc, screencopy_failed, self);
|
||||
|
||||
screencopy_stop(&self->frame_capture);
|
||||
self->frame_capture.status = CAPTURE_FAILED;
|
||||
self->frame_capture.on_done(&self->frame_capture);
|
||||
screencopy_stop(self);
|
||||
self->status = SCREENCOPY_FAILED;
|
||||
self->on_done(self);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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->frame =
|
||||
zwlr_screencopy_manager_v1_capture_output(self->manager,
|
||||
fc->overlay_cursor,
|
||||
fc->wl_output);
|
||||
self->frame = zwlr_screencopy_manager_v1_capture_output(self->manager,
|
||||
self->overlay_cursor, self->wl_output);
|
||||
if (!self->frame)
|
||||
return -1;
|
||||
|
||||
|
@ -229,38 +218,40 @@ static int screencopy__start_capture(struct frame_capture* fc)
|
|||
static void screencopy__poll(void* 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,
|
||||
enum frame_capture_options options)
|
||||
static int screencopy__start(struct screencopy* self, bool is_immediate_copy)
|
||||
{
|
||||
struct screencopy* self = (void*)fc;
|
||||
|
||||
if (fc->status == CAPTURE_IN_PROGRESS)
|
||||
if (self->status == SCREENCOPY_IN_PROGRESS)
|
||||
return -1;
|
||||
|
||||
self->is_immediate_copy = !!(options & CAPTURE_NOW);
|
||||
self->is_immediate_copy = is_immediate_copy;
|
||||
|
||||
uint64_t now = gettime_us();
|
||||
double dt = (now - self->last_time) * 1.0e-6;
|
||||
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) {
|
||||
aml_set_duration(self->timer, time_left);
|
||||
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,
|
||||
struct renderer* renderer, struct nvnc_fb* fb)
|
||||
int screencopy_start(struct screencopy* self)
|
||||
{
|
||||
return screencopy__start(self, false);
|
||||
}
|
||||
|
||||
int screencopy_start_immediate(struct screencopy* self)
|
||||
{
|
||||
return screencopy__start(self, true);
|
||||
}
|
||||
|
||||
void screencopy_init(struct screencopy* self)
|
||||
|
@ -272,10 +263,6 @@ void screencopy_init(struct screencopy* self)
|
|||
assert(self->timer);
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue