Skip to content

Commit

Permalink
buffer: Keep gbm device alive while buffer lives
Browse files Browse the repository at this point in the history
If the buffer has a mapped bo, the gbm device must be open while the bo
is mapped.
  • Loading branch information
any1 committed Sep 24, 2024
1 parent 5ae8265 commit 92141ee
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 22 deletions.
20 changes: 16 additions & 4 deletions include/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <stdint.h>
#include <pixman.h>
#include <sys/types.h>
#include <stdatomic.h>

struct wl_buffer;
struct gbm_bo;
Expand All @@ -44,6 +45,14 @@ enum wv_buffer_domain {
WV_BUFFER_DOMAIN_CURSOR,
};

#ifdef ENABLE_SCREENCOPY_DMABUF
struct wv_gbm_device {
atomic_int ref;
struct gbm_device* dev;
int fd;
};
#endif

struct wv_buffer {
enum wv_buffer_type type;
TAILQ_ENTRY(wv_buffer) link;
Expand All @@ -63,11 +72,14 @@ struct wv_buffer {
struct pixman_region16 frame_damage;
struct pixman_region16 buffer_damage;

#ifdef ENABLE_SCREENCOPY_DMABUF
/* The following is only applicable to DMABUF */
struct gbm_bo* bo;
dev_t node;
int n_modifiers;
uint64_t* modifiers;
struct wv_gbm_device* gbm;
#endif

/* The following is only applicable to cursors */
uint16_t cursor_width;
Expand All @@ -92,15 +104,15 @@ struct wv_buffer_config {
struct wv_buffer_pool {
struct wv_buffer_queue queue;
struct wv_buffer_config config;

int gbm_fd;
struct gbm_device* gbm;
#ifdef ENABLE_SCREENCOPY_DMABUF
struct wv_gbm_device* gbm;
#endif
};

enum wv_buffer_type wv_buffer_get_available_types(void);

struct wv_buffer* wv_buffer_create(const struct wv_buffer_config* config,
struct gbm_device* gbm);
struct wv_gbm_device* gbm);
void wv_buffer_destroy(struct wv_buffer* self);

void wv_buffer_damage_rect(struct wv_buffer* self, int x, int y, int width,
Expand Down
65 changes: 47 additions & 18 deletions src/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ static int linux_cma_alloc(size_t size)

// Some devices (mostly ARM SBCs) need CMA for hardware encoders.
static struct gbm_bo* create_cma_gbm_bo(int width, int height, uint32_t fourcc,
struct gbm_device* gbm)
struct wv_gbm_device* gbm)
{
int bpp = pixel_size_from_fourcc(fourcc);
if (!bpp) {
Expand Down Expand Up @@ -241,7 +241,8 @@ static struct gbm_bo* create_cma_gbm_bo(int width, int height, uint32_t fourcc,
.strides[0] = stride,
};

struct gbm_bo* bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &d, 0);
struct gbm_bo* bo = gbm_bo_import(gbm->dev, GBM_BO_IMPORT_FD_MODIFIER,
&d, 0);
if (!bo) {
nvnc_log(NVNC_LOG_DEBUG, "Failed to import dmabuf: %m");
close(fd);
Expand All @@ -252,8 +253,30 @@ static struct gbm_bo* create_cma_gbm_bo(int width, int height, uint32_t fourcc,
}
#endif // HAVE_LINUX_DMA_HEAP

#ifdef ENABLE_SCREENCOPY_DMABUF
static void wv_gbm_device_ref(struct wv_gbm_device* dev)
{
++dev->ref;
}

static void wv_gbm_device_unref(struct wv_gbm_device* dev)
{
if (!dev || --dev->ref != 0)
return;

if (dev->dev)
gbm_device_destroy(dev->dev);

if (dev->fd > 0)
close(dev->fd);

free(dev);
}
#endif

static struct wv_buffer* wv_buffer_create_dmabuf(
const struct wv_buffer_config* config, struct gbm_device* gbm)
const struct wv_buffer_config* config,
struct wv_gbm_device* gbm)
{
assert(zwp_linux_dmabuf);

Expand All @@ -278,7 +301,7 @@ static struct wv_buffer* wv_buffer_create_dmabuf(
self->bo = have_linux_cma() ?
create_cma_gbm_bo(config->width, config->height,
config->format, gbm) :
gbm_bo_create_with_modifiers2(gbm, config->width,
gbm_bo_create_with_modifiers2(gbm->dev, config->width,
config->height, config->format,
config->modifiers, config->n_modifiers,
GBM_BO_USE_RENDERING);
Expand Down Expand Up @@ -325,6 +348,9 @@ static struct wv_buffer* wv_buffer_create_dmabuf(
pixman_region_init_rect(&self->buffer_damage, 0, 0, config->width,
config->height);

self->gbm = gbm;
wv_gbm_device_ref(gbm);

LIST_INSERT_HEAD(&buffer_registry, self, registry_link);

return self;
Expand All @@ -343,7 +369,7 @@ static struct wv_buffer* wv_buffer_create_dmabuf(
#endif

struct wv_buffer* wv_buffer_create(const struct wv_buffer_config* config,
struct gbm_device* gbm)
struct wv_gbm_device* gbm)
{
nvnc_trace("wv_buffer_create: %dx%d, stride: %d, format: %"PRIu32" gbm: %p",
config->width, config->height, config->stride,
Expand Down Expand Up @@ -378,6 +404,7 @@ static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
wl_buffer_destroy(self->wl_buffer);
free(self->modifiers);
gbm_bo_destroy(self->bo);
wv_gbm_device_unref(self->gbm);
free(self);
}
#endif
Expand Down Expand Up @@ -428,7 +455,6 @@ struct wv_buffer_pool* wv_buffer_pool_create(
return NULL;

TAILQ_INIT(&self->queue);
self->gbm_fd = -1;

if (config)
wv_buffer_pool_reconfig(self, config);
Expand All @@ -450,10 +476,7 @@ void wv_buffer_pool_destroy(struct wv_buffer_pool* pool)
wv_buffer_pool_clear(pool);
free(pool->config.modifiers);
#ifdef ENABLE_SCREENCOPY_DMABUF
if (pool->gbm)
gbm_device_destroy(pool->gbm);
if (pool->gbm_fd > 0)
close(pool->gbm_fd);
wv_gbm_device_unref(pool->gbm);
#endif
free(pool);
}
Expand Down Expand Up @@ -509,16 +532,26 @@ static void open_render_node(struct wv_buffer_pool* pool)

nvnc_log(NVNC_LOG_DEBUG, "Using render node: %s", path);

pool->gbm_fd = open(path, O_RDWR);
if (pool->gbm_fd < 0) {
pool->gbm = calloc(1, sizeof(*pool->gbm));
assert(pool->gbm);

pool->gbm->ref = 1;

pool->gbm->fd = open(path, O_RDWR);
if (pool->gbm->fd < 0) {
nvnc_log(NVNC_LOG_ERROR, "Failed to open render node %s: %m",
path);
free(pool->gbm);
pool->gbm = NULL;
return;
}

pool->gbm = gbm_create_device(pool->gbm_fd);
pool->gbm->dev = gbm_create_device(pool->gbm->fd);
if (!pool->gbm) {
nvnc_log(NVNC_LOG_ERROR, "Failed to create a GBM device");
close(pool->gbm->fd);
free(pool->gbm);
pool->gbm = NULL;
}
}
#endif // ENABLE_SCREENCOPY_DMABUF
Expand All @@ -535,12 +568,8 @@ void wv_buffer_pool_reconfig(struct wv_buffer_pool* pool,

#ifdef ENABLE_SCREENCOPY_DMABUF
if (old_node != config->node) {
if (pool->gbm)
gbm_device_destroy(pool->gbm);
wv_gbm_device_unref(pool->gbm);
pool->gbm = NULL;
if (pool->gbm_fd > 0)
close(pool->gbm_fd);
pool->gbm_fd = -1;

open_render_node(pool);
}
Expand Down

0 comments on commit 92141ee

Please sign in to comment.