From c01b81c99c9e7d6418611bab4fd709c4c2a8b3d9 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Mon, 1 Apr 2019 19:15:56 +0300 Subject: [PATCH] render: introduce wlr_drm_format_set This types adds a container for formats + modifiers. A list that is of [format [modifier]] was chosen instead of [format modifer] because that is how GBM accepts them. Co-Authored-By: emersion --- include/wlr/render/drm_format_set.h | 27 +++++++ include/wlr/render/meson.build | 3 +- render/drm_format_set.c | 105 ++++++++++++++++++++++++++++ render/meson.build | 3 +- 4 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 include/wlr/render/drm_format_set.h create mode 100644 render/drm_format_set.c diff --git a/include/wlr/render/drm_format_set.h b/include/wlr/render/drm_format_set.h new file mode 100644 index 00000000..588914ae --- /dev/null +++ b/include/wlr/render/drm_format_set.h @@ -0,0 +1,27 @@ +#ifndef WLR_RENDER_DRM_FORMAT_SET_H +#define WLR_RENDER_DRM_FORMAT_SET_H + +#include +#include +#include + +struct wlr_drm_format { + uint32_t format; + size_t len, cap; + uint64_t modifiers[]; +}; + +struct wlr_drm_format_set { + size_t len, cap; + struct wlr_drm_format **formats; +}; + +void wlr_drm_format_set_finish(struct wlr_drm_format_set *set); + +const struct wlr_drm_format *wlr_drm_format_set_get( + const struct wlr_drm_format_set *set, uint32_t format); + +bool wlr_drm_format_set_add(struct wlr_drm_format_set *set, uint32_t format, + uint64_t modifier); + +#endif diff --git a/include/wlr/render/meson.build b/include/wlr/render/meson.build index 05127bb7..06ebcc37 100644 --- a/include/wlr/render/meson.build +++ b/include/wlr/render/meson.build @@ -1,9 +1,10 @@ install_headers( 'dmabuf.h', 'egl.h', + 'drm_format_set.h', 'gles2.h', 'interface.h', 'wlr_renderer.h', 'wlr_texture.h', - subdir: 'wlr/render' + subdir: 'wlr/render', ) 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 +#include +#include +#include +#include +#include +#include + +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/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), # glesv2, pixman, - wayland_server + wayland_server, ], )