diff options
Diffstat (limited to 'render')
-rw-r--r-- | render/drm_format_set.c | 105 | ||||
-rw-r--r-- | render/egl.c | 76 | ||||
-rw-r--r-- | render/gles2/renderer.c | 13 | ||||
-rw-r--r-- | render/meson.build | 3 | ||||
-rw-r--r-- | render/wlr_renderer.c | 16 |
5 files changed, 167 insertions, 46 deletions
diff --git a/render/drm_format_set.c b/render/drm_format_set.c new file mode 100644 index 00000000..df683b6d --- /dev/null +++ b/render/drm_format_set.c @@ -0,0 +1,105 @@ +#include <drm_fourcc.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wlr/render/drm_format_set.h> +#include <wlr/util/log.h> + +void wlr_drm_format_set_finish(struct wlr_drm_format_set *set) { + for (size_t i = 0; i < set->len; ++i) { + free(set->formats[i]); + } + free(set->formats); + + set->len = 0; + set->cap = 0; + set->formats = NULL; +} + +static struct wlr_drm_format **format_set_get_ref(struct wlr_drm_format_set *set, + uint32_t format) { + for (size_t i = 0; i < set->len; ++i) { + if (set->formats[i]->format == format) { + return &set->formats[i]; + } + } + + return NULL; +} + +const struct wlr_drm_format *wlr_drm_format_set_get( + const struct wlr_drm_format_set *set, uint32_t format) { + struct wlr_drm_format **ptr = + format_set_get_ref((struct wlr_drm_format_set *)set, format); + return ptr ? *ptr : NULL; +} + +bool wlr_drm_format_set_add(struct wlr_drm_format_set *set, uint32_t format, + uint64_t modifier) { + struct wlr_drm_format **ptr = format_set_get_ref(set, format); + + if (ptr) { + struct wlr_drm_format *fmt = *ptr; + + if (modifier == DRM_FORMAT_MOD_INVALID) { + return true; + } + + for (size_t i = 0; i < fmt->len; ++i) { + if (fmt->modifiers[i] == modifier) { + return true; + } + } + + if (fmt->len == fmt->cap) { + size_t cap = fmt->cap ? fmt->cap * 2 : 4; + + fmt = realloc(fmt, sizeof(*fmt) + sizeof(fmt->modifiers[0]) * cap); + if (!fmt) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + return false; + } + + fmt->cap = cap; + *ptr = fmt; + } + + fmt->modifiers[fmt->len++] = modifier; + return true; + } + + size_t cap = modifier != DRM_FORMAT_MOD_INVALID ? 4 : 0; + + struct wlr_drm_format *fmt = + calloc(1, sizeof(*fmt) + sizeof(fmt->modifiers[0]) * cap); + if (!fmt) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + return false; + } + + fmt->format = format; + if (cap) { + fmt->cap = cap; + fmt->len = 1; + fmt->modifiers[0] = modifier; + } + + if (set->len == set->cap) { + size_t new = set->cap ? set->cap * 2 : 4; + + struct wlr_drm_format **tmp = realloc(set->formats, + sizeof(*fmt) + sizeof(fmt->modifiers[0]) * new); + if (!tmp) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + free(fmt); + return false; + } + + set->cap = new; + set->formats = tmp; + } + + set->formats[set->len++] = fmt; + return true; +} 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 <assert.h> -#include <drm_fourcc.h> #include <EGL/egl.h> #include <EGL/eglext.h> +#include <assert.h> +#include <drm_fourcc.h> #include <stdio.h> #include <stdlib.h> #include <wlr/render/egl.h> @@ -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/meson.build b/render/meson.build index e45ea90b..3f6bfdca 100644 --- a/render/meson.build +++ b/render/meson.build @@ -12,6 +12,7 @@ lib_wlr_render = static_library( files( 'dmabuf.c', 'egl.c', + 'drm_format_set.c', 'gles2/pixel_format.c', 'gles2/renderer.c', 'gles2/shaders.c', @@ -27,7 +28,7 @@ lib_wlr_render = static_library( drm.partial_dependency(compile_args: true), # <drm_fourcc.h> glesv2, pixman, - wayland_server + wayland_server, ], ) 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, |