Skip to content

Commit 92141ee

Browse files
committed
buffer: Keep gbm device alive while buffer lives
If the buffer has a mapped bo, the gbm device must be open while the bo is mapped.
1 parent 5ae8265 commit 92141ee

File tree

2 files changed

+63
-22
lines changed

2 files changed

+63
-22
lines changed

include/buffer.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <stdint.h>
2525
#include <pixman.h>
2626
#include <sys/types.h>
27+
#include <stdatomic.h>
2728

2829
struct wl_buffer;
2930
struct gbm_bo;
@@ -44,6 +45,14 @@ enum wv_buffer_domain {
4445
WV_BUFFER_DOMAIN_CURSOR,
4546
};
4647

48+
#ifdef ENABLE_SCREENCOPY_DMABUF
49+
struct wv_gbm_device {
50+
atomic_int ref;
51+
struct gbm_device* dev;
52+
int fd;
53+
};
54+
#endif
55+
4756
struct wv_buffer {
4857
enum wv_buffer_type type;
4958
TAILQ_ENTRY(wv_buffer) link;
@@ -63,11 +72,14 @@ struct wv_buffer {
6372
struct pixman_region16 frame_damage;
6473
struct pixman_region16 buffer_damage;
6574

75+
#ifdef ENABLE_SCREENCOPY_DMABUF
6676
/* The following is only applicable to DMABUF */
6777
struct gbm_bo* bo;
6878
dev_t node;
6979
int n_modifiers;
7080
uint64_t* modifiers;
81+
struct wv_gbm_device* gbm;
82+
#endif
7183

7284
/* The following is only applicable to cursors */
7385
uint16_t cursor_width;
@@ -92,15 +104,15 @@ struct wv_buffer_config {
92104
struct wv_buffer_pool {
93105
struct wv_buffer_queue queue;
94106
struct wv_buffer_config config;
95-
96-
int gbm_fd;
97-
struct gbm_device* gbm;
107+
#ifdef ENABLE_SCREENCOPY_DMABUF
108+
struct wv_gbm_device* gbm;
109+
#endif
98110
};
99111

100112
enum wv_buffer_type wv_buffer_get_available_types(void);
101113

102114
struct wv_buffer* wv_buffer_create(const struct wv_buffer_config* config,
103-
struct gbm_device* gbm);
115+
struct wv_gbm_device* gbm);
104116
void wv_buffer_destroy(struct wv_buffer* self);
105117

106118
void wv_buffer_damage_rect(struct wv_buffer* self, int x, int y, int width,

src/buffer.c

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static int linux_cma_alloc(size_t size)
210210

211211
// Some devices (mostly ARM SBCs) need CMA for hardware encoders.
212212
static struct gbm_bo* create_cma_gbm_bo(int width, int height, uint32_t fourcc,
213-
struct gbm_device* gbm)
213+
struct wv_gbm_device* gbm)
214214
{
215215
int bpp = pixel_size_from_fourcc(fourcc);
216216
if (!bpp) {
@@ -241,7 +241,8 @@ static struct gbm_bo* create_cma_gbm_bo(int width, int height, uint32_t fourcc,
241241
.strides[0] = stride,
242242
};
243243

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

256+
#ifdef ENABLE_SCREENCOPY_DMABUF
257+
static void wv_gbm_device_ref(struct wv_gbm_device* dev)
258+
{
259+
++dev->ref;
260+
}
261+
262+
static void wv_gbm_device_unref(struct wv_gbm_device* dev)
263+
{
264+
if (!dev || --dev->ref != 0)
265+
return;
266+
267+
if (dev->dev)
268+
gbm_device_destroy(dev->dev);
269+
270+
if (dev->fd > 0)
271+
close(dev->fd);
272+
273+
free(dev);
274+
}
275+
#endif
276+
255277
static struct wv_buffer* wv_buffer_create_dmabuf(
256-
const struct wv_buffer_config* config, struct gbm_device* gbm)
278+
const struct wv_buffer_config* config,
279+
struct wv_gbm_device* gbm)
257280
{
258281
assert(zwp_linux_dmabuf);
259282

@@ -278,7 +301,7 @@ static struct wv_buffer* wv_buffer_create_dmabuf(
278301
self->bo = have_linux_cma() ?
279302
create_cma_gbm_bo(config->width, config->height,
280303
config->format, gbm) :
281-
gbm_bo_create_with_modifiers2(gbm, config->width,
304+
gbm_bo_create_with_modifiers2(gbm->dev, config->width,
282305
config->height, config->format,
283306
config->modifiers, config->n_modifiers,
284307
GBM_BO_USE_RENDERING);
@@ -325,6 +348,9 @@ static struct wv_buffer* wv_buffer_create_dmabuf(
325348
pixman_region_init_rect(&self->buffer_damage, 0, 0, config->width,
326349
config->height);
327350

351+
self->gbm = gbm;
352+
wv_gbm_device_ref(gbm);
353+
328354
LIST_INSERT_HEAD(&buffer_registry, self, registry_link);
329355

330356
return self;
@@ -343,7 +369,7 @@ static struct wv_buffer* wv_buffer_create_dmabuf(
343369
#endif
344370

345371
struct wv_buffer* wv_buffer_create(const struct wv_buffer_config* config,
346-
struct gbm_device* gbm)
372+
struct wv_gbm_device* gbm)
347373
{
348374
nvnc_trace("wv_buffer_create: %dx%d, stride: %d, format: %"PRIu32" gbm: %p",
349375
config->width, config->height, config->stride,
@@ -378,6 +404,7 @@ static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
378404
wl_buffer_destroy(self->wl_buffer);
379405
free(self->modifiers);
380406
gbm_bo_destroy(self->bo);
407+
wv_gbm_device_unref(self->gbm);
381408
free(self);
382409
}
383410
#endif
@@ -428,7 +455,6 @@ struct wv_buffer_pool* wv_buffer_pool_create(
428455
return NULL;
429456

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

433459
if (config)
434460
wv_buffer_pool_reconfig(self, config);
@@ -450,10 +476,7 @@ void wv_buffer_pool_destroy(struct wv_buffer_pool* pool)
450476
wv_buffer_pool_clear(pool);
451477
free(pool->config.modifiers);
452478
#ifdef ENABLE_SCREENCOPY_DMABUF
453-
if (pool->gbm)
454-
gbm_device_destroy(pool->gbm);
455-
if (pool->gbm_fd > 0)
456-
close(pool->gbm_fd);
479+
wv_gbm_device_unref(pool->gbm);
457480
#endif
458481
free(pool);
459482
}
@@ -509,16 +532,26 @@ static void open_render_node(struct wv_buffer_pool* pool)
509532

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

512-
pool->gbm_fd = open(path, O_RDWR);
513-
if (pool->gbm_fd < 0) {
535+
pool->gbm = calloc(1, sizeof(*pool->gbm));
536+
assert(pool->gbm);
537+
538+
pool->gbm->ref = 1;
539+
540+
pool->gbm->fd = open(path, O_RDWR);
541+
if (pool->gbm->fd < 0) {
514542
nvnc_log(NVNC_LOG_ERROR, "Failed to open render node %s: %m",
515543
path);
544+
free(pool->gbm);
545+
pool->gbm = NULL;
516546
return;
517547
}
518548

519-
pool->gbm = gbm_create_device(pool->gbm_fd);
549+
pool->gbm->dev = gbm_create_device(pool->gbm->fd);
520550
if (!pool->gbm) {
521551
nvnc_log(NVNC_LOG_ERROR, "Failed to create a GBM device");
552+
close(pool->gbm->fd);
553+
free(pool->gbm);
554+
pool->gbm = NULL;
522555
}
523556
}
524557
#endif // ENABLE_SCREENCOPY_DMABUF
@@ -535,12 +568,8 @@ void wv_buffer_pool_reconfig(struct wv_buffer_pool* pool,
535568

536569
#ifdef ENABLE_SCREENCOPY_DMABUF
537570
if (old_node != config->node) {
538-
if (pool->gbm)
539-
gbm_device_destroy(pool->gbm);
571+
wv_gbm_device_unref(pool->gbm);
540572
pool->gbm = NULL;
541-
if (pool->gbm_fd > 0)
542-
close(pool->gbm_fd);
543-
pool->gbm_fd = -1;
544573

545574
open_render_node(pool);
546575
}

0 commit comments

Comments
 (0)