diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index a68febc5..03b23171 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -919,6 +919,8 @@ struct weston_plane { struct wl_list link; }; +struct weston_drm_format_array; + struct weston_renderer { int (*read_pixels)(struct weston_output *output, pixman_format_code_t format, void *pixels, @@ -948,14 +950,8 @@ struct weston_renderer { bool (*import_dmabuf)(struct weston_compositor *ec, struct linux_dmabuf_buffer *buffer); - /** On error sets num_formats to zero */ - void (*query_dmabuf_formats)(struct weston_compositor *ec, - int **formats, int *num_formats); - - /** On error sets num_modifiers to zero */ - void (*query_dmabuf_modifiers)(struct weston_compositor *ec, - int format, uint64_t **modifiers, - int *num_modifiers); + const struct weston_drm_format_array * + (*get_supported_formats)(struct weston_compositor *ec); }; enum weston_capability { diff --git a/libweston/linux-dmabuf.c b/libweston/linux-dmabuf.c index a06e324b..60373d39 100644 --- a/libweston/linux-dmabuf.c +++ b/libweston/linux-dmabuf.c @@ -477,12 +477,12 @@ bind_linux_dmabuf(struct wl_client *client, void *data, uint32_t version, uint32_t id) { struct weston_compositor *compositor = data; + const struct weston_drm_format_array *supported_formats; struct wl_resource *resource; - int *formats = NULL; - uint64_t *modifiers = NULL; - int num_formats, num_modifiers; - uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID; - int i, j; + struct weston_drm_format *fmt; + const uint64_t *modifiers; + unsigned int num_modifiers; + unsigned int i; resource = wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id); @@ -494,43 +494,25 @@ bind_linux_dmabuf(struct wl_client *client, wl_resource_set_implementation(resource, &linux_dmabuf_implementation, compositor, NULL); - /* - * Use EGL_EXT_image_dma_buf_import_modifiers to query and advertise - * format/modifier codes. - */ - compositor->renderer->query_dmabuf_formats(compositor, &formats, - &num_formats); - - for (i = 0; i < num_formats; i++) { - compositor->renderer->query_dmabuf_modifiers(compositor, - formats[i], - &modifiers, - &num_modifiers); - - /* send DRM_FORMAT_MOD_INVALID token when no modifiers are supported - * for this format */ - if (num_modifiers == 0) { - num_modifiers = 1; - modifiers = &modifier_invalid; - } - for (j = 0; j < num_modifiers; j++) { + /* Advertise the formats/modifiers */ + supported_formats = compositor->renderer->get_supported_formats(compositor); + wl_array_for_each(fmt, &supported_formats->arr) { + modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers); + for (i = 0; i < num_modifiers; i++) { if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) { - uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF; - uint32_t modifier_hi = modifiers[j] >> 32; + uint32_t modifier_lo = modifiers[i] & 0xFFFFFFFF; + uint32_t modifier_hi = modifiers[i] >> 32; zwp_linux_dmabuf_v1_send_modifier(resource, - formats[i], + fmt->format, modifier_hi, modifier_lo); - } else if (modifiers[j] == DRM_FORMAT_MOD_LINEAR || - modifiers == &modifier_invalid) { + } else if (modifiers[i] == DRM_FORMAT_MOD_LINEAR || + modifiers[i] == DRM_FORMAT_MOD_INVALID) { zwp_linux_dmabuf_v1_send_format(resource, - formats[i]); + fmt->format); } } - if (modifiers != &modifier_invalid) - free(modifiers); } - free(formats); } /** Advertise linux_dmabuf support diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h index 06904d5f..35203dd3 100644 --- a/libweston/renderer-gl/gl-renderer-internal.h +++ b/libweston/renderer-gl/gl-renderer-internal.h @@ -108,6 +108,8 @@ struct gl_renderer { struct wl_array vertices; struct wl_array vtxcnt; + struct weston_drm_format_array supported_formats; + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; PFNEGLCREATEIMAGEKHRPROC create_image; PFNEGLDESTROYIMAGEKHRPROC destroy_image; diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 8e332722..3b8a2932 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -2777,6 +2777,63 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface, gs->shader_variant = image->shader_variant; } +static const struct weston_drm_format_array * +gl_renderer_get_supported_formats(struct weston_compositor *ec) +{ + struct gl_renderer *gr = get_renderer(ec); + + return &gr->supported_formats; +} + +static int +populate_supported_formats(struct weston_compositor *ec, + struct weston_drm_format_array *supported_formats) +{ + struct weston_drm_format *fmt; + int *formats = NULL; + uint64_t *modifiers = NULL; + unsigned int num_formats, num_modifiers; + unsigned int i, j; + int ret = 0; + + /* Use EGL_EXT_image_dma_buf_import_modifiers to query the + * list of formats/modifiers of the renderer. */ + gl_renderer_query_dmabuf_formats(ec, &formats, &num_formats); + if (num_formats == 0) + return 0; + + for (i = 0; i < num_formats; i++) { + fmt = weston_drm_format_array_add_format(supported_formats, + formats[i]); + if (!fmt) { + ret = -1; + goto out; + } + + gl_renderer_query_dmabuf_modifiers(ec, formats[i], + &modifiers, &num_modifiers); + if (num_modifiers == 0) { + ret = weston_drm_format_add_modifier(fmt, DRM_FORMAT_MOD_INVALID); + if (ret < 0) + goto out; + continue; + } + + for (j = 0; j < num_modifiers; j++) { + ret = weston_drm_format_add_modifier(fmt, modifiers[j]); + if (ret < 0) { + free(modifiers); + goto out; + } + } + free(modifiers); + } + +out: + free(formats); + return ret; +} + static void gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { @@ -3423,6 +3480,8 @@ gl_renderer_destroy(struct weston_compositor *ec) wl_list_for_each_safe(format, next_format, &gr->dmabuf_formats, link) dmabuf_format_destroy(format); + weston_drm_format_array_fini(&gr->supported_formats); + if (gr->dummy_surface != EGL_NO_SURFACE) weston_platform_destroy_egl_surface(gr->egl_display, gr->dummy_surface); @@ -3495,6 +3554,7 @@ gl_renderer_display_create(struct weston_compositor *ec, const struct gl_renderer_display_options *options) { struct gl_renderer *gr; + int ret; gr = zalloc(sizeof *gr); if (gr == NULL) @@ -3524,6 +3584,8 @@ gl_renderer_display_create(struct weston_compositor *ec, if (gl_renderer_setup_egl_display(gr, options->egl_native_display) < 0) goto fail; + weston_drm_format_array_init(&gr->supported_formats); + log_egl_info(gr->egl_display); ec->renderer = &gr->base; @@ -3557,10 +3619,10 @@ gl_renderer_display_create(struct weston_compositor *ec, wl_list_init(&gr->dmabuf_images); if (gr->has_dmabuf_import) { gr->base.import_dmabuf = gl_renderer_import_dmabuf; - gr->base.query_dmabuf_formats = - gl_renderer_query_dmabuf_formats; - gr->base.query_dmabuf_modifiers = - gl_renderer_query_dmabuf_modifiers; + gr->base.get_supported_formats = gl_renderer_get_supported_formats; + ret = populate_supported_formats(ec, &gr->supported_formats); + if (ret < 0) + goto fail_terminate; } wl_list_init(&gr->dmabuf_formats); @@ -3598,6 +3660,7 @@ gl_renderer_display_create(struct weston_compositor *ec, fail_with_error: gl_renderer_print_egl_error_state(); fail_terminate: + weston_drm_format_array_fini(&gr->supported_formats); eglTerminate(gr->egl_display); fail: weston_log_scope_destroy(gr->shader_scope);