Integrate dmabuf capturing into frame-capture
parent
ffda3c164c
commit
cc1f470c6e
|
@ -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);
|
|
||||||
|
|
44
src/dmabuf.c
44
src/dmabuf.c
|
@ -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;
|
||||||
|
}
|
||||||
|
|
50
src/main.c
50
src/main.c
|
@ -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++;
|
||||||
wayvnc_process_screen(self);
|
if (self->capture_backend == (struct frame_capture*)&self->screencopy_backend)
|
||||||
|
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;
|
||||||
|
|
Loading…
Reference in New Issue