buffer: Add DMA-BUFs
parent
492b1ce8d8
commit
4fa019d31f
|
@ -7,21 +7,33 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct wl_buffer;
|
struct wl_buffer;
|
||||||
|
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,
|
||||||
|
WV_BUFFER_DMABUF,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wv_buffer {
|
struct wv_buffer {
|
||||||
enum wv_buffer_type type;
|
enum wv_buffer_type type;
|
||||||
TAILQ_ENTRY(wv_buffer) link;
|
TAILQ_ENTRY(wv_buffer) link;
|
||||||
|
|
||||||
struct wl_buffer* wl_buffer;
|
struct wl_buffer* wl_buffer;
|
||||||
|
|
||||||
void* pixels;
|
void* pixels;
|
||||||
size_t size;
|
size_t size;
|
||||||
int width, height, stride;
|
int width, height, stride;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
bool y_inverted;
|
bool y_inverted;
|
||||||
|
|
||||||
|
/* The following is only applicable to DMABUF */
|
||||||
|
struct gbm_bo* bo;
|
||||||
|
void* bo_map_handle;
|
||||||
|
|
||||||
|
bool is_ready;
|
||||||
|
void (*on_ready)(struct wv_buffer*);
|
||||||
|
void* userdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
TAILQ_HEAD(wv_buffer_queue, wv_buffer);
|
TAILQ_HEAD(wv_buffer_queue, wv_buffer);
|
||||||
|
|
|
@ -30,6 +30,7 @@ librt = cc.find_library('rt', required: false)
|
||||||
pixman = dependency('pixman-1')
|
pixman = dependency('pixman-1')
|
||||||
egl = dependency('egl')
|
egl = dependency('egl')
|
||||||
glesv2 = dependency('glesv2')
|
glesv2 = dependency('glesv2')
|
||||||
|
gbm = dependency('gbm')
|
||||||
xkbcommon = dependency('xkbcommon')
|
xkbcommon = dependency('xkbcommon')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ dependencies = [
|
||||||
aml,
|
aml,
|
||||||
egl,
|
egl,
|
||||||
glesv2,
|
glesv2,
|
||||||
|
gbm,
|
||||||
wayland_client,
|
wayland_client,
|
||||||
neatvnc,
|
neatvnc,
|
||||||
xkbcommon,
|
xkbcommon,
|
||||||
|
|
115
src/buffer.c
115
src/buffer.c
|
@ -6,13 +6,17 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <libdrm/drm_fourcc.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
|
||||||
|
#include "linux-dmabuf-unstable-v1.h"
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
#include "sys/queue.h"
|
#include "sys/queue.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "pixels.h"
|
#include "pixels.h"
|
||||||
|
|
||||||
extern struct wl_shm* wl_shm;
|
extern struct wl_shm* wl_shm;
|
||||||
|
extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf;
|
||||||
|
extern struct gbm_device* gbm_device;
|
||||||
|
|
||||||
struct wv_buffer* wv_buffer_create_shm(int width,
|
struct wv_buffer* wv_buffer_create_shm(int width,
|
||||||
int height, int stride, uint32_t fourcc)
|
int height, int stride, uint32_t fourcc)
|
||||||
|
@ -29,6 +33,7 @@ struct wv_buffer* wv_buffer_create_shm(int width,
|
||||||
self->height = height;
|
self->height = height;
|
||||||
self->stride = stride;
|
self->stride = stride;
|
||||||
self->format = fourcc;
|
self->format = fourcc;
|
||||||
|
self->is_ready = true;
|
||||||
|
|
||||||
self->size = height * stride;
|
self->size = height * stride;
|
||||||
int fd = shm_alloc_fd(self->size);
|
int fd = shm_alloc_fd(self->size);
|
||||||
|
@ -63,12 +68,93 @@ failure:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wv_buffer_dmabuf_created(void* data,
|
||||||
|
struct zwp_linux_buffer_params_v1* params,
|
||||||
|
struct wl_buffer* wl_buffer)
|
||||||
|
{
|
||||||
|
(void)params;
|
||||||
|
struct wv_buffer* self = data;
|
||||||
|
|
||||||
|
self->wl_buffer = wl_buffer;
|
||||||
|
self->is_ready = true;
|
||||||
|
|
||||||
|
if (self->on_ready)
|
||||||
|
self->on_ready(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wv_buffer_dmabuf_failed(void* data,
|
||||||
|
struct zwp_linux_buffer_params_v1* params)
|
||||||
|
{
|
||||||
|
(void)params;
|
||||||
|
struct wv_buffer* self = data;
|
||||||
|
|
||||||
|
if (self->on_ready)
|
||||||
|
self->on_ready(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_linux_buffer_params_v1_listener
|
||||||
|
wv_buffer_params_listener = {
|
||||||
|
.created = wv_buffer_dmabuf_created,
|
||||||
|
.failed = wv_buffer_dmabuf_failed,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
|
||||||
|
uint32_t fourcc)
|
||||||
|
{
|
||||||
|
assert(zwp_linux_dmabuf);
|
||||||
|
|
||||||
|
struct wv_buffer* self = calloc(1, sizeof(*self));
|
||||||
|
if (!self)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
self->type = WV_BUFFER_DMABUF;
|
||||||
|
self->width = width;
|
||||||
|
self->height = height;
|
||||||
|
self->format = fourcc;
|
||||||
|
|
||||||
|
self->bo = gbm_bo_create(gbm_device, width, height, fourcc,
|
||||||
|
GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
|
||||||
|
if (self->bo)
|
||||||
|
goto bo_failure;
|
||||||
|
|
||||||
|
struct zwp_linux_buffer_params_v1* params;
|
||||||
|
params = zwp_linux_dmabuf_v1_create_params(zwp_linux_dmabuf);
|
||||||
|
if (!params)
|
||||||
|
goto params_failure;
|
||||||
|
|
||||||
|
uint32_t offset = gbm_bo_get_offset(self->bo, 0);
|
||||||
|
uint32_t stride = gbm_bo_get_stride(self->bo);
|
||||||
|
uint64_t mod = gbm_bo_get_modifier(self->bo);
|
||||||
|
int fd = gbm_bo_get_fd(self->bo);
|
||||||
|
if (fd < 0)
|
||||||
|
goto fd_failure;
|
||||||
|
|
||||||
|
zwp_linux_buffer_params_v1_add(params, fd, 0, offset, stride,
|
||||||
|
mod >> 32, mod & 0xffffffff);
|
||||||
|
zwp_linux_buffer_params_v1_add_listener(params,
|
||||||
|
&wv_buffer_params_listener, self);
|
||||||
|
zwp_linux_buffer_params_v1_create(params, width, height, fourcc,
|
||||||
|
/* flags */ 0);
|
||||||
|
|
||||||
|
close(fd); // TODO: Maybe keep this open?
|
||||||
|
return self;
|
||||||
|
|
||||||
|
fd_failure:
|
||||||
|
params_failure:
|
||||||
|
gbm_bo_destroy(self->bo);
|
||||||
|
bo_failure:
|
||||||
|
free(self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
case WV_BUFFER_DMABUF:
|
||||||
|
return wv_buffer_create_dmabuf(width, height, fourcc);
|
||||||
case WV_BUFFER_UNSPEC:;
|
case WV_BUFFER_UNSPEC:;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,35 +169,64 @@ static void wv_buffer_destroy_shm(struct wv_buffer* self)
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wv_buffer_destroy_dmabuf(struct wv_buffer* self)
|
||||||
|
{
|
||||||
|
wl_buffer_destroy(self->wl_buffer);
|
||||||
|
gbm_bo_destroy(self->bo);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
void wv_buffer_destroy(struct wv_buffer* self)
|
void wv_buffer_destroy(struct wv_buffer* self)
|
||||||
{
|
{
|
||||||
switch (self->type) {
|
switch (self->type) {
|
||||||
case WV_BUFFER_SHM:
|
case WV_BUFFER_SHM:
|
||||||
wv_buffer_destroy_shm(self);
|
wv_buffer_destroy_shm(self);
|
||||||
return;
|
return;
|
||||||
|
case WV_BUFFER_DMABUF:
|
||||||
|
wv_buffer_destroy_dmabuf(self);
|
||||||
|
return;
|
||||||
case WV_BUFFER_UNSPEC:;
|
case WV_BUFFER_UNSPEC:;
|
||||||
}
|
}
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wv_buffer_map_dmabuf(struct wv_buffer* self)
|
||||||
|
{
|
||||||
|
uint32_t stride = 0;
|
||||||
|
self->pixels = gbm_bo_map(self->bo, 0, 0, self->width, self->height,
|
||||||
|
GBM_BO_TRANSFER_READ, &stride, &self->bo_map_handle);
|
||||||
|
self->stride = stride;
|
||||||
|
return self->pixels ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
case WV_BUFFER_DMABUF:
|
||||||
|
return wv_buffer_map_dmabuf(self);
|
||||||
case WV_BUFFER_UNSPEC:;
|
case WV_BUFFER_UNSPEC:;
|
||||||
}
|
}
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wv_buffer_unmap_dmabuf(struct wv_buffer* self)
|
||||||
|
{
|
||||||
|
gbm_bo_unmap(self->bo, self->bo_map_handle);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
case WV_BUFFER_DMABUF:
|
||||||
|
return wv_buffer_unmap_dmabuf(self);
|
||||||
case WV_BUFFER_UNSPEC:;
|
case WV_BUFFER_UNSPEC:;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
|
|
|
@ -111,6 +111,8 @@ void on_capture_done(struct frame_capture* capture);
|
||||||
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
||||||
|
|
||||||
struct wl_shm* wl_shm = NULL;
|
struct wl_shm* wl_shm = NULL;
|
||||||
|
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf = NULL;
|
||||||
|
struct gbm_device* gbm_device = NULL;
|
||||||
|
|
||||||
static enum frame_capture_backend_type
|
static enum frame_capture_backend_type
|
||||||
frame_capture_backend_from_string(const char* str)
|
frame_capture_backend_from_string(const char* str)
|
||||||
|
|
Loading…
Reference in New Issue