Integrate dmabuf capturing into frame-capture

shader-damage
Andri Yngvason 2019-10-10 22:51:44 +00:00
parent ffda3c164c
commit cc1f470c6e
3 changed files with 49 additions and 66 deletions

View File

@ -18,19 +18,12 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "frame-capture.h"
struct zwlr_export_dmabuf_manager_v1; struct zwlr_export_dmabuf_manager_v1;
struct zwlr_export_dmabuf_frame_v1; struct zwlr_export_dmabuf_frame_v1;
struct wl_output; struct wl_output;
enum dmabuf_capture_status {
DMABUF_CAPTURE_UNSPEC = 0,
DMABUF_CAPTURE_IN_PROGRESS,
DMABUF_CAPTURE_CANCELLED,
DMABUF_CAPTURE_FATAL,
DMABUF_CAPTURE_DONE
};
struct dmabuf_plane { struct dmabuf_plane {
int fd; int fd;
uint32_t offset; uint32_t offset;
@ -49,17 +42,11 @@ struct dmabuf_frame {
}; };
struct dmabuf_capture { struct dmabuf_capture {
struct frame_capture fc;
struct zwlr_export_dmabuf_manager_v1* manager; struct zwlr_export_dmabuf_manager_v1* manager;
struct zwlr_export_dmabuf_frame_v1* zwlr_frame; struct zwlr_export_dmabuf_frame_v1* zwlr_frame;
struct dmabuf_frame frame; struct dmabuf_frame frame;
bool overlay_cursor;
struct wl_output* output;
enum dmabuf_capture_status status;
void (*on_done)(struct dmabuf_capture*);
void* userdata;
}; };
int dmabuf_capture_start(struct dmabuf_capture* self); void dmabuf_capture_init(struct dmabuf_capture* self);
void dmabuf_capture_stop(struct dmabuf_capture* self);

View File

@ -23,8 +23,10 @@
#include "dmabuf.h" #include "dmabuf.h"
#include "wlr-export-dmabuf-unstable-v1.h" #include "wlr-export-dmabuf-unstable-v1.h"
void dmabuf_capture_stop(struct dmabuf_capture* self) static void dmabuf_capture_stop(struct frame_capture* fc)
{ {
struct dmabuf_capture* self = (void*)fc;
if (self->zwlr_frame) { if (self->zwlr_frame) {
zwlr_export_dmabuf_frame_v1_destroy(self->zwlr_frame); zwlr_export_dmabuf_frame_v1_destroy(self->zwlr_frame);
self->zwlr_frame = NULL; self->zwlr_frame = NULL;
@ -41,6 +43,7 @@ static void dmabuf_frame_start(void* data,
uint32_t num_objects) uint32_t num_objects)
{ {
struct dmabuf_capture* self = data; struct dmabuf_capture* self = data;
struct frame_capture* fc = data;
uint64_t mod = ((uint64_t)mod_high << 32) | (uint64_t)mod_low; uint64_t mod = ((uint64_t)mod_high << 32) | (uint64_t)mod_low;
@ -53,6 +56,11 @@ static void dmabuf_frame_start(void* data,
self->frame.plane[1].modifier = mod; self->frame.plane[1].modifier = mod;
self->frame.plane[2].modifier = mod; self->frame.plane[2].modifier = mod;
self->frame.plane[3].modifier = mod; self->frame.plane[3].modifier = mod;
fc->damage_hint.x = 0;
fc->damage_hint.y = 0;
fc->damage_hint.width = width;
fc->damage_hint.height = height;
} }
static void dmabuf_frame_object(void* data, static void dmabuf_frame_object(void* data,
@ -62,6 +70,7 @@ static void dmabuf_frame_object(void* data,
uint32_t plane_index) uint32_t plane_index)
{ {
struct dmabuf_capture* self = data; struct dmabuf_capture* self = data;
struct frame_capture* fc = data;
self->frame.plane[plane_index].fd = fd; self->frame.plane[plane_index].fd = fd;
self->frame.plane[plane_index].size = size; self->frame.plane[plane_index].size = size;
@ -75,28 +84,31 @@ static void dmabuf_frame_ready(void* data,
uint32_t tv_nsec) uint32_t tv_nsec)
{ {
struct dmabuf_capture* self = data; struct dmabuf_capture* self = data;
struct frame_capture* fc = data;
dmabuf_capture_stop(self); dmabuf_capture_stop(fc);
self->status = DMABUF_CAPTURE_DONE; fc->status = CAPTURE_DONE;
self->on_done(self); fc->on_done(fc);
} }
static void dmabuf_frame_cancel(void* data, static void dmabuf_frame_cancel(void* data,
struct zwlr_export_dmabuf_frame_v1* frame, struct zwlr_export_dmabuf_frame_v1* frame,
uint32_t reason) uint32_t reason)
{ {
struct dmabuf_capture* self = data; struct frame_capture* fc = data;
self->status = reason == ZWLR_EXPORT_DMABUF_FRAME_V1_CANCEL_REASON_PERMANENT fc->status = reason == ZWLR_EXPORT_DMABUF_FRAME_V1_CANCEL_REASON_PERMANENT
? DMABUF_CAPTURE_FATAL : DMABUF_CAPTURE_DONE; ? CAPTURE_FATAL : CAPTURE_FAILED;
dmabuf_capture_stop(self); dmabuf_capture_stop(fc);
self->on_done(self); fc->on_done(fc);
} }
int dmabuf_capture_start(struct dmabuf_capture* self) static int dmabuf_capture_start(struct frame_capture* fc)
{ {
struct dmabuf_capture* self = (void*)fc;
static const struct zwlr_export_dmabuf_frame_v1_listener static const struct zwlr_export_dmabuf_frame_v1_listener
dmabuf_frame_listener = { dmabuf_frame_listener = {
.frame = dmabuf_frame_start, .frame = dmabuf_frame_start,
@ -107,15 +119,21 @@ int dmabuf_capture_start(struct dmabuf_capture* self)
self->zwlr_frame = self->zwlr_frame =
zwlr_export_dmabuf_manager_v1_capture_output(self->manager, zwlr_export_dmabuf_manager_v1_capture_output(self->manager,
self->overlay_cursor, fc->overlay_cursor,
self->output); fc->wl_output);
if (!self->zwlr_frame) if (!self->zwlr_frame)
return -1; return -1;
self->status = DMABUF_CAPTURE_IN_PROGRESS; fc->status = CAPTURE_IN_PROGRESS;
zwlr_export_dmabuf_frame_v1_add_listener(self->zwlr_frame, zwlr_export_dmabuf_frame_v1_add_listener(self->zwlr_frame,
&dmabuf_frame_listener, self); &dmabuf_frame_listener, self);
return 0; return 0;
} }
void dmabuf_capture_init(struct dmabuf_capture* self)
{
self->fc.backend.start = dmabuf_capture_start;
self->fc.backend.stop = dmabuf_capture_stop;
}

View File

@ -73,8 +73,7 @@ struct wayvnc {
uint32_t n_frames; uint32_t n_frames;
}; };
void on_capture_done(struct dmabuf_capture* capture); void on_capture_done(struct frame_capture* 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,
@ -241,10 +240,10 @@ static int init_wayland(struct wayvnc* self)
goto export_manager_failure; goto export_manager_failure;
} }
self->dmabuf_backend.on_done = on_capture_done; self->dmabuf_backend.fc.on_done = on_capture_done;
self->dmabuf_backend.userdata = self; self->dmabuf_backend.fc.userdata = self;
self->screencopy_backend.frame_capture.on_done = on_screencopy_done; self->screencopy_backend.frame_capture.on_done = on_capture_done;
self->screencopy_backend.frame_capture.userdata = self; self->screencopy_backend.frame_capture.userdata = self;
return 0; return 0;
@ -262,7 +261,7 @@ 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.fc.wl_output = out->wl_output;
self->screencopy_backend.frame_capture.wl_output self->screencopy_backend.frame_capture.wl_output
= out->wl_output; = out->wl_output;
return 0; return 0;
@ -412,9 +411,10 @@ void wayvnc_update_vnc(struct wayvnc* self, struct nvnc_fb* fb)
} }
} }
void wayvnc_process_frame(struct wayvnc* self, struct dmabuf_frame* frame) void wayvnc_process_frame(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);
struct dmabuf_frame* frame = &self->dmabuf_backend.frame;
struct nvnc_fb* fb = nvnc_fb_new(frame->width, frame->height, format); struct nvnc_fb* fb = nvnc_fb_new(frame->width, frame->height, format);
void* addr = nvnc_fb_get_addr(fb); void* addr = nvnc_fb_get_addr(fb);
@ -445,33 +445,7 @@ void wayvnc_process_screen(struct wayvnc* self)
wayvnc_update_vnc(self, fb); wayvnc_update_vnc(self, fb);
} }
void on_capture_done(struct dmabuf_capture* capture) void on_capture_done(struct frame_capture* capture)
{
struct wayvnc* self = capture->userdata;
switch (capture->status) {
case DMABUF_CAPTURE_IN_PROGRESS:
break;
case DMABUF_CAPTURE_FATAL:
log_error("Fatal error while capturing. Exiting...\n");
wayvnc_exit();
break;
case DMABUF_CAPTURE_CANCELLED:
if (wayvnc_start_capture(self) < 0) {
log_error("Failed to start capture. Exiting...\n");
wayvnc_exit();
}
break;
case DMABUF_CAPTURE_DONE:
self->n_frames++;
wayvnc_process_frame(self, &capture->frame);
break;
case DMABUF_CAPTURE_UNSPEC:
abort();
}
}
void on_screencopy_done(struct frame_capture* capture)
{ {
struct wayvnc* self = capture->userdata; struct wayvnc* self = capture->userdata;
@ -492,7 +466,10 @@ void on_screencopy_done(struct frame_capture* capture)
break; break;
case CAPTURE_DONE: case CAPTURE_DONE:
self->n_frames++; self->n_frames++;
if (self->capture_backend == (struct frame_capture*)&self->screencopy_backend)
wayvnc_process_screen(self); wayvnc_process_screen(self);
else
wayvnc_process_frame(self);
break; break;
} }
} }
@ -532,7 +509,8 @@ int main(int argc, char* argv[])
goto nvnc_failure; goto nvnc_failure;
screencopy_init(&self.screencopy_backend); screencopy_init(&self.screencopy_backend);
self.capture_backend = &self.screencopy_backend.frame_capture; dmabuf_capture_init(&self.dmabuf_backend);
self.capture_backend = &self.dmabuf_backend.fc;
if (wayvnc_start_capture(&self) < 0) if (wayvnc_start_capture(&self) < 0)
goto capture_failure; goto capture_failure;