Create frame-capture backend framework

shader-damage
Andri Yngvason 2019-10-10 22:32:54 +00:00
parent e037e74756
commit ffda3c164c
4 changed files with 128 additions and 60 deletions

View File

@ -0,0 +1,53 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
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);
}

View File

@ -2,6 +2,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "wlr-screencopy-unstable-v1.h" #include "wlr-screencopy-unstable-v1.h"
#include "frame-capture.h"
struct zwlr_screencopy_manager_v1; struct zwlr_screencopy_manager_v1;
struct zwlr_screencopy_frame_v1; struct zwlr_screencopy_frame_v1;
@ -17,6 +18,8 @@ enum screencopy_status {
}; };
struct screencopy { struct screencopy {
struct frame_capture frame_capture;
struct wl_shm* wl_shm; struct wl_shm* wl_shm;
struct wl_buffer* buffer; struct wl_buffer* buffer;
@ -25,26 +28,6 @@ struct screencopy {
struct zwlr_screencopy_manager_v1* manager; struct zwlr_screencopy_manager_v1* manager;
struct zwlr_screencopy_frame_v1* frame; 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_init(struct screencopy* self);
void screencopy_stop(struct screencopy* self);

View File

@ -58,6 +58,7 @@ struct wayvnc {
struct dmabuf_capture dmabuf_backend; struct dmabuf_capture dmabuf_backend;
struct screencopy screencopy_backend; struct screencopy screencopy_backend;
struct frame_capture* capture_backend;
uv_poll_t wayland_poller; uv_poll_t wayland_poller;
uv_prepare_t flusher; uv_prepare_t flusher;
@ -73,7 +74,7 @@ struct wayvnc {
}; };
void on_capture_done(struct dmabuf_capture* capture); 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, static void output_handle_geometry(void* data, struct wl_output* wl_output,
int32_t x, int32_t y, int32_t phys_width, 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.on_done = on_capture_done;
self->dmabuf_backend.userdata = self; self->dmabuf_backend.userdata = self;
self->screencopy_backend.on_done = on_screencopy_done; self->screencopy_backend.frame_capture.on_done = on_screencopy_done;
self->screencopy_backend.userdata = self; self->screencopy_backend.frame_capture.userdata = self;
return 0; return 0;
@ -262,7 +263,8 @@ int wayvnc_select_first_output(struct wayvnc* self)
wl_list_for_each(out, &self->outputs, link) { wl_list_for_each(out, &self->outputs, link) {
self->selected_output = out; self->selected_output = out;
self->dmabuf_backend.output = out->wl_output; 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; 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) 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); // 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; self->current_fb = fb;
if (self->last_fb) { if (self->last_fb) {
uint32_t hint_x = self->screencopy_backend.damage.x; uint32_t hint_x = self->capture_backend->damage_hint.x;
uint32_t hint_y = self->screencopy_backend.damage.y; uint32_t hint_y = self->capture_backend->damage_hint.y;
uint32_t hint_width = self->screencopy_backend.damage.width; uint32_t hint_width = self->capture_backend->damage_hint.width;
uint32_t hint_height = self->screencopy_backend.damage.height; uint32_t hint_height = self->capture_backend->damage_hint.height;
nvnc_check_damage(self->current_fb, self->last_fb, hint_x, nvnc_check_damage(self->current_fb, self->last_fb, hint_x,
hint_y, hint_width, hint_height, 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); uint32_t format = fourcc_from_gl_format(self->renderer.read_format);
void* pixels = self->screencopy_backend.pixels; void* pixels = self->screencopy_backend.pixels;
uint32_t width = self->screencopy_backend.width;
uint32_t height = self->screencopy_backend.height; uint32_t width = self->capture_backend->frame_info.width;
uint32_t stride = self->screencopy_backend.stride; 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); struct nvnc_fb* fb = nvnc_fb_new(width, height, format);
void* addr = nvnc_fb_get_addr(fb); 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; struct wayvnc* self = capture->userdata;
switch (capture->status) { switch (capture->status) {
case SCREENCOPY_STATUS_CAPTURING: case CAPTURE_STOPPED:
break; break;
case SCREENCOPY_STATUS_FATAL: case CAPTURE_IN_PROGRESS:
break;
case CAPTURE_FATAL:
log_error("Fatal error while capturing. Exiting...\n"); log_error("Fatal error while capturing. Exiting...\n");
wayvnc_exit(); wayvnc_exit();
break; break;
case SCREENCOPY_STATUS_FAILED: case CAPTURE_FAILED:
if (wayvnc_start_capture(self) < 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(); wayvnc_exit();
} }
break; break;
case SCREENCOPY_STATUS_DONE: case CAPTURE_DONE:
self->n_frames++; self->n_frames++;
wayvnc_process_screen(self); wayvnc_process_screen(self);
break; break;
@ -526,6 +531,9 @@ int main(int argc, char* argv[])
if (init_nvnc(&self, "0.0.0.0", 5900) < 0) if (init_nvnc(&self, "0.0.0.0", 5900) < 0)
goto nvnc_failure; goto nvnc_failure;
screencopy_init(&self.screencopy_backend);
self.capture_backend = &self.screencopy_backend.frame_capture;
if (wayvnc_start_capture(&self) < 0) if (wayvnc_start_capture(&self) < 0)
goto capture_failure; goto capture_failure;

View File

@ -20,10 +20,20 @@
#include <stdbool.h> #include <stdbool.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <libdrm/drm_fourcc.h>
#include "shm.h" #include "shm.h"
#include "screencopy.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, static int screencopy_buffer_init(struct screencopy* self,
enum wl_shm_format format, uint32_t width, enum wl_shm_format format, uint32_t width,
uint32_t height, uint32_t stride) uint32_t height, uint32_t stride)
@ -66,8 +76,10 @@ mmap_failure:
return -1; return -1;
} }
void screencopy_stop(struct screencopy* self) static void screencopy_stop(struct frame_capture* fc)
{ {
struct screencopy* self = (void*)fc;
if (self->frame) { if (self->frame) {
zwlr_screencopy_frame_v1_destroy(self->frame); zwlr_screencopy_frame_v1_destroy(self->frame);
self->frame = NULL; self->frame = NULL;
@ -82,15 +94,16 @@ static void screencopy_buffer(void* data,
struct screencopy* self = data; struct screencopy* self = data;
if (screencopy_buffer_init(self, format, width, height, stride) < 0) { if (screencopy_buffer_init(self, format, width, height, stride) < 0) {
self->status = SCREENCOPY_STATUS_FATAL; self->frame_capture.status = CAPTURE_FATAL;
screencopy_stop(self); screencopy_stop(&self->frame_capture);
self->on_done(self); self->frame_capture.on_done(&self->frame_capture);
} }
self->format = format; self->frame_capture.frame_info.fourcc_format =
self->width = width; fourcc_from_wl_shm(format);
self->height = height; self->frame_capture.frame_info.width = width;
self->stride = stride; 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); zwlr_screencopy_frame_v1_copy_with_damage(self->frame, self->buffer);
} }
@ -115,18 +128,21 @@ static void screencopy_ready(void* data,
(void)nsec; (void)nsec;
struct screencopy* self = data; struct screencopy* self = data;
screencopy_stop(self);
self->status = SCREENCOPY_STATUS_DONE; screencopy_stop(&self->frame_capture);
self->on_done(self);
self->frame_capture.status = CAPTURE_DONE;
self->frame_capture.on_done(&self->frame_capture);
} }
static void screencopy_failed(void* data, static void screencopy_failed(void* data,
struct zwlr_screencopy_frame_v1* frame) struct zwlr_screencopy_frame_v1* frame)
{ {
struct screencopy* self = data; struct screencopy* self = data;
screencopy_stop(self);
self->status = SCREENCOPY_STATUS_FAILED; screencopy_stop(&self->frame_capture);
self->on_done(self); self->frame_capture.status = CAPTURE_FAILED;
self->frame_capture.on_done(&self->frame_capture);
} }
static void screencopy_damage(void* data, static void screencopy_damage(void* data,
@ -136,14 +152,16 @@ static void screencopy_damage(void* data,
{ {
struct screencopy* self = data; struct screencopy* self = data;
self->damage.x = x; self->frame_capture.damage_hint.x = x;
self->damage.y = y; self->frame_capture.damage_hint.y = y;
self->damage.width = width; self->frame_capture.damage_hint.width = width;
self->damage.height = height; 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 = { static const struct zwlr_screencopy_frame_v1_listener frame_listener = {
.buffer = screencopy_buffer, .buffer = screencopy_buffer,
.flags = screencopy_flags, .flags = screencopy_flags,
@ -154,14 +172,20 @@ int screencopy_start(struct screencopy* self)
self->frame = self->frame =
zwlr_screencopy_manager_v1_capture_output(self->manager, zwlr_screencopy_manager_v1_capture_output(self->manager,
self->overlay_cursor, fc->overlay_cursor,
self->output); fc->wl_output);
if (!self->frame) if (!self->frame)
return -1; return -1;
zwlr_screencopy_frame_v1_add_listener(self->frame, &frame_listener, zwlr_screencopy_frame_v1_add_listener(self->frame, &frame_listener,
self); self);
self->status = SCREENCOPY_STATUS_CAPTURING; fc->status = CAPTURE_IN_PROGRESS;
return 0; return 0;
} }
void screencopy_init(struct screencopy* self)
{
self->frame_capture.backend.start = screencopy_start;
self->frame_capture.backend.stop = screencopy_stop;
}