aboutsummaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/drm_format_set.c105
-rw-r--r--render/egl.c76
-rw-r--r--render/gles2/renderer.c13
-rw-r--r--render/meson.build3
-rw-r--r--render/wlr_renderer.c16
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,