Add build option for enabling screencopy-dmabuf

pull/58/head
Andri Yngvason 2020-07-26 14:52:00 +00:00
parent ca069ea738
commit 3742dc7144
6 changed files with 81 additions and 19 deletions

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#include "sys/queue.h" #include "sys/queue.h"
#include "config.h"
#include <unistd.h> #include <unistd.h>
#include <stdbool.h> #include <stdbool.h>
@ -29,7 +30,9 @@ struct gbm_bo;
enum wv_buffer_type { enum wv_buffer_type {
WV_BUFFER_UNSPEC = 0, WV_BUFFER_UNSPEC = 0,
WV_BUFFER_SHM, WV_BUFFER_SHM,
#ifdef ENABLE_SCREENCOPY_DMABUF
WV_BUFFER_DMABUF, WV_BUFFER_DMABUF,
#endif
}; };
struct wv_buffer { struct wv_buffer {

View File

@ -41,7 +41,7 @@ libm = cc.find_library('m', required: false)
librt = cc.find_library('rt', required: false) librt = cc.find_library('rt', required: false)
pixman = dependency('pixman-1') pixman = dependency('pixman-1')
gbm = dependency('gbm') gbm = dependency('gbm', required: get_option('screencopy-dmabuf'))
drm = dependency('libdrm') drm = dependency('libdrm')
xkbcommon = dependency('xkbcommon') xkbcommon = dependency('xkbcommon')
wayland_client = dependency('wayland-client') wayland_client = dependency('wayland-client')
@ -116,6 +116,10 @@ elif cc.has_function('SYS_memfd_create', prefix : '#include <sys/syscall.h>')
config.set('HAVE_MEMFD', true) config.set('HAVE_MEMFD', true)
endif endif
if gbm.found() and not get_option('screencopy-dmabuf').disabled()
config.set('ENABLE_SCREENCOPY_DMABUF', true)
endif
configure_file( configure_file(
output: 'config.h', output: 'config.h',
configuration: config, configuration: config,

View File

@ -0,0 +1,2 @@
option('screencopy-dmabuf', type: 'feature', value: 'disabled',
description: 'Enable GPU-side screencopy (experimental)')

View File

@ -30,6 +30,7 @@
#include "sys/queue.h" #include "sys/queue.h"
#include "buffer.h" #include "buffer.h"
#include "pixels.h" #include "pixels.h"
#include "config.h"
extern struct wl_shm* wl_shm; extern struct wl_shm* wl_shm;
extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf; extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf;
@ -42,8 +43,10 @@ enum wv_buffer_type wv_buffer_get_available_types(void)
if (wl_shm) if (wl_shm)
type |= WV_BUFFER_SHM; type |= WV_BUFFER_SHM;
#ifdef ENABLE_SCREENCOPY_DMABUF
if (zwp_linux_dmabuf && gbm_device) if (zwp_linux_dmabuf && gbm_device)
type |= WV_BUFFER_DMABUF; type |= WV_BUFFER_DMABUF;
#endif
return type; return type;
} }
@ -99,6 +102,7 @@ failure:
return NULL; return NULL;
} }
#ifdef ENABLE_SCREENCOPY_DMABUF
static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height, static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
uint32_t fourcc) uint32_t fourcc)
{ {
@ -152,6 +156,7 @@ bo_failure:
free(self); free(self);
return NULL; return NULL;
} }
#endif
struct wv_buffer* wv_buffer_create(enum wv_buffer_type type, int width, struct wv_buffer* wv_buffer_create(enum wv_buffer_type type, int width,
int height, int stride, uint32_t fourcc) int height, int stride, uint32_t fourcc)
@ -159,8 +164,10 @@ struct wv_buffer* wv_buffer_create(enum wv_buffer_type type, int width,
switch (type) { switch (type) {
case WV_BUFFER_SHM: case WV_BUFFER_SHM:
return wv_buffer_create_shm(width, height, stride, fourcc); return wv_buffer_create_shm(width, height, stride, fourcc);
#ifdef ENABLE_SCREENCOPY_DMABUF
case WV_BUFFER_DMABUF: case WV_BUFFER_DMABUF:
return wv_buffer_create_dmabuf(width, height, fourcc); return wv_buffer_create_dmabuf(width, height, fourcc);
#endif
case WV_BUFFER_UNSPEC:; case WV_BUFFER_UNSPEC:;
} }
@ -175,12 +182,14 @@ static void wv_buffer_destroy_shm(struct wv_buffer* self)
free(self); free(self);
} }
#ifdef ENABLE_SCREENCOPY_DMABUF
static void wv_buffer_destroy_dmabuf(struct wv_buffer* self) static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
{ {
wl_buffer_destroy(self->wl_buffer); wl_buffer_destroy(self->wl_buffer);
gbm_bo_destroy(self->bo); gbm_bo_destroy(self->bo);
free(self); free(self);
} }
#endif
void wv_buffer_destroy(struct wv_buffer* self) void wv_buffer_destroy(struct wv_buffer* self)
{ {
@ -191,15 +200,18 @@ void wv_buffer_destroy(struct wv_buffer* self)
case WV_BUFFER_SHM: case WV_BUFFER_SHM:
wv_buffer_destroy_shm(self); wv_buffer_destroy_shm(self);
return; return;
#ifdef ENABLE_SCREENCOPY_DMABUF
case WV_BUFFER_DMABUF: case WV_BUFFER_DMABUF:
wv_buffer_destroy_dmabuf(self); wv_buffer_destroy_dmabuf(self);
return; return;
#endif
case WV_BUFFER_UNSPEC:; case WV_BUFFER_UNSPEC:;
} }
abort(); abort();
} }
#ifdef ENABLE_SCREENCOPY_DMABUF
static int wv_buffer_map_dmabuf(struct wv_buffer* self) static int wv_buffer_map_dmabuf(struct wv_buffer* self)
{ {
if (self->bo_map_handle) if (self->bo_map_handle)
@ -215,34 +227,41 @@ static int wv_buffer_map_dmabuf(struct wv_buffer* self)
self->bo_map_handle = NULL; self->bo_map_handle = NULL;
return -1; return -1;
} }
#endif
int wv_buffer_map(struct wv_buffer* self) int wv_buffer_map(struct wv_buffer* self)
{ {
switch (self->type) { switch (self->type) {
case WV_BUFFER_SHM: case WV_BUFFER_SHM:
return 0; return 0;
#ifdef ENABLE_SCREENCOPY_DMABUF
case WV_BUFFER_DMABUF: case WV_BUFFER_DMABUF:
return wv_buffer_map_dmabuf(self); return wv_buffer_map_dmabuf(self);
#endif
case WV_BUFFER_UNSPEC:; case WV_BUFFER_UNSPEC:;
} }
abort(); abort();
} }
#ifdef ENABLE_SCREENCOPY_DMABUF
static void wv_buffer_unmap_dmabuf(struct wv_buffer* self) static void wv_buffer_unmap_dmabuf(struct wv_buffer* self)
{ {
if (self->bo_map_handle) if (self->bo_map_handle)
gbm_bo_unmap(self->bo, self->bo_map_handle); gbm_bo_unmap(self->bo, self->bo_map_handle);
self->bo_map_handle = NULL; self->bo_map_handle = NULL;
} }
#endif
void wv_buffer_unmap(struct wv_buffer* self) void wv_buffer_unmap(struct wv_buffer* self)
{ {
switch (self->type) { switch (self->type) {
case WV_BUFFER_SHM: case WV_BUFFER_SHM:
return; return;
#ifdef ENABLE_SCREENCOPY_DMABUF
case WV_BUFFER_DMABUF: case WV_BUFFER_DMABUF:
return wv_buffer_unmap_dmabuf(self); return wv_buffer_unmap_dmabuf(self);
#endif
case WV_BUFFER_UNSPEC:; case WV_BUFFER_UNSPEC:;
} }
@ -327,12 +346,13 @@ static bool wv_buffer_pool_match_buffer(struct wv_buffer_pool* pool,
return false; return false;
/* fall-through */ /* fall-through */
#ifdef ENABLE_SCREENCOPY_DMABUF
case WV_BUFFER_DMABUF: case WV_BUFFER_DMABUF:
if (pool->width != buffer->width if (pool->width != buffer->width
|| pool->height != buffer->height || pool->height != buffer->height
|| pool->format != buffer->format) || pool->format != buffer->format)
return false; return false;
#endif
return true; return true;
case WV_BUFFER_UNSPEC: case WV_BUFFER_UNSPEC:
abort(); abort();

View File

@ -34,8 +34,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <gbm.h>
#include <xf86drm.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"
@ -55,6 +53,11 @@
#include "damage-refinery.h" #include "damage-refinery.h"
#include "usdt.h" #include "usdt.h"
#ifdef ENABLE_SCREENCOPY_DMABUF
#include <gbm.h>
#include <xf86drm.h>
#endif
#define DEFAULT_ADDRESS "127.0.0.1" #define DEFAULT_ADDRESS "127.0.0.1"
#define DEFAULT_PORT 5900 #define DEFAULT_PORT 5900
@ -229,6 +232,7 @@ static void registry_remove(void* data, struct wl_registry* registry,
} }
} }
#ifdef ENABLE_SCREENCOPY_DMABUF
static int find_render_node(char *node, size_t maxlen) { static int find_render_node(char *node, size_t maxlen) {
bool r = -1; bool r = -1;
drmDevice *devices[64]; drmDevice *devices[64];
@ -248,6 +252,26 @@ static int find_render_node(char *node, size_t maxlen) {
return r; return r;
} }
static int init_render_node(int* fd)
{
char render_node[256];
if (find_render_node(render_node, sizeof(render_node)) < 0)
return -1;
*fd = open(render_node, O_RDWR);
if (*fd < 0)
return -1;
gbm_device = gbm_create_device(*fd);
if (!gbm_device) {
close(*fd);
return -1;
}
return 0;
}
#endif
void wayvnc_destroy(struct wayvnc* self) void wayvnc_destroy(struct wayvnc* self)
{ {
output_list_destroy(&self->outputs); output_list_destroy(&self->outputs);
@ -739,7 +763,7 @@ int main(int argc, char* argv[])
int max_rate = 30; int max_rate = 30;
static const char* shortopts = "C:o:k:s:rf:hpV"; static const char* shortopts = "C:o:k:s:rf:hpV";
int drm_fd = -1; int drm_fd MAYBE_UNUSED = -1;
static const struct option longopts[] = { static const struct option longopts[] = {
{ "config", required_argument, NULL, 'C' }, { "config", required_argument, NULL, 'C' },
@ -883,17 +907,11 @@ int main(int argc, char* argv[])
out->on_dimension_change = on_output_dimension_change; out->on_dimension_change = on_output_dimension_change;
out->userdata = &self; out->userdata = &self;
char render_node[256]; #ifdef ENABLE_SCREENCOPY_DMABUF
if (find_render_node(render_node, sizeof(render_node)) < 0) if (init_render_node(&drm_fd) < 0) {
goto failure; log_error("Failed to initialise DRM render node. No GPU acceleration will be available.\n");
}
drm_fd = open(render_node, O_RDWR); #endif
if (drm_fd < 0)
goto failure;
gbm_device = gbm_create_device(drm_fd);
if (!gbm_device)
goto failure;
struct aml* aml = aml_new(); struct aml* aml = aml_new();
if (!aml) if (!aml)
@ -948,7 +966,12 @@ int main(int argc, char* argv[])
zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf); zwp_linux_dmabuf_v1_destroy(zwp_linux_dmabuf);
if (self.screencopy.manager) if (self.screencopy.manager)
screencopy_destroy(&self.screencopy); screencopy_destroy(&self.screencopy);
#ifdef ENABLE_SCREENCOPY_DMABUF
if (gbm_device) {
gbm_device_destroy(gbm_device); gbm_device_destroy(gbm_device);
close(drm_fd);
}
#endif
wayvnc_destroy(&self); wayvnc_destroy(&self);
aml_unref(aml); aml_unref(aml);
@ -960,9 +983,12 @@ capture_failure:
nvnc_failure: nvnc_failure:
main_loop_failure: main_loop_failure:
failure: failure:
#ifdef ENABLE_SCREENCOPY_DMABUF
if (gbm_device)
gbm_device_destroy(gbm_device); gbm_device_destroy(gbm_device);
if (drm_fd >= 0) if (drm_fd >= 0)
close(drm_fd); close(drm_fd);
#endif
wayvnc_destroy(&self); wayvnc_destroy(&self);
return 1; return 1;
} }

View File

@ -32,6 +32,7 @@
#include "time-util.h" #include "time-util.h"
#include "usdt.h" #include "usdt.h"
#include "pixels.h" #include "pixels.h"
#include "config.h"
#define DELAY_SMOOTHER_TIME_CONSTANT 0.5 // s #define DELAY_SMOOTHER_TIME_CONSTANT 0.5 // s
@ -63,6 +64,9 @@ static void screencopy_linux_dmabuf(void* data,
#ifdef ENABLE_SCREENCOPY_DMABUF #ifdef ENABLE_SCREENCOPY_DMABUF
struct screencopy* self = data; struct screencopy* self = data;
if (!(wv_buffer_get_available_types() & WV_BUFFER_DMABUF))
return;
self->have_linux_dmabuf = true; self->have_linux_dmabuf = true;
self->dmabuf_width = width; self->dmabuf_width = width;
self->dmabuf_height = height; self->dmabuf_height = height;
@ -77,13 +81,16 @@ static void screencopy_buffer_done(void* data,
uint32_t width, height, stride, fourcc; uint32_t width, height, stride, fourcc;
enum wv_buffer_type type = WV_BUFFER_UNSPEC; enum wv_buffer_type type = WV_BUFFER_UNSPEC;
#ifdef ENABLE_SCREENCOPY_DMABUF
if (self->have_linux_dmabuf) { if (self->have_linux_dmabuf) {
width = self->dmabuf_width; width = self->dmabuf_width;
height = self->dmabuf_height; height = self->dmabuf_height;
stride = 0; stride = 0;
fourcc = self->fourcc; fourcc = self->fourcc;
type = WV_BUFFER_DMABUF; type = WV_BUFFER_DMABUF;
} else { } else
#endif
{
width = self->wl_shm_width; width = self->wl_shm_width;
height = self->wl_shm_height; height = self->wl_shm_height;
stride = self->wl_shm_stride; stride = self->wl_shm_stride;