mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-07 08:28:09 +02:00
Merge branch 'vnc-enable-dmabuf' into 'main'
backend-vnc: Enable dmabuf See merge request wayland/weston!1988
This commit is contained in:
commit
ae4f4c8ca6
4 changed files with 184 additions and 46 deletions
|
|
@ -81,6 +81,18 @@ struct vnc_backend {
|
|||
unsigned int formats_count;
|
||||
};
|
||||
|
||||
struct vnc_fbq_item {
|
||||
struct nvnc_fb* fb;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct vnc_fb_pool {
|
||||
int ref;
|
||||
struct wl_list fbs;
|
||||
|
||||
struct vnc_backend *backend;
|
||||
};
|
||||
|
||||
struct vnc_output {
|
||||
struct weston_output base;
|
||||
struct weston_plane cursor_plane;
|
||||
|
|
@ -89,11 +101,12 @@ struct vnc_output {
|
|||
struct wl_event_source *finish_frame_timer;
|
||||
struct nvnc_display *display;
|
||||
|
||||
struct nvnc_fb_pool *fb_pool;
|
||||
struct vnc_fb_pool *fb_pool;
|
||||
|
||||
struct wl_list peers;
|
||||
|
||||
bool resizeable;
|
||||
bool use_dma;
|
||||
};
|
||||
|
||||
struct vnc_peer {
|
||||
|
|
@ -113,6 +126,7 @@ struct vnc_buffer {
|
|||
weston_renderbuffer_t rb;
|
||||
struct nvnc_fb *fb;
|
||||
struct vnc_output *output;
|
||||
struct linux_dmabuf_memory *dma;
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -292,6 +306,143 @@ static const uint32_t vnc_formats[] = {
|
|||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static void
|
||||
vnc_fb_pool_destroy_fbs(struct vnc_fb_pool *self)
|
||||
{
|
||||
struct vnc_fbq_item *item, *tmp;
|
||||
|
||||
wl_list_for_each_safe(item, tmp, &self->fbs, link) {
|
||||
nvnc_fb_unref(item->fb);
|
||||
wl_list_remove(&item->link);
|
||||
free(item);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vnc_fb_pool_unref(struct vnc_fb_pool *self)
|
||||
{
|
||||
if (--self->ref > 0)
|
||||
return;
|
||||
|
||||
vnc_fb_pool_destroy_fbs(self);
|
||||
free(self);
|
||||
}
|
||||
|
||||
static struct vnc_fb_pool*
|
||||
vnc_fb_pool_new(struct vnc_backend* backend)
|
||||
{
|
||||
struct vnc_fb_pool* self;
|
||||
|
||||
self = zalloc(sizeof *self);
|
||||
if (self == NULL)
|
||||
return NULL;
|
||||
|
||||
wl_list_init(&self->fbs);
|
||||
self->ref = 1;
|
||||
self->backend = backend;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
vnc_fb_pool_release_fn(struct nvnc_fb* fb, void *context)
|
||||
{
|
||||
struct vnc_fbq_item* item;
|
||||
struct vnc_fb_pool* self = context;
|
||||
struct weston_mode *current_mode =
|
||||
self->backend->output->base.current_mode;
|
||||
|
||||
// Drop fb if it's properties do not align with current mode.
|
||||
if (nvnc_fb_get_width(fb) != current_mode->width ||
|
||||
nvnc_fb_get_height(fb) != current_mode->height ||
|
||||
nvnc_fb_get_fourcc_format(fb) !=
|
||||
self->backend->formats[0]->format ||
|
||||
(nvnc_fb_get_type(fb) != NVNC_FB_GBM_BO &&
|
||||
nvnc_fb_get_stride(fb) != current_mode->width)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nvnc_fb_ref(fb);
|
||||
|
||||
item = zalloc(sizeof *item);
|
||||
assert(item);
|
||||
item->fb = fb;
|
||||
wl_list_insert(&self->fbs, &item->link);
|
||||
}
|
||||
|
||||
static struct nvnc_fb*
|
||||
vnc_fb_pool_acquire_from_list(struct vnc_fb_pool* self)
|
||||
{
|
||||
struct vnc_fbq_item* item;
|
||||
struct nvnc_fb* fb;
|
||||
|
||||
item = wl_container_of(self->fbs.next, item, link);
|
||||
fb = item->fb;
|
||||
assert(item && fb);
|
||||
|
||||
wl_list_remove(&item->link);
|
||||
free(item);
|
||||
|
||||
self->ref++;
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
static struct nvnc_fb*
|
||||
vnc_fb_pool_acquire_new(struct vnc_fb_pool* self)
|
||||
{
|
||||
struct vnc_output *output = self->backend->output;
|
||||
struct weston_mode *current_mode = output->base.current_mode;
|
||||
struct linux_dmabuf_memory *linux_dmabuf_memory = NULL;
|
||||
struct nvnc_fb *fb = NULL;
|
||||
struct vnc_buffer *buffer;
|
||||
|
||||
#ifdef HAVE_GBM
|
||||
if (output->use_dma) {
|
||||
struct weston_renderer *rdr = output->base.compositor->renderer;
|
||||
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
||||
|
||||
linux_dmabuf_memory =
|
||||
rdr->dmabuf_alloc(rdr, current_mode->width,
|
||||
current_mode->height,
|
||||
self->backend->formats[0]->format,
|
||||
modifier, ARRAY_LENGTH(modifier));
|
||||
|
||||
// Don't try to use dma again if allocation failed once.
|
||||
if (!linux_dmabuf_memory)
|
||||
output->use_dma = false;
|
||||
else
|
||||
fb = nvnc_fb_from_gbm_bo(linux_dmabuf_memory->bo);
|
||||
|
||||
}
|
||||
|
||||
if (!fb)
|
||||
#endif
|
||||
fb = nvnc_fb_new(current_mode->width, current_mode->height,
|
||||
self->backend->formats[0]->format,
|
||||
current_mode->width);
|
||||
|
||||
assert(fb);
|
||||
|
||||
buffer = xzalloc(sizeof *buffer);
|
||||
buffer->dma = linux_dmabuf_memory;
|
||||
|
||||
nvnc_set_userdata(fb, buffer, (nvnc_cleanup_fn) vnc_buffer_destroy);
|
||||
nvnc_fb_set_release_fn(fb, vnc_fb_pool_release_fn, self);
|
||||
self->ref++;
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
static struct nvnc_fb*
|
||||
vnc_fb_pool_acquire(struct vnc_fb_pool* self)
|
||||
{
|
||||
if (wl_list_empty(&self->fbs))
|
||||
return vnc_fb_pool_acquire_new(self);
|
||||
else
|
||||
return vnc_fb_pool_acquire_from_list(self);
|
||||
}
|
||||
|
||||
static void
|
||||
vnc_handle_key_event(struct nvnc_client *client, uint32_t keysym,
|
||||
bool is_pressed)
|
||||
|
|
@ -675,35 +826,29 @@ vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
|
|||
weston_log_scope_printf(backend->debug, "\n\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
vnc_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||
{
|
||||
struct vnc_buffer *buffer = (struct vnc_buffer *) data;
|
||||
|
||||
assert(nvnc_get_userdata(buffer->fb) == buffer);
|
||||
|
||||
nvnc_set_userdata(buffer->fb, NULL, NULL);
|
||||
vnc_buffer_destroy(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct vnc_buffer *
|
||||
vnc_buffer_create(struct nvnc_fb* fb, struct vnc_output *output)
|
||||
static void
|
||||
vnc_renderbuffer_create(struct vnc_buffer *buffer, struct nvnc_fb* fb,
|
||||
struct vnc_output *output)
|
||||
{
|
||||
const struct pixel_format_info *pfmt =
|
||||
pixel_format_get_info(DRM_FORMAT_XRGB8888);
|
||||
struct weston_renderer *rdr = output->base.compositor->renderer;
|
||||
struct vnc_buffer *buffer = xmalloc(sizeof *buffer);
|
||||
|
||||
buffer->rb = rdr->create_renderbuffer(&output->base, pfmt,
|
||||
nvnc_fb_get_addr(fb),
|
||||
output->base.current_mode->width * 4,
|
||||
vnc_rb_discarded_cb, buffer);
|
||||
#ifdef HAVE_GBM
|
||||
if (nvnc_fb_get_type(fb) == NVNC_FB_GBM_BO)
|
||||
buffer->rb =
|
||||
rdr->create_renderbuffer_dmabuf(&output->base,
|
||||
buffer->dma, NULL,
|
||||
NULL);
|
||||
else
|
||||
#endif
|
||||
buffer->rb =
|
||||
rdr->create_renderbuffer(&output->base, pfmt,
|
||||
nvnc_fb_get_addr(fb),
|
||||
output->base.current_mode->width * 4,
|
||||
NULL, NULL);
|
||||
buffer->fb = fb;
|
||||
buffer->output = output;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -711,7 +856,8 @@ vnc_buffer_destroy(struct vnc_buffer *buffer)
|
|||
{
|
||||
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
|
||||
|
||||
rdr->destroy_renderbuffer(buffer->rb);
|
||||
if (buffer->rb)
|
||||
rdr->destroy_renderbuffer(buffer->rb);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
|
@ -727,15 +873,11 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
|||
pixman_region16_t nvnc_damage;
|
||||
struct nvnc_fb *fb;
|
||||
|
||||
fb = nvnc_fb_pool_acquire(output->fb_pool);
|
||||
assert(fb);
|
||||
fb = vnc_fb_pool_acquire(output->fb_pool);
|
||||
|
||||
buffer = nvnc_get_userdata(fb);
|
||||
if (!buffer) {
|
||||
buffer = vnc_buffer_create(fb, output);
|
||||
nvnc_set_userdata(fb, buffer,
|
||||
(nvnc_cleanup_fn) vnc_buffer_destroy);
|
||||
}
|
||||
if (!buffer->rb)
|
||||
vnc_renderbuffer_create(buffer, fb, output);
|
||||
|
||||
vnc_log_damage(backend, damage);
|
||||
|
||||
|
|
@ -867,10 +1009,7 @@ vnc_output_enable(struct weston_output *base)
|
|||
finish_frame_handler,
|
||||
output);
|
||||
|
||||
output->fb_pool = nvnc_fb_pool_new(output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
backend->formats[0]->format,
|
||||
output->base.current_mode->width);
|
||||
output->fb_pool = vnc_fb_pool_new(backend);
|
||||
|
||||
output->display = nvnc_display_new(0, 0);
|
||||
|
||||
|
|
@ -895,7 +1034,7 @@ vnc_output_disable(struct weston_output *base)
|
|||
|
||||
nvnc_remove_display(backend->server, output->display);
|
||||
nvnc_display_unref(output->display);
|
||||
nvnc_fb_pool_unref(output->fb_pool);
|
||||
vnc_fb_pool_unref(output->fb_pool);
|
||||
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
|
|
@ -951,6 +1090,7 @@ vnc_create_output(struct weston_backend *backend, const char *name)
|
|||
output->base.attach_head = NULL;
|
||||
|
||||
output->backend = b;
|
||||
output->use_dma = b->compositor->renderer->import_dmabuf != NULL;
|
||||
|
||||
weston_compositor_add_pending_output(&output->base, b->compositor);
|
||||
|
||||
|
|
@ -1120,15 +1260,13 @@ vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
|||
/* vnc_buffers are stored as user data pointers into the renderbuffers
|
||||
* for the discarded callback. weston_renderer_resize_output(), which
|
||||
* triggers the renderbuffer's discarded callbacks, must be called
|
||||
* before nvnc_fb_pool_resize(), which destroys all the nvnc_fbs and
|
||||
* before vnc_fb_pool_destroy_fbs(), which destroys all the nvnc_fbs and
|
||||
* their associated vnc_buffers, so that the vnc_buffers are valid at
|
||||
* callback. */
|
||||
if (!weston_renderer_resize_output(base, &fb_size, NULL))
|
||||
return -1;
|
||||
|
||||
nvnc_fb_pool_resize(output->fb_pool, target_mode->width,
|
||||
target_mode->height, DRM_FORMAT_XRGB8888,
|
||||
target_mode->width);
|
||||
vnc_fb_pool_destroy_fbs(output->fb_pool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,10 @@ typedef bool (*weston_renderbuffer_discarded_func)(weston_renderbuffer_t renderb
|
|||
struct weston_renderer_options {
|
||||
};
|
||||
|
||||
struct gbm_bo;
|
||||
struct linux_dmabuf_memory {
|
||||
struct dmabuf_attributes *attributes;
|
||||
struct gbm_bo *bo;
|
||||
|
||||
void (*destroy)(struct linux_dmabuf_memory *dmabuf);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -227,7 +227,6 @@ struct dmabuf_allocator {
|
|||
struct gl_renderer_dmabuf_memory {
|
||||
struct linux_dmabuf_memory base;
|
||||
struct dmabuf_allocator *allocator;
|
||||
struct gbm_bo *bo;
|
||||
};
|
||||
|
||||
struct dmabuf_format {
|
||||
|
|
@ -4994,7 +4993,7 @@ gl_renderer_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
|
|||
close(attributes->fd[i]);
|
||||
free(dmabuf->attributes);
|
||||
|
||||
gbm_bo_destroy(gl_renderer_dmabuf->bo);
|
||||
gbm_bo_destroy(gl_renderer_dmabuf->base.bo);
|
||||
free(gl_renderer_dmabuf);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -5032,7 +5031,7 @@ gl_renderer_dmabuf_alloc(struct weston_renderer *renderer,
|
|||
}
|
||||
|
||||
gl_renderer_dmabuf = xzalloc(sizeof(*gl_renderer_dmabuf));
|
||||
gl_renderer_dmabuf->bo = bo;
|
||||
gl_renderer_dmabuf->base.bo = bo;
|
||||
gl_renderer_dmabuf->allocator = allocator;
|
||||
|
||||
attributes = xzalloc(sizeof(*attributes));
|
||||
|
|
|
|||
|
|
@ -271,7 +271,6 @@ struct dmabuf_allocator {
|
|||
struct vulkan_renderer_dmabuf_memory {
|
||||
struct linux_dmabuf_memory base;
|
||||
struct dmabuf_allocator *allocator;
|
||||
struct gbm_bo *bo;
|
||||
};
|
||||
|
||||
struct dmabuf_format {
|
||||
|
|
@ -749,7 +748,7 @@ vulkan_renderer_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
|
|||
close(attributes->fd[i]);
|
||||
free(dmabuf->attributes);
|
||||
|
||||
gbm_bo_destroy(vulkan_renderer_dmabuf->bo);
|
||||
gbm_bo_destroy(vulkan_renderer_dmabuf->base.bo);
|
||||
free(vulkan_renderer_dmabuf);
|
||||
}
|
||||
|
||||
|
|
@ -785,7 +784,7 @@ vulkan_renderer_dmabuf_alloc(struct weston_renderer *renderer,
|
|||
}
|
||||
|
||||
vulkan_renderer_dmabuf = xzalloc(sizeof(*vulkan_renderer_dmabuf));
|
||||
vulkan_renderer_dmabuf->bo = bo;
|
||||
vulkan_renderer_dmabuf->base.bo = bo;
|
||||
vulkan_renderer_dmabuf->allocator = allocator;
|
||||
|
||||
attributes = xzalloc(sizeof(*attributes));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue