diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 269af7e2..fb473ba8 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -21,6 +21,7 @@ #include #include #include +#include struct wlr_egl { EGLenum platform; @@ -42,6 +43,8 @@ struct wlr_egl { } exts; struct wl_display *wl_display; + + struct wlr_drm_format_set dmabuf_formats; }; // TODO: Allocate and return a wlr_egl @@ -88,13 +91,7 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, /** * Get the available dmabuf formats */ -int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, int **formats); - -/** - * Get the available dmabuf modifiers for a given format - */ -int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, int format, - uint64_t **modifiers); +const struct wlr_drm_format_set *wlr_egl_get_dmabuf_formats(struct wlr_egl *egl); bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, int32_t width, int32_t height, uint32_t flags, diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index c98a7cda..088b1efa 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -46,9 +46,8 @@ struct wlr_renderer_impl { struct wl_resource *resource); void (*wl_drm_buffer_get_size)(struct wlr_renderer *renderer, struct wl_resource *buffer, int *width, int *height); - int (*get_dmabuf_formats)(struct wlr_renderer *renderer, int **formats); - int (*get_dmabuf_modifiers)(struct wlr_renderer *renderer, int format, - uint64_t **modifiers); + const struct wlr_drm_format_set *(*get_dmabuf_formats)( + struct wlr_renderer *renderer); enum wl_shm_format (*preferred_read_format)(struct wlr_renderer *renderer); bool (*read_pixels)(struct wlr_renderer *renderer, enum wl_shm_format fmt, uint32_t *flags, uint32_t stride, uint32_t width, uint32_t height, diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index 9c031b7f..33f96b68 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -20,6 +20,7 @@ enum wlr_renderer_read_pixels_flags { }; struct wlr_renderer_impl; +struct wlr_drm_format_set; struct wlr_renderer { const struct wlr_renderer_impl *impl; @@ -87,15 +88,10 @@ bool wlr_renderer_resource_is_wl_drm_buffer(struct wlr_renderer *renderer, void wlr_renderer_wl_drm_buffer_get_size(struct wlr_renderer *renderer, struct wl_resource *buffer, int *width, int *height); /** - * Get the available dmabuf formats + * Get the available DMA-BUF formats. */ -int wlr_renderer_get_dmabuf_formats(struct wlr_renderer *renderer, - int **formats); -/** - * Get the available dmabuf modifiers for a given format - */ -int wlr_renderer_get_dmabuf_modifiers(struct wlr_renderer *renderer, int format, - uint64_t **modifiers); +const struct wlr_drm_format_set *wlr_renderer_get_dmabuf_formats( + struct wlr_renderer *renderer); /** * Reads out of pixels of the currently bound surface into data. `stride` is in * bytes. diff --git a/render/egl.c b/render/egl.c index cc00dece..450f8fc7 100644 --- a/render/egl.c +++ b/render/egl.c @@ -1,7 +1,7 @@ -#include -#include #include #include +#include +#include #include #include #include @@ -77,24 +77,49 @@ static bool check_egl_ext(const char *exts, const char *ext) { return false; } -static void print_dmabuf_formats(struct wlr_egl *egl) { - /* Avoid log msg if extension is not present */ - if (!egl->exts.image_dmabuf_import_modifiers_ext) { - return; - } +static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats); +static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format, + uint64_t **modifiers); +static void init_dmabuf_formats(struct wlr_egl *egl) { int *formats; - int num = wlr_egl_get_dmabuf_formats(egl, &formats); - if (num < 0) { + int formats_len = get_egl_dmabuf_formats(egl, &formats); + if (formats_len < 0) { return; } - char str_formats[num * 5 + 1]; - for (int i = 0; i < num; i++) { - snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ", + for (int i = 0; i < formats_len; i++) { + uint32_t fmt = formats[i]; + + uint64_t *modifiers; + int modifiers_len = get_egl_dmabuf_modifiers(egl, fmt, &modifiers); + if (modifiers_len < 0) { + continue; + } + + if (modifiers_len == 0) { + wlr_drm_format_set_add(&egl->dmabuf_formats, fmt, DRM_FORMAT_MOD_INVALID); + } + + for (int j = 0; j < modifiers_len; j++) { + wlr_drm_format_set_add(&egl->dmabuf_formats, fmt, modifiers[j]); + } + + free(modifiers); + } + + char *str_formats = malloc(formats_len * 5 + 1); + if (str_formats == NULL) { + goto out; + } + for (int i = 0; i < formats_len; i++) { + snprintf(&str_formats[i*5], (formats_len - i) * 5 + 1, "%.4s ", (char*)&formats[i]); } wlr_log(WLR_DEBUG, "Supported dmabuf buffer formats: %s", str_formats); + free(str_formats); + +out: free(formats); } @@ -173,7 +198,7 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, check_egl_ext(egl->exts_str, "EGL_MESA_image_dma_buf_export") && eglExportDMABUFImageQueryMESA && eglExportDMABUFImageMESA; - print_dmabuf_formats(egl); + init_dmabuf_formats(egl); egl->exts.bind_wayland_display_wl = check_egl_ext(egl->exts_str, "EGL_WL_bind_wayland_display") @@ -242,6 +267,8 @@ void wlr_egl_finish(struct wlr_egl *egl) { return; } + wlr_drm_format_set_finish(&egl->dmabuf_formats); + eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (egl->wl_display) { assert(egl->exts.bind_wayland_display_wl); @@ -486,10 +513,9 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); } -int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, - int **formats) { +static int get_egl_dmabuf_formats(struct wlr_egl *egl, int **formats) { if (!egl->exts.image_dmabuf_import_ext) { - wlr_log(WLR_DEBUG, "dmabuf import extension not present"); + wlr_log(WLR_DEBUG, "DMA-BUF import extension not present"); return -1; } @@ -518,7 +544,7 @@ int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, EGLint num; if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) { - wlr_log(WLR_ERROR, "failed to query number of dmabuf formats"); + wlr_log(WLR_ERROR, "Failed to query number of dmabuf formats"); return -1; } @@ -529,17 +555,17 @@ int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, } if (!eglQueryDmaBufFormatsEXT(egl->display, num, *formats, &num)) { - wlr_log(WLR_ERROR, "failed to query dmabuf format"); + wlr_log(WLR_ERROR, "Failed to query dmabuf format"); free(*formats); return -1; } return num; } -int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, - int format, uint64_t **modifiers) { +static int get_egl_dmabuf_modifiers(struct wlr_egl *egl, int format, + uint64_t **modifiers) { if (!egl->exts.image_dmabuf_import_ext) { - wlr_log(WLR_DEBUG, "dmabuf extension not present"); + wlr_log(WLR_DEBUG, "DMA-BUF extension not present"); return -1; } @@ -551,7 +577,7 @@ int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, EGLint num; if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0, NULL, NULL, &num)) { - wlr_log(WLR_ERROR, "failed to query dmabuf number of modifiers"); + wlr_log(WLR_ERROR, "Failed to query dmabuf number of modifiers"); return -1; } @@ -563,13 +589,17 @@ int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, if (!eglQueryDmaBufModifiersEXT(egl->display, format, num, *modifiers, NULL, &num)) { - wlr_log(WLR_ERROR, "failed to query dmabuf modifiers"); + wlr_log(WLR_ERROR, "Failed to query dmabuf modifiers"); free(*modifiers); return -1; } return num; } +const struct wlr_drm_format_set *wlr_egl_get_dmabuf_formats(struct wlr_egl *egl) { + return &egl->dmabuf_formats; +} + bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, int32_t width, int32_t height, uint32_t flags, struct wlr_dmabuf_attributes *attribs) { diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 3409d144..dce1f162 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -247,16 +247,10 @@ static void gles2_wl_drm_buffer_get_size(struct wlr_renderer *wlr_renderer, eglQueryWaylandBufferWL(renderer->egl->display, buffer, EGL_HEIGHT, height); } -static int gles2_get_dmabuf_formats(struct wlr_renderer *wlr_renderer, - int **formats) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - return wlr_egl_get_dmabuf_formats(renderer->egl, formats); -} - -static int gles2_get_dmabuf_modifiers(struct wlr_renderer *wlr_renderer, - int format, uint64_t **modifiers) { +static const struct wlr_drm_format_set *gles2_get_dmabuf_formats( + struct wlr_renderer *wlr_renderer) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - return wlr_egl_get_dmabuf_modifiers(renderer->egl, format, modifiers); + return wlr_egl_get_dmabuf_formats(renderer->egl); } static enum wl_shm_format gles2_preferred_read_format( @@ -402,7 +396,6 @@ static const struct wlr_renderer_impl renderer_impl = { .resource_is_wl_drm_buffer = gles2_resource_is_wl_drm_buffer, .wl_drm_buffer_get_size = gles2_wl_drm_buffer_get_size, .get_dmabuf_formats = gles2_get_dmabuf_formats, - .get_dmabuf_modifiers = gles2_get_dmabuf_modifiers, .preferred_read_format = gles2_preferred_read_format, .read_pixels = gles2_read_pixels, .texture_from_pixels = gles2_texture_from_pixels, diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 58731d7f..802cbdbd 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -123,20 +123,12 @@ void wlr_renderer_wl_drm_buffer_get_size(struct wlr_renderer *r, return r->impl->wl_drm_buffer_get_size(r, buffer, width, height); } -int wlr_renderer_get_dmabuf_formats(struct wlr_renderer *r, - int **formats) { +const struct wlr_drm_format_set *wlr_renderer_get_dmabuf_formats( + struct wlr_renderer *r) { if (!r->impl->get_dmabuf_formats) { - return -1; - } - return r->impl->get_dmabuf_formats(r, formats); -} - -int wlr_renderer_get_dmabuf_modifiers(struct wlr_renderer *r, int format, - uint64_t **modifiers) { - if (!r->impl->get_dmabuf_modifiers) { - return -1; + return NULL; } - return r->impl->get_dmabuf_modifiers(r, format, modifiers); + return r->impl->get_dmabuf_formats(r); } bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt, diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index 179602e1..19eab3f1 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -386,45 +387,39 @@ struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_from_resource( static void linux_dmabuf_send_formats(struct wlr_linux_dmabuf_v1 *linux_dmabuf, struct wl_resource *resource, uint32_t version) { - struct wlr_renderer *renderer = linux_dmabuf->renderer; uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID; - int *formats = NULL; - int num_formats = wlr_renderer_get_dmabuf_formats(renderer, &formats); - if (num_formats < 0) { + const struct wlr_drm_format_set *formats = + wlr_renderer_get_dmabuf_formats(linux_dmabuf->renderer); + if (formats == NULL) { return; } - for (int i = 0; i < num_formats; i++) { - uint64_t *modifiers = NULL; - int num_modifiers = wlr_renderer_get_dmabuf_modifiers(renderer, - formats[i], &modifiers); - if (num_modifiers < 0) { - return; - } - /* send DRM_FORMAT_MOD_INVALID token when no modifiers are supported - * for this format */ - if (num_modifiers == 0) { - num_modifiers = 1; + for (size_t i = 0; i < formats->len; i++) { + struct wlr_drm_format *fmt = formats->formats[i]; + + size_t modifiers_len = fmt->len; + uint64_t *modifiers = fmt->modifiers; + + // Send DRM_FORMAT_MOD_INVALID token when no modifiers are supported + // for this format + if (modifiers_len == 0) { + modifiers_len = 1; modifiers = &modifier_invalid; } - for (int j = 0; j < num_modifiers; j++) { + for (size_t j = 0; j < modifiers_len; j++) { if (version >= ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) { uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF; uint32_t modifier_hi = modifiers[j] >> 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) { - zwp_linux_dmabuf_v1_send_format(resource, formats[i]); + modifiers == &modifier_invalid) { + zwp_linux_dmabuf_v1_send_format(resource, fmt->format); } } - if (modifiers != &modifier_invalid) { - free(modifiers); - } } - free(formats); } static void linux_dmabuf_resource_destroy(struct wl_resource *resource) {